commit some work and rename
authorLennart Poettering <lennart@poettering.net>
Mon, 14 Jun 2004 22:47:12 +0000 (22:47 +0000)
committerLennart Poettering <lennart@poettering.net>
Mon, 14 Jun 2004 22:47:12 +0000 (22:47 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@13 fefdeb5f-60dc-0310-8127-8f9354f1896f

src/Makefile.am
src/mainloop.c
src/mainloop.h
src/module-oss.c [new file with mode: 0644]
src/module-simple-protocol-tcp.c [moved from src/protocol-simple-tcp.c with 100% similarity]
src/pstream.c
src/sink-pipe.c

index 485513d..d249964 100644 (file)
@@ -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
index 2992673..37dbdb1 100644 (file)
@@ -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;
index 3c6d7e3..3fe26fd 100644 (file)
@@ -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 (file)
index 0000000..b2b106b
--- /dev/null
@@ -0,0 +1,234 @@
+#include <soundcard.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+
+#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);
+}
index 083ebc2..0336d16 100644 (file)
@@ -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();
index 78ea7bf..e63a7a8 100644 (file)
@@ -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);
 }