diff options
-rw-r--r-- | doc/todo | 3 | ||||
-rw-r--r-- | polyp/Makefile.am | 5 | ||||
-rw-r--r-- | polyp/memblockq.c | 2 | ||||
-rw-r--r-- | polyp/module-pipe-sink.c | 2 | ||||
-rw-r--r-- | polyp/module-pipe-source.c | 202 | ||||
-rw-r--r-- | polyp/pacat.c | 11 | ||||
-rwxr-xr-x | polyp/polypaudio.pa | 11 | ||||
-rw-r--r-- | polyp/protocol-native.c | 8 |
8 files changed, 233 insertions, 11 deletions
@@ -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 335fa99a..27ada2e1 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 0bba6581..a79814be 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 5f1ced03..a5a7877f 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 00000000..baed06a5 --- /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 <config.h> +#endif + +#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 "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 fd6e90e1..40301be8 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 a31712f5..87b4114a 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 4c99d5fe..67352b3f 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; |