From f78e9b68cbc45015af05db497d1547c0e02d2751 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Jun 2004 22:47:12 +0000 Subject: [PATCH] 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 +++++++++++++++++++++ ...l-simple-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 485513d..d249964 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 2992673..37dbdb1 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 3c6d7e3..3fe26fd 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 0000000..b2b106b --- /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 083ebc2..0336d16 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 78ea7bf..e63a7a8 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); } -- 2.7.4