From 7dfeb1fc745757f1c2b7bf43bae80cf0f49fc9a6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Jun 2004 21:30:16 +0000 Subject: 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 c64babb3..485513df 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 -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 +libsocket_server_la_SOURCES = socket-server.c +libsocket_server_la_LDFLAGS = -avoid-version +libsocket_server_la_LIBADD = libiochannel.la -sink_pipe_la_SOURCES = sink-pipe.c -sink_pipe_la_LDFLAGS = -module -avoid-version +libpstream_la_SOURCES = pstream.c +libpstream_la_LDFLAGS = -avoid-version +libpstream_la_LIBADD = libpacket.la -pstream_la_SOURCES = pstream.c -pstream_la_LDFLAGS = -module -avoid-version +libiochannel_la_SOURCES = iochannel.c +libiochannel_la_LDFLAGS = -avoid-version -iochannel_la_SOURCES = pstream.c -iochannel_la_LDFLAGS = -module -avoid-version +libpacket_la_SOURCES = packet.c +libpacket_la_LDFLAGS = -avoid-version -packet_la_SOURCES = pstream.c -packet_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 = 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 diff --git a/src/idxset.c b/src/idxset.c index eaea34f4..f0d7ad87 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 db9717a9..aa7de714 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 0785b39c..436dd30b 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 d043ce90..0f5811f2 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 72376c72..3c6d7e37 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 4aa9fd68..62204e4c 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 d16c25cd..98082194 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 4a8348f8..78ea7bf2 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 ac387c78..0e68cf8b 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); - 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); + idxset_free(s->input_streams, NULL, NULL); + idxset_remove_by_data(s->core->sinks, s, NULL); + source_free(s->monitor_source); + free(s->name); free(s); } diff --git a/src/source.c b/src/source.c index 2f34c461..98df2447 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); } -- cgit