]> code.delx.au - pulseaudio/commitdiff
make the whole stuff run and clean it self up again
authorLennart Poettering <lennart@poettering.net>
Fri, 11 Jun 2004 21:30:16 +0000 (21:30 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 11 Jun 2004 21:30:16 +0000 (21:30 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@8 fefdeb5f-60dc-0310-8127-8f9354f1896f

src/Makefile.am
src/idxset.c
src/iochannel.c
src/main.c
src/mainloop.c
src/mainloop.h
src/module.c
src/module.h
src/sink-pipe.c
src/sink.c
src/source.c

index c64babb3962cc8a2ee2fcd8d00fe07b770752cdc..485513df9bfbf6321825ebad25b85780940f018c 100644 (file)
@@ -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
index eaea34f46d9dfcb0d3fe3d049b82793dac3e162b..f0d7ad879522d519cfbce55ce7eca90d8360cc19 100644 (file)
@@ -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;
index db9717a96a33d3687c5881cffddb6a1b5ed93bd5..aa7de714e4e8df0aa43eee547b7f5c2d7cf52b84 100644 (file)
@@ -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;
+}
index 0785b39c6f5d0ffb545e965073fdfb4da9a21ec4..436dd30bacc9a6910469c8950081b0877636e985 100644 (file)
@@ -1,3 +1,5 @@
+#include <stdio.h>
+#include <signal.h>
 #include <stddef.h>
 #include <assert.h>
 #include <ltdl.h>
@@ -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);
     
index d043ce90aac882eca18cca6a311f16d6f2885b08..0f5811f2fd22970142e6f5e76f0fe04bacb4b8d3 100644 (file)
@@ -1,7 +1,11 @@
+#include <signal.h>
+#include <unistd.h>
 #include <sys/poll.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #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) {
index 72376c727036f85fb66965e17953d4bf90b08cf5..3c6d7e37cf79e81a23ba99388b9554968120b693 100644 (file)
@@ -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);
index 4aa9fd68184d3cd4595538f96ea96a2179eb2878..62204e4c27b01cc128dfa8b19ca0c768031f72c0 100644 (file)
@@ -3,66 +3,10 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
+#include <errno.h>
 
 #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);
index d16c25cda456773c5d0f7d2292379b01ff8f4862..980821945be9e41e7f8dc33f29df3499053bbeb6 100644 (file)
@@ -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);
index 4a8348f8ca849a376f07b9063c8a3ab8530f3924..78ea7bf2a37249fb0b6f7b91c83ef3acdc9f26a5 100644 (file)
@@ -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;
     }
index ac387c78ca44727f67c79e306585515f34672271..0e68cf8b2def12ac8f6b8517d6d9fba1f1d6bf14 100644 (file)
@@ -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);
 }
index 2f34c461e22c266a8ed30e1ae011333afc8429cb..98df2447b5da76886f974ab8430af6f91e738d31 100644 (file)
@@ -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);
 }