From e205b25d65ccb380fa158711e24d55b6de5d9bc1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 16 Feb 2006 19:19:58 +0000 Subject: Reorganised the source tree. We now have src/ with a couple of subdirs: * daemon/ - Contains the files specific to the polypaudio daemon. * modules/ - All loadable modules. * polyp/ - Files that are part of the public, application interface or are only used in libpolyp. * polypcore/ - All other shared files. * tests/ - Test programs. * utils/ - Utility programs. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@487 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/esdcompat.sh.in | 98 ++++++ src/utils/pabrowse.c | 139 ++++++++ src/utils/pacat.c | 541 ++++++++++++++++++++++++++++++++ src/utils/pacmd.c | 183 +++++++++++ src/utils/pactl.c | 784 ++++++++++++++++++++++++++++++++++++++++++++++ src/utils/paplay.c | 386 +++++++++++++++++++++++ src/utils/pax11publish.c | 217 +++++++++++++ 7 files changed, 2348 insertions(+) create mode 100755 src/utils/esdcompat.sh.in create mode 100644 src/utils/pabrowse.c create mode 100644 src/utils/pacat.c create mode 100644 src/utils/pacmd.c create mode 100644 src/utils/pactl.c create mode 100644 src/utils/paplay.c create mode 100644 src/utils/pax11publish.c (limited to 'src/utils') diff --git a/src/utils/esdcompat.sh.in b/src/utils/esdcompat.sh.in new file mode 100755 index 00000000..76023f52 --- /dev/null +++ b/src/utils/esdcompat.sh.in @@ -0,0 +1,98 @@ +#!/bin/sh + +# $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 Lesser 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 Lesser 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. + +VERSION_STRING="@PACKAGE_NAME@ esd wrapper @PACKAGE_VERSION@" + +fail() { + echo "ERROR: $1" + exit 1 +} + +ARGS=" --log-target=syslog" + +for N in $(seq $#) ; do + + case "$1" in + "") + ;; + + -v|--version) + echo "$VERSION_STRING" + exit 0 + ;; + + -h|--help) + cat < +#endif + +#include +#include +#include + +#include +#include +#include +#include + +static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, "Got signal, exiting\n"); + m->quit(m, 0); +} + +static void dump_server(const pa_browse_info *i) { + char t[16]; + + if (i->cookie) + snprintf(t, sizeof(t), "0x%08x", *i->cookie); + + printf("server: %s\n" + "server-version: %s\n" + "user-name: %s\n" + "fqdn: %s\n" + "cookie: %s\n", + i->server, + i->server_version ? i->server_version : "n/a", + i->user_name ? i->user_name : "n/a", + i->fqdn ? i->fqdn : "n/a", + i->cookie ? t : "n/a"); +} + +static void dump_device(const pa_browse_info *i) { + char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (i->sample_spec) + pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec); + + if (i->typeid) + pa_typeid_to_string(*i->typeid, t, sizeof(t)); + + printf("device: %s\n" + "description: %s\n" + "type: %s\n" + "sample spec: %s\n", + i->device, + i->description ? i->description : "n/a", + i->typeid ? t : "n/a", + i->sample_spec ? ss : "n/a"); + +} + +static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_info *i, void *userdata) { + assert(b && i); + + switch (c) { + + case PA_BROWSE_NEW_SERVER: + printf("\n=> new server <%s>\n", i->name); + dump_server(i); + break; + + case PA_BROWSE_NEW_SINK: + printf("\n=> new sink <%s>\n", i->name); + dump_server(i); + dump_device(i); + break; + + case PA_BROWSE_NEW_SOURCE: + printf("\n=> new source <%s>\n", i->name); + dump_server(i); + dump_device(i); + break; + + case PA_BROWSE_REMOVE: + printf("\n=> removed service <%s>\n", i->name); + break; + + default: + ; + } +} + + +int main(int argc, char *argv[]) { + pa_mainloop *mainloop = NULL; + pa_browser *browser = NULL; + int ret = 1, r; + + if (!(mainloop = pa_mainloop_new())) + goto finish; + + r = pa_signal_init(pa_mainloop_get_api(mainloop)); + assert(r == 0); + pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGTERM, exit_signal_callback, NULL); + signal(SIGPIPE, SIG_IGN); + + if (!(browser = pa_browser_new(pa_mainloop_get_api(mainloop)))) + goto finish; + + pa_browser_set_callback(browser, browser_callback, NULL); + + ret = 0; + pa_mainloop_run(mainloop, &ret); + +finish: + if (mainloop) { + pa_signal_done(); + pa_mainloop_free(mainloop); + } + + return ret; +} diff --git a/src/utils/pacat.c b/src/utils/pacat.c new file mode 100644 index 00000000..bd2b64fd --- /dev/null +++ b/src/utils/pacat.c @@ -0,0 +1,541 @@ +/* $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 Lesser 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 Lesser 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if PA_API_VERSION != 8 +#error Invalid Polypaudio API version +#endif + +static enum { RECORD, PLAYBACK } mode = PLAYBACK; + +static pa_context *context = NULL; +static pa_stream *stream = NULL; +static pa_mainloop_api *mainloop_api = NULL; + +static void *buffer = NULL; +static size_t buffer_length = 0, buffer_index = 0; + +static pa_io_event* stdio_event = NULL; + +static char *stream_name = NULL, *client_name = NULL, *device = NULL; + +static int verbose = 0; +static pa_volume_t volume = PA_VOLUME_NORM; + +static pa_sample_spec sample_spec = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 2 +}; + +/* A shortcut for terminating the application */ +static void quit(int ret) { + assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + +/* Write some data to the stream */ +static void do_stream_write(size_t length) { + size_t l; + assert(length); + + if (!buffer || !buffer_length) + return; + + l = length; + if (l > buffer_length) + l = buffer_length; + + pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0); + buffer_length -= l; + buffer_index += l; + + if (!buffer_length) { + free(buffer); + buffer = NULL; + buffer_index = buffer_length = 0; + } +} + +/* This is called whenever new data may be written to the stream */ +static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { + assert(s && length); + + if (stdio_event) + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); + + if (!buffer) + return; + + do_stream_write(length); +} + +/* This is called whenever new data may is available */ +static void stream_read_callback(pa_stream *s, const void*data, size_t length, void *userdata) { + assert(s && data && length); + + if (stdio_event) + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); + + if (buffer) { + fprintf(stderr, "Buffer overrun, dropping incoming data\n"); + return; + } + + buffer = malloc(buffer_length = length); + assert(buffer); + memcpy(buffer, data, length); + buffer_index = 0; +} + +/* This routine is called whenever the stream state changes */ +static void stream_state_callback(pa_stream *s, void *userdata) { + assert(s); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_TERMINATED: + break; + + case PA_STREAM_READY: + if (verbose) + fprintf(stderr, "Stream successfully created\n"); + break; + + case PA_STREAM_FAILED: + default: + fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); + } +} + +/* This is called whenever the context status changes */ +static void context_state_callback(pa_context *c, void *userdata) { + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + + assert(c && !stream); + + if (verbose) + fprintf(stderr, "Connection established.\n"); + + stream = pa_stream_new(c, stream_name, &sample_spec, NULL); + assert(stream); + + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_write_callback(stream, stream_write_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); + + if (mode == PLAYBACK) { + pa_cvolume cv; + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + } else + pa_stream_connect_record(stream, device, NULL, 0); + + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + } +} + +/* Connection draining complete */ +static void context_drain_complete(pa_context*c, void *userdata) { + pa_context_disconnect(c); +} + +/* Stream draining complete */ +static void stream_drain_complete(pa_stream*s, int success, void *userdata) { + pa_operation *o; + + if (!success) { + fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } + + if (verbose) + fprintf(stderr, "Playback stream drained.\n"); + + pa_stream_disconnect(stream); + pa_stream_unref(stream); + stream = NULL; + + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else { + pa_operation_unref(o); + + if (verbose) + fprintf(stderr, "Draining connection to server.\n"); + } +} + +/* New data on STDIN **/ +static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { + size_t l, w = 0; + ssize_t r; + assert(a == mainloop_api && e && stdio_event == e); + + if (buffer) { + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); + return; + } + + if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) + l = 4096; + + buffer = malloc(l); + assert(buffer); + if ((r = read(fd, buffer, l)) <= 0) { + if (r == 0) { + if (verbose) + fprintf(stderr, "Got EOF.\n"); + pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL)); + } else { + fprintf(stderr, "read() failed: %s\n", strerror(errno)); + quit(1); + } + + mainloop_api->io_free(stdio_event); + stdio_event = NULL; + return; + } + + buffer_length = r; + buffer_index = 0; + + if (w) + do_stream_write(w); +} + +/* Some data may be written to STDOUT */ +static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { + ssize_t r; + assert(a == mainloop_api && e && stdio_event == e); + + if (!buffer) { + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); + return; + } + + assert(buffer_length); + + if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) { + fprintf(stderr, "write() failed: %s\n", strerror(errno)); + quit(1); + + mainloop_api->io_free(stdio_event); + stdio_event = NULL; + return; + } + + buffer_length -= r; + buffer_index += r; + + if (!buffer_length) { + free(buffer); + buffer = NULL; + buffer_length = buffer_index = 0; + } +} + +/* UNIX signal to quit recieved */ +static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { + if (verbose) + fprintf(stderr, "Got signal, exiting.\n"); + quit(0); + +} + +/* Show the current latency */ +static void stream_get_latency_callback(pa_stream *s, const pa_latency_info *i, void *userdata) { + pa_usec_t total; + int negative = 0; + assert(s); + + if (!i) { + fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + + total = pa_stream_get_latency(s, i, &negative); + + fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", + (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, (float) total * (negative?-1:1), + i->synchronized_clocks ? "yes" : "no"); +} + +/* Someone requested that the latency is shown */ +static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); + pa_operation_unref(pa_stream_get_latency_info(stream, stream_get_latency_callback, NULL)); +} + + +static void help(const char *argv0) { + + printf("%s [options]\n\n" + " -h, --help Show this help\n" + " --version Show version\n\n" + " -r, --record Create a connection for recording\n" + " -p, --playback Create a connection for playback\n\n" + " -v, --verbose Enable verbose operations\n\n" + " -s, --server=SERVER The name of the server to connect to\n" + " -d, --device=DEVICE The name of the sink/source to connect to\n" + " -n, --client-name=NAME How to call this client on the server\n" + " --stream-name=NAME How to call this stream on the server\n" + " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n" + " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" + " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" + " float32be, ulaw, alaw (defaults to s16ne)\n" + " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" + " (defaults to 2)\n", + argv0); +} + +enum { + ARG_VERSION = 256, + ARG_STREAM_NAME, + ARG_VOLUME, + ARG_SAMPLERATE, + ARG_SAMPLEFORMAT, + ARG_CHANNELS +}; + +int main(int argc, char *argv[]) { + pa_mainloop* m = NULL; + int ret = 1, r, c; + char *bn, *server = NULL; + + static const struct option long_options[] = { + {"record", 0, NULL, 'r'}, + {"playback", 0, NULL, 'p'}, + {"device", 1, NULL, 'd'}, + {"server", 1, NULL, 's'}, + {"client-name", 1, NULL, 'n'}, + {"stream-name", 1, NULL, ARG_STREAM_NAME}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"volume", 1, NULL, ARG_VOLUME}, + {"rate", 1, NULL, ARG_SAMPLERATE}, + {"format", 1, NULL, ARG_SAMPLEFORMAT}, + {"channels", 1, NULL, ARG_CHANNELS}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + if (strstr(bn, "rec") || strstr(bn, "mon")) + mode = RECORD; + else if (strstr(bn, "cat") || strstr(bn, "play")) + mode = PLAYBACK; + + while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) { + + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("pacat "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 'r': + mode = RECORD; + break; + + case 'p': + mode = PLAYBACK; + break; + + case 'd': + free(device); + device = strdup(optarg); + break; + + case 's': + free(server); + server = strdup(optarg); + break; + + case 'n': + free(client_name); + client_name = strdup(optarg); + break; + + case ARG_STREAM_NAME: + free(stream_name); + stream_name = strdup(optarg); + break; + + case 'v': + verbose = 1; + break; + + case ARG_VOLUME: { + int v = atoi(optarg); + volume = v < 0 ? 0 : v; + break; + } + + case ARG_CHANNELS: + sample_spec.channels = atoi(optarg); + break; + + case ARG_SAMPLEFORMAT: + sample_spec.format = pa_parse_sample_format(optarg); + break; + + case ARG_SAMPLERATE: + sample_spec.rate = atoi(optarg); + break; + + default: + goto quit; + } + } + + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) + stream_name = strdup(client_name); + + if (!pa_sample_spec_valid(&sample_spec)) { + fprintf(stderr, "Invalid sample specification\n"); + goto quit; + } + + if (verbose) { + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + pa_sample_spec_snprint(t, sizeof(t), &sample_spec); + fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); + } + + /* Set up a new main loop */ + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + mainloop_api = pa_mainloop_get_api(m); + + r = pa_signal_init(mainloop_api); + assert(r == 0); + pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGTERM, exit_signal_callback, NULL); +#ifdef SIGUSR1 + pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); +#endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + if (!(stdio_event = mainloop_api->io_new(mainloop_api, + mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, + mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, + mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { + fprintf(stderr, "source_io() failed.\n"); + goto quit; + } + + /* Create a new connection context */ + if (!(context = pa_context_new(mainloop_api, client_name))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + pa_context_set_state_callback(context, context_state_callback, NULL); + + /* Connect the context */ + pa_context_connect(context, server, 1, NULL); + + /* Run the main loop */ + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (stream) + pa_stream_unref(stream); + + if (context) + pa_context_unref(context); + + if (stdio_event) { + assert(mainloop_api); + mainloop_api->io_free(stdio_event); + } + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + free(buffer); + + free(server); + free(device); + free(client_name); + free(stream_name); + + return ret; +} diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c new file mode 100644 index 00000000..4054bc2c --- /dev/null +++ b/src/utils/pacmd.c @@ -0,0 +1,183 @@ +/* $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 Lesser 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 Lesser 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { + pid_t pid ; + int fd = -1; + int ret = 1, i; + struct sockaddr_un sa; + char ibuf[256], obuf[256]; + size_t ibuf_index, ibuf_length, obuf_index, obuf_length; + fd_set ifds, ofds; + + if (pa_pid_file_check_running(&pid) < 0) { + pa_log(__FILE__": no Polypaudio daemon running\n"); + goto fail; + } + + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s\n", strerror(errno)); + goto fail; + } + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + pa_runtime_path("cli", sa.sun_path, sizeof(sa.sun_path)); + + for (i = 0; i < 5; i++) { + int r; + + if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { + pa_log(__FILE__": connect() failed: %s\n", strerror(errno)); + goto fail; + } + + if (r >= 0) + break; + + if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { + pa_log(__FILE__": failed to kill Polypaudio daemon.\n"); + goto fail; + } + + pa_msleep(50); + } + + if (i >= 5) { + pa_log(__FILE__": daemon not responding.\n"); + goto fail; + } + + ibuf_index = ibuf_length = obuf_index = obuf_length = 0; + + + FD_ZERO(&ifds); + FD_SET(0, &ifds); + FD_SET(fd, &ifds); + + FD_ZERO(&ofds); + + for (;;) { + if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { + pa_log(__FILE__": select() failed: %s\n", strerror(errno)); + goto fail; + } + + if (FD_ISSET(0, &ifds)) { + ssize_t r; + assert(!ibuf_length); + + if ((r = read(0, ibuf, sizeof(ibuf))) <= 0) { + if (r == 0) + break; + + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + goto fail; + } + + ibuf_length = (size_t) r; + ibuf_index = 0; + } + + if (FD_ISSET(fd, &ifds)) { + ssize_t r; + assert(!obuf_length); + + if ((r = read(fd, obuf, sizeof(obuf))) <= 0) { + if (r == 0) + break; + + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + goto fail; + } + + obuf_length = (size_t) r; + obuf_index = 0; + } + + if (FD_ISSET(1, &ofds)) { + ssize_t r; + assert(obuf_length); + + if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + goto fail; + } + + obuf_length -= (size_t) r; + obuf_index += obuf_index; + + } + + if (FD_ISSET(fd, &ofds)) { + ssize_t r; + assert(ibuf_length); + + if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + goto fail; + } + + ibuf_length -= (size_t) r; + ibuf_index += obuf_index; + + } + + FD_ZERO(&ifds); + FD_ZERO(&ofds); + + if (obuf_length <= 0) + FD_SET(fd, &ifds); + else + FD_SET(1, &ofds); + + if (ibuf_length <= 0) + FD_SET(0, &ifds); + else + FD_SET(fd, &ofds); + } + + + ret = 0; + +fail: + if (fd >= 0) + close(fd); + + return ret; +} diff --git a/src/utils/pactl.c b/src/utils/pactl.c new file mode 100644 index 00000000..23bd924b --- /dev/null +++ b/src/utils/pactl.c @@ -0,0 +1,784 @@ +/* $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 Lesser 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 Lesser 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#if PA_API_VERSION != 8 +#error Invalid Polypaudio API version +#endif + +#define BUFSIZE 1024 + +static pa_context *context = NULL; +static pa_mainloop_api *mainloop_api = NULL; + +static char *device = NULL, *sample_name = NULL; + +static SNDFILE *sndfile = NULL; +static pa_stream *sample_stream = NULL; +static pa_sample_spec sample_spec; +static size_t sample_length = 0; + +static int actions = 1; + +static int nl = 0; + +static enum { + NONE, + EXIT, + STAT, + UPLOAD_SAMPLE, + PLAY_SAMPLE, + REMOVE_SAMPLE, + LIST +} action = NONE; + +static void quit(int ret) { + assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + + +static void context_drain_complete(pa_context *c, void *userdata) { + pa_context_disconnect(c); +} + +static void drain(void) { + pa_operation *o; + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else + pa_operation_unref(o); +} + + +static void complete_action(void) { + assert(actions > 0); + + if (!(--actions)) + drain(); +} + +static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) { + char s[128]; + if (!i) { + fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + pa_bytes_snprint(s, sizeof(s), i->memblock_total_size); + printf("Currently in use: %u blocks containing %s bytes total.\n", i->memblock_total, s); + + pa_bytes_snprint(s, sizeof(s), i->memblock_allocated_size); + printf("Allocated during whole lifetime: %u blocks containing %s bytes total.\n", i->memblock_allocated, s); + + pa_bytes_snprint(s, sizeof(s), i->scache_size); + printf("Sample cache size: %s\n", s); + + complete_action(); +} + +static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) { + char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (!i) { + fprintf(stderr, "Failed to get server information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + + printf("User name: %s\n" + "Host Name: %s\n" + "Server Name: %s\n" + "Server Version: %s\n" + "Default Sample Specification: %s\n" + "Default Sink: %s\n" + "Default Source: %s\n" + "Cookie: %08x\n", + i->user_name, + i->host_name, + i->server_name, + i->server_version, + s, + i->default_sink_name, + i->default_source_name, + i->cookie); + + complete_action(); +} + +static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) { + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + printf("*** Sink #%u ***\n" + "Name: %s\n" + "Driver: %s\n" + "Description: %s\n" + "Sample Specification: %s\n" + "Channel Map: %s\n" + "Owner Module: %u\n" + "Volume: %s\n" + "Monitor Source: %u\n" + "Latency: %0.0f usec\n", + i->index, + i->name, + i->driver, + i->description, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + i->owner_module, + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + i->monitor_source, + (double) i->latency); + +} + +static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) { + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->monitor_of_sink); + + printf("*** Source #%u ***\n" + "Name: %s\n" + "Driver: %s\n" + "Description: %s\n" + "Sample Specification: %s\n" + "Channel Map: %s\n" + "Owner Module: %u\n" + "Monitor of Sink: %s\n" + "Latency: %0.0f usec\n", + i->index, + i->driver, + i->name, + i->description, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + i->owner_module, + i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", + (double) i->latency); + +} + +static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) { + char t[32]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get module information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->n_used); + + printf("*** Module #%u ***\n" + "Name: %s\n" + "Argument: %s\n" + "Usage counter: %s\n" + "Auto unload: %s\n", + i->index, + i->name, + i->argument, + i->n_used != PA_INVALID_INDEX ? t : "n/a", + i->auto_unload ? "yes" : "no"); +} + +static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) { + char t[32]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->owner_module); + + printf("*** Client #%u ***\n" + "Name: %s\n" + "Driver: %s\n" + "Owner Module: %s\n", + i->index, + i->name, + i->driver, + i->owner_module != PA_INVALID_INDEX ? t : "n/a"); +} + +static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) { + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->owner_module); + snprintf(k, sizeof(k), "%u", i->client); + + printf("*** Sink Input #%u ***\n" + "Name: %s\n" + "Driver: %s\n" + "Owner Module: %s\n" + "Client: %s\n" + "Sink: %u\n" + "Sample Specification: %s\n" + "Channel Map: %s\n" + "Volume: %s\n" + "Buffer Latency: %0.0f usec\n" + "Sink Latency: %0.0f usec\n" + "Resample method: %s\n", + i->index, + i->name, + i->driver, + i->owner_module != PA_INVALID_INDEX ? t : "n/a", + i->client != PA_INVALID_INDEX ? k : "n/a", + i->sink, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + (double) i->buffer_usec, + (double) i->sink_usec, + i->resample_method ? i->resample_method : "n/a"); +} + + +static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) { + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + + snprintf(t, sizeof(t), "%u", i->owner_module); + snprintf(k, sizeof(k), "%u", i->client); + + printf("*** Source Output #%u ***\n" + "Name: %s\n" + "Driver: %s\n" + "Owner Module: %s\n" + "Client: %s\n" + "Source: %u\n" + "Sample Specification: %s\n" + "Channel Map: %s\n" + "Buffer Latency: %0.0f usec\n" + "Source Latency: %0.0f usec\n" + "Resample method: %s\n", + i->index, + i->name, + i->driver, + i->owner_module != PA_INVALID_INDEX ? t : "n/a", + i->client != PA_INVALID_INDEX ? k : "n/a", + i->source, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + (double) i->buffer_usec, + (double) i->source_usec, + i->resample_method ? i->resample_method : "n/a"); +} + +static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) { + char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get sample information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + + pa_bytes_snprint(t, sizeof(t), i->bytes); + + printf("*** Sample #%u ***\n" + "Name: %s\n" + "Volume: %s\n" + "Sample Specification: %s\n" + "Channel Map: %s\n" + "Duration: %0.1fs\n" + "Size: %s\n" + "Lazy: %s\n" + "Filename: %s\n", + i->index, + i->name, + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : "n/a", + pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : "n/a", + (double) i->duration/1000000, + t, + i->lazy ? "yes" : "no", + i->filename ? i->filename : "n/a"); +} + +static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata) { + if (is_last < 0) { + fprintf(stderr, "Failed to get autoload information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + printf("*** Autoload Entry #%u ***\n" + "Name: %s\n" + "Type: %s\n" + "Module: %s\n" + "Argument: %s\n", + i->index, + i->name, + i->type == PA_AUTOLOAD_SINK ? "sink" : "source", + i->module, + i->argument); +} + +static void simple_callback(pa_context *c, int success, void *userdata) { + if (!success) { + fprintf(stderr, "Failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + complete_action(); +} + +static void stream_state_callback(pa_stream *s, void *userdata) { + assert(s); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_READY: + break; + + case PA_STREAM_TERMINATED: + drain(); + break; + + case PA_STREAM_FAILED: + default: + fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); + } +} + +static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { + sf_count_t l; + float *d; + assert(s && length && sndfile); + + d = malloc(length); + assert(d); + + assert(sample_length >= length); + l = length/pa_frame_size(&sample_spec); + + if ((sf_readf_float(sndfile, d, l)) != l) { + free(d); + fprintf(stderr, "Premature end of file\n"); + quit(1); + } + + pa_stream_write(s, d, length, free, 0); + + sample_length -= length; + + if (sample_length <= 0) { + pa_stream_set_write_callback(sample_stream, NULL, NULL); + pa_stream_finish_upload(sample_stream); + } +} + +static void context_state_callback(pa_context *c, void *userdata) { + assert(c); + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + switch (action) { + case STAT: + actions = 2; + pa_operation_unref(pa_context_stat(c, stat_callback, NULL)); + pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL)); + break; + + case PLAY_SAMPLE: + pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL)); + break; + + case REMOVE_SAMPLE: + pa_operation_unref(pa_context_remove_sample(c, sample_name, simple_callback, NULL)); + break; + + case UPLOAD_SAMPLE: + sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL); + assert(sample_stream); + + pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); + pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); + pa_stream_connect_upload(sample_stream, sample_length); + break; + + case EXIT: + pa_context_exit_daemon(c); + drain(); + + case LIST: + actions = 8; + pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL)); + pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL)); + pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL)); + pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL)); + pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL)); + pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL)); + pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL)); + pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL)); + break; + + default: + assert(0); + } + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + } +} + +static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); +} + +static void help(const char *argv0) { + + printf("%s [options] stat\n" + "%s [options] list\n" + "%s [options] exit\n" + "%s [options] upload-sample FILENAME [NAME]\n" + "%s [options] play-sample NAME [SINK]\n" + "%s [options] remove-sample NAME\n\n" + " -h, --help Show this help\n" + " --version Show version\n\n" + " -s, --server=SERVER The name of the server to connect to\n" + " -n, --client-name=NAME How to call this client on the server\n", + argv0, argv0, argv0, argv0, argv0, argv0); +} + +enum { ARG_VERSION = 256 }; + +int main(int argc, char *argv[]) { + pa_mainloop* m = NULL; + char tmp[PATH_MAX]; + int ret = 1, r, c; + char *server = NULL, *client_name = NULL, *bn; + + static const struct option long_options[] = { + {"server", 1, NULL, 's'}, + {"client-name", 1, NULL, 'n'}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) { + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("pactl "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 's': + free(server); + server = strdup(optarg); + break; + + case 'n': + free(client_name); + client_name = strdup(optarg); + break; + + default: + goto quit; + } + } + + if (!client_name) + client_name = strdup(bn); + + if (optind < argc) { + if (!strcmp(argv[optind], "stat")) + action = STAT; + else if (!strcmp(argv[optind], "exit")) + action = EXIT; + else if (!strcmp(argv[optind], "list")) + action = LIST; + else if (!strcmp(argv[optind], "upload-sample")) { + struct SF_INFO sfinfo; + action = UPLOAD_SAMPLE; + + if (optind+1 >= argc) { + fprintf(stderr, "Please specify a sample file to load\n"); + goto quit; + } + + if (optind+2 < argc) + sample_name = strdup(argv[optind+2]); + else { + char *f = strrchr(argv[optind+1], '/'); + size_t n; + if (f) + f++; + else + f = argv[optind]; + + n = strcspn(f, "."); + strncpy(tmp, f, n); + tmp[n] = 0; + sample_name = strdup(tmp); + } + + memset(&sfinfo, 0, sizeof(sfinfo)); + if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfinfo))) { + fprintf(stderr, "Failed to open sound file.\n"); + goto quit; + } + + sample_spec.format = PA_SAMPLE_FLOAT32; + sample_spec.rate = sfinfo.samplerate; + sample_spec.channels = sfinfo.channels; + + sample_length = sfinfo.frames*pa_frame_size(&sample_spec); + } else if (!strcmp(argv[optind], "play-sample")) { + action = PLAY_SAMPLE; + if (optind+1 >= argc) { + fprintf(stderr, "You have to specify a sample name to play\n"); + goto quit; + } + + sample_name = strdup(argv[optind+1]); + + if (optind+2 < argc) + device = strdup(argv[optind+2]); + + } else if (!strcmp(argv[optind], "remove-sample")) { + action = REMOVE_SAMPLE; + if (optind+1 >= argc) { + fprintf(stderr, "You have to specify a sample name to remove\n"); + goto quit; + } + + sample_name = strdup(argv[optind+1]); + } + } + + if (action == NONE) { + fprintf(stderr, "No valid command specified.\n"); + goto quit; + } + + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + mainloop_api = pa_mainloop_get_api(m); + + r = pa_signal_init(mainloop_api); + assert(r == 0); + pa_signal_new(SIGINT, exit_signal_callback, NULL); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + if (!(context = pa_context_new(mainloop_api, client_name))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + pa_context_set_state_callback(context, context_state_callback, NULL); + pa_context_connect(context, server, 1, NULL); + + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (sample_stream) + pa_stream_unref(sample_stream); + + if (context) + pa_context_unref(context); + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + if (sndfile) + sf_close(sndfile); + + free(server); + free(device); + free(sample_name); + + return ret; +} diff --git a/src/utils/paplay.c b/src/utils/paplay.c new file mode 100644 index 00000000..ddc1cbc1 --- /dev/null +++ b/src/utils/paplay.c @@ -0,0 +1,386 @@ +/* $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 Lesser 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 Lesser 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#if PA_API_VERSION != 8 +#error Invalid Polypaudio API version +#endif + +static pa_context *context = NULL; +static pa_stream *stream = NULL; +static pa_mainloop_api *mainloop_api = NULL; + +static char *stream_name = NULL, *client_name = NULL, *device = NULL; + +static int verbose = 0; +static pa_volume_t volume = PA_VOLUME_NORM; + +static SNDFILE* sndfile = NULL; + +static pa_sample_spec sample_spec = { 0, 0, 0 }; + +static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames); + +/* A shortcut for terminating the application */ +static void quit(int ret) { + assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + +/* Connection draining complete */ +static void context_drain_complete(pa_context*c, void *userdata) { + pa_context_disconnect(c); +} + +/* Stream draining complete */ +static void stream_drain_complete(pa_stream*s, int success, void *userdata) { + pa_operation *o; + + if (!success) { + fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } + + if (verbose) + fprintf(stderr, "Playback stream drained.\n"); + + pa_stream_disconnect(stream); + pa_stream_unref(stream); + stream = NULL; + + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else { + pa_operation_unref(o); + + if (verbose) + fprintf(stderr, "Draining connection to server.\n"); + } +} + +/* This is called whenever new data may be written to the stream */ +static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { + size_t k; + sf_count_t f, n; + void *data; + assert(s && length); + + if (!sndfile) + return; + + k = pa_frame_size(&sample_spec); + + data = malloc(length); + + n = length/k; + + f = readf_function(sndfile, data, n); + + if (f > 0) + pa_stream_write(s, data, f*k, free, 0); + + if (f < n) { + sf_close(sndfile); + sndfile = NULL; + pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); + } +} + +/* This routine is called whenever the stream state changes */ +static void stream_state_callback(pa_stream *s, void *userdata) { + assert(s); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_TERMINATED: + break; + + case PA_STREAM_READY: + if (verbose) + fprintf(stderr, "Stream successfully created\n"); + break; + + case PA_STREAM_FAILED: + default: + fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); + } +} + +/* This is called whenever the context status changes */ +static void context_state_callback(pa_context *c, void *userdata) { + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: { + pa_cvolume cv; + + assert(c && !stream); + + if (verbose) + fprintf(stderr, "Connection established.\n"); + + stream = pa_stream_new(c, stream_name, &sample_spec, NULL); + assert(stream); + + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_write_callback(stream, stream_write_callback, NULL); + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + + break; + } + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + } +} + +/* UNIX signal to quit recieved */ +static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { + if (verbose) + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); + +} + +static void help(const char *argv0) { + + printf("%s [options] [FILE]\n\n" + " -h, --help Show this help\n" + " --version Show version\n\n" + " -v, --verbose Enable verbose operations\n\n" + " -s, --server=SERVER The name of the server to connect to\n" + " -d, --device=DEVICE The name of the sink/source to connect to\n" + " -n, --client-name=NAME How to call this client on the server\n" + " --stream-name=NAME How to call this stream on the server\n" + " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + argv0); +} + +enum { + ARG_VERSION = 256, + ARG_STREAM_NAME, + ARG_VOLUME +}; + +int main(int argc, char *argv[]) { + pa_mainloop* m = NULL; + int ret = 1, r, c; + char *bn, *server = NULL; + const char *filename; + SF_INFO sfinfo; + + static const struct option long_options[] = { + {"device", 1, NULL, 'd'}, + {"server", 1, NULL, 's'}, + {"client-name", 1, NULL, 'n'}, + {"stream-name", 1, NULL, ARG_STREAM_NAME}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"volume", 1, NULL, ARG_VOLUME}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + while ((c = getopt_long(argc, argv, "d:s:n:hv", long_options, NULL)) != -1) { + + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("paplay "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 'd': + free(device); + device = strdup(optarg); + break; + + case 's': + free(server); + server = strdup(optarg); + break; + + case 'n': + free(client_name); + client_name = strdup(optarg); + break; + + case ARG_STREAM_NAME: + free(stream_name); + stream_name = strdup(optarg); + break; + + case 'v': + verbose = 1; + break; + + case ARG_VOLUME: { + int v = atoi(optarg); + volume = v < 0 ? 0 : v; + break; + } + + default: + goto quit; + } + } + + + filename = optind < argc ? argv[optind] : "STDIN"; + + + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) + stream_name = strdup(filename); + + memset(&sfinfo, 0, sizeof(sfinfo)); + + if (optind < argc) + sndfile = sf_open(filename, SFM_READ, &sfinfo); + else + sndfile = sf_open_fd(STDIN_FILENO, SFM_READ, &sfinfo, 0); + + if (!sndfile) { + fprintf(stderr, "Failed to open file '%s'\n", filename); + goto quit; + } + + sample_spec.rate = sfinfo.samplerate; + sample_spec.channels = sfinfo.channels; + + switch (sfinfo.format & 0xFF) { + case SF_FORMAT_PCM_16: + case SF_FORMAT_PCM_U8: + case SF_FORMAT_ULAW: + case SF_FORMAT_ALAW: + sample_spec.format = PA_SAMPLE_S16NE; + readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + break; + case SF_FORMAT_FLOAT: + default: + sample_spec.format = PA_SAMPLE_FLOAT32NE; + readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + break; + } + + if (verbose) { + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + pa_sample_spec_snprint(t, sizeof(t), &sample_spec); + fprintf(stderr, "Using sample spec '%s'\n", t); + } + + /* Set up a new main loop */ + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + mainloop_api = pa_mainloop_get_api(m); + + r = pa_signal_init(mainloop_api); + assert(r == 0); + pa_signal_new(SIGINT, exit_signal_callback, NULL); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + /* Create a new connection context */ + if (!(context = pa_context_new(mainloop_api, client_name))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + pa_context_set_state_callback(context, context_state_callback, NULL); + + /* Connect the context */ + pa_context_connect(context, server, 1, NULL); + + /* Run the main loop */ + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (stream) + pa_stream_unref(stream); + + if (context) + pa_context_unref(context); + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + free(server); + free(device); + free(client_name); + free(stream_name); + + if (sndfile) + sf_close(sndfile); + + return ret; +} diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c new file mode 100644 index 00000000..63ee4821 --- /dev/null +++ b/src/utils/pax11publish.c @@ -0,0 +1,217 @@ +/* $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 Lesser 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 Lesser 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 +#endif + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; + int c, ret = 1; + Display *d = NULL; + enum { DUMP, EXPORT, IMPORT, REMOVE } mode = DUMP; + + while ((c = getopt(argc, argv, "deiD:S:O:I:c:hr")) != -1) { + switch (c) { + case 'D' : + dname = optarg; + break; + case 'h': + printf("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n\n" + " -d Show current Polypaudio data attached to X11 display (default)\n" + " -e Export local Polypaudio data to X11 display\n" + " -i Import Polypaudio data from X11 display to local environment variables and cookie file.\n" + " -r Remove Polypaudio data from X11 display\n", + pa_path_get_filename(argv[0])); + ret = 0; + goto finish; + case 'd': + mode = DUMP; + break; + case 'e': + mode = EXPORT; + break; + case 'i': + mode = IMPORT; + break; + case 'r': + mode = REMOVE; + break; + case 'c': + cookie_file = optarg; + break; + case 'I': + source = optarg; + break; + case 'O': + sink = optarg; + break; + case 'S': + server = optarg; + break; + default: + fprintf(stderr, "Failed to parse command line.\n"); + goto finish; + } + } + + if (!(d = XOpenDisplay(dname))) { + pa_log(__FILE__": XOpenDisplay() failed\n"); + goto finish; + } + + switch (mode) { + case DUMP: { + char t[1024]; + if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + printf("Server: %s\n", t); + if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) + printf("Source: %s\n", t); + if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) + printf("Sink: %s\n", t); + if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) + printf("Cookie: %s\n", t); + + break; + } + + case IMPORT: { + char t[1024]; + if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); + if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) + printf("POLYP_SOURCE='%s'\nexport POLYP_SOURCE\n", t); + if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) + printf("POLYP_SINK='%s'\nexport POLYP_SINK\n", t); + + if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + size_t l; + if ((l = pa_parsehex(t, cookie, sizeof(cookie))) != sizeof(cookie)) { + fprintf(stderr, "Failed to parse cookie data\n"); + goto finish; + } + + if (pa_authkey_save(cookie_file, cookie, l) < 0) { + fprintf(stderr, "Failed to save cookie data\n"); + goto finish; + } + } + + break; + } + + case EXPORT: { + pa_client_conf *conf = pa_client_conf_new(); + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; + assert(conf); + + if (pa_client_conf_load(conf, NULL) < 0) { + fprintf(stderr, "Failed to load client configuration file.\n"); + goto finish; + } + + if (pa_client_conf_env(conf) < 0) { + fprintf(stderr, "Failed to read environment configuration data.\n"); + goto finish; + } + + pa_x11_del_prop(d, "POLYP_SERVER"); + pa_x11_del_prop(d, "POLYP_SINK"); + pa_x11_del_prop(d, "POLYP_SOURCE"); + pa_x11_del_prop(d, "POLYP_ID"); + pa_x11_del_prop(d, "POLYP_COOKIE"); + + if (server) + pa_x11_set_prop(d, "POLYP_SERVER", server); + else if (conf->default_server) + pa_x11_set_prop(d, "POLYP_SERVER", conf->default_server); + else { + char hn[256]; + if (!pa_get_fqdn(hn, sizeof(hn))) { + fprintf(stderr, "Failed to get FQDN.\n"); + goto finish; + } + + pa_x11_set_prop(d, "POLYP_SERVER", hn); + } + + if (sink) + pa_x11_set_prop(d, "POLYP_SINK", sink); + else if (conf->default_sink) + pa_x11_set_prop(d, "POLYP_SINK", conf->default_sink); + + if (source) + pa_x11_set_prop(d, "POLYP_SOURCE", source); + if (conf->default_source) + pa_x11_set_prop(d, "POLYP_SOURCE", conf->default_source); + + pa_client_conf_free(conf); + + if (pa_authkey_load_auto(cookie_file, cookie, sizeof(cookie)) < 0) { + fprintf(stderr, "Failed to load cookie data\n"); + goto finish; + } + + pa_x11_set_prop(d, "POLYP_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); + break; + } + + case REMOVE: + pa_x11_del_prop(d, "POLYP_SERVER"); + pa_x11_del_prop(d, "POLYP_SINK"); + pa_x11_del_prop(d, "POLYP_SOURCE"); + pa_x11_del_prop(d, "POLYP_ID"); + pa_x11_del_prop(d, "POLYP_COOKIE"); + break; + + default: + fprintf(stderr, "No yet implemented.\n"); + goto finish; + } + + ret = 0; + +finish: + + if (d) { + XSync(d, False); + XCloseDisplay(d); + } + + return ret; +} -- cgit From b56b9e50e027c22fc56c805d8d0cd10d99a4cd5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 21:37:20 +0000 Subject: * svn:ignore some files * move configuration files to the directories they belong to * built esd-compat.sh in the src/ dir git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@488 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/esdcompat.sh.in | 98 ----------------------------------------------- 1 file changed, 98 deletions(-) delete mode 100755 src/utils/esdcompat.sh.in (limited to 'src/utils') diff --git a/src/utils/esdcompat.sh.in b/src/utils/esdcompat.sh.in deleted file mode 100755 index 76023f52..00000000 --- a/src/utils/esdcompat.sh.in +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/sh - -# $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 Lesser 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 Lesser 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. - -VERSION_STRING="@PACKAGE_NAME@ esd wrapper @PACKAGE_VERSION@" - -fail() { - echo "ERROR: $1" - exit 1 -} - -ARGS=" --log-target=syslog" - -for N in $(seq $#) ; do - - case "$1" in - "") - ;; - - -v|--version) - echo "$VERSION_STRING" - exit 0 - ;; - - -h|--help) - cat < Date: Thu, 16 Feb 2006 22:11:35 +0000 Subject: add a bunch of simple Makefile in the subdirs, just to make compilation with emacs easier they are not intended to be distributed or anything. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@490 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/Makefile | 1 + 1 file changed, 1 insertion(+) create mode 120000 src/utils/Makefile (limited to 'src/utils') diff --git a/src/utils/Makefile b/src/utils/Makefile new file mode 120000 index 00000000..cd2a5c9a --- /dev/null +++ b/src/utils/Makefile @@ -0,0 +1 @@ +../polyp/Makefile \ No newline at end of file -- cgit From 22c8cebb858012e4e9c551bb54456237e7597697 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 22:43:59 +0000 Subject: drop polyplib- prefix from client library files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@492 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 2 +- src/utils/pacat.c | 4 ++-- src/utils/pactl.c | 2 +- src/utils/paplay.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 634c308a..290531e6 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { diff --git a/src/utils/pacat.c b/src/utils/pacat.c index bd2b64fd..a4f3d3af 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -33,10 +33,10 @@ #include #include -#include +#include #include #include -#include +#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 23bd924b..7d903eb8 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/utils/paplay.c b/src/utils/paplay.c index ddc1cbc1..1b3697fa 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -35,10 +35,10 @@ #include #include -#include +#include #include #include -#include +#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version -- cgit From b4cb249d704cbb0458640526a07e1f541b899d3e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 23:12:10 +0000 Subject: shorten include list of utils a little git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@495 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 1 - src/utils/pacat.c | 4 +--- src/utils/pactl.c | 4 +--- src/utils/paplay.c | 4 +--- src/utils/pax11publish.c | 2 +- 5 files changed, 4 insertions(+), 11 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 290531e6..344e3281 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -30,7 +30,6 @@ #include #include #include -#include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got signal, exiting\n"); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index a4f3d3af..3c50402f 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -32,11 +32,9 @@ #include #include -#include -#include +#include #include #include -#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 7d903eb8..4c22c925 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -35,11 +35,9 @@ #include -#include -#include +#include #include #include -#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 1b3697fa..9f73b834 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -34,11 +34,9 @@ #include -#include -#include +#include #include #include -#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 63ee4821..908a3507 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -35,8 +35,8 @@ #include #include #include -#include #include +#include int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; -- cgit From 5eda18bf608a325c136a450e58fa154eb0b270f4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 12:10:58 +0000 Subject: Cleaned up the includes after the restructuring. Indicate which headers are public and which are internal through <> vs "". git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@500 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pax11publish.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 908a3507..56b62d37 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -36,7 +36,8 @@ #include #include #include -#include + +#include "../polyp/client-conf.h" int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; -- cgit From 45700da4ebf2986126d7a4d6889c028599fd3085 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 15:42:47 +0000 Subject: Have a memblock queue on the client side during recording. This makes the record callback optional in stead of mandatory. For applications that wish to retain the old behaviour, simply call pa_stream_peek() followed by pa_stream_drop() in the callback. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@507 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 3c50402f..a3c3f2c8 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -105,14 +105,19 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { } /* This is called whenever new data may is available */ -static void stream_read_callback(pa_stream *s, const void*data, size_t length, void *userdata) { - assert(s && data && length); +static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { + assert(s && length); + void *data; if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); + pa_stream_peek(s, &data, &length); + assert(data && length); + if (buffer) { fprintf(stderr, "Buffer overrun, dropping incoming data\n"); + pa_stream_drop(s); return; } @@ -120,6 +125,7 @@ static void stream_read_callback(pa_stream *s, const void*data, size_t length, v assert(buffer); memcpy(buffer, data, length); buffer_index = 0; + pa_stream_drop(s); } /* This routine is called whenever the stream state changes */ -- cgit From 304449002cbc84fdcf235b5dfaec891278dd7085 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 04:05:16 +0000 Subject: 1) Add flexible seeking support (including absolute) for memory block queues and playback streams 2) Add support to synchronize multiple playback streams 3) add two tests for 1) and 2) 4) s/PA_ERROR/PA_ERR/ 5) s/PA_ERROR_OK/PA_OK/ 6) update simple API to deal properly with new peek/drop recording API 7) add beginnings of proper validity checking on API calls in client libs (needs to be extended) 8) report playback buffer overflows/underflows to the client 9) move client side recording mcalign stuff into the memblockq 10) create typedefs for a bunch of API callback prototypes 11) simplify handling of HUP poll() events Yes, i know, it's usually better to commit a lot of small patches instead of a single big one. In this case however, this would have contradicted the other rule: never commit broken or incomplete stuff. *** This stuff needs a lot of additional testing! *** git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@511 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 6 +++--- src/utils/pactl.c | 2 +- src/utils/paplay.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index a3c3f2c8..4e126c8a 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -80,7 +80,7 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0); + pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE); buffer_length -= l; buffer_index += l; @@ -106,8 +106,8 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { /* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { + const void *data; assert(s && length); - void *data; if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); @@ -175,7 +175,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (mode == PLAYBACK) { pa_cvolume cv; - pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume), NULL); } else pa_stream_connect_record(stream, device, NULL, 0); diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 4c22c925..e3305f0f 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -515,7 +515,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { quit(1); } - pa_stream_write(s, d, length, free, 0); + pa_stream_write(s, d, length, free, 0, PA_SEEK_RELATIVE); sample_length -= length; diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 9f73b834..5f985ee9 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -113,7 +113,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { f = readf_function(sndfile, data, n); if (f > 0) - pa_stream_write(s, data, f*k, free, 0); + pa_stream_write(s, data, f*k, free, 0, PA_SEEK_RELATIVE); if (f < n) { sf_close(sndfile); @@ -166,7 +166,7 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); - pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL); break; } -- cgit From 71b3bff6816b857a6a9613cc45b06f0b9e5a65e1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 22:41:02 +0000 Subject: * modify pa_context_exit_daemon() to return a pa_operation object * add callback prototypes to all introspection functions in client lib * add proper validity checking and error handling to all functions in the client lib * other minor cleanups * todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@531 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index e3305f0f..86c4e7be 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -559,7 +559,7 @@ static void context_state_callback(pa_context *c, void *userdata) { break; case EXIT: - pa_context_exit_daemon(c); + pa_operation_unref(pa_context_exit_daemon(c, NULL, NULL)); drain(); case LIST: -- cgit From 31a027b78b5081903ecdde5cff1b42770c93b075 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:29:46 +0000 Subject: change calls of pa_context_connect() to pass flags arugment correctly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@533 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 4e126c8a..6efc3a47 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -509,7 +509,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, server, 1, NULL); + pa_context_connect(context, server, 0, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 86c4e7be..907746aa 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -752,7 +752,7 @@ int main(int argc, char *argv[]) { } pa_context_set_state_callback(context, context_state_callback, NULL); - pa_context_connect(context, server, 1, NULL); + pa_context_connect(context, server, 0, NULL); if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 5f985ee9..4efb4cf6 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -352,7 +352,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, server, 1, NULL); + pa_context_connect(context, server, 0, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { -- cgit From a10257d680d178d493ccae7a2f273ee6987c2dae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 01:22:42 +0000 Subject: fix pacat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@550 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 64 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 6efc3a47..43e67144 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -80,7 +80,12 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE); + if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { + fprintf(stderr, "pa_stream_write() failed: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + buffer_length -= l; buffer_index += l; @@ -112,12 +117,20 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); - pa_stream_peek(s, &data, &length); + if (pa_stream_peek(s, &data, &length) < 0) { + fprintf(stderr, "pa_stream_peek() failed: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + assert(data && length); if (buffer) { fprintf(stderr, "Buffer overrun, dropping incoming data\n"); - pa_stream_drop(s); + if (pa_stream_drop(s) < 0) { + fprintf(stderr, "pa_stream_drop() failed: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } return; } @@ -159,15 +172,18 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_SETTING_NAME: break; - case PA_CONTEXT_READY: + case PA_CONTEXT_READY: { + int r; assert(c && !stream); if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &sample_spec, NULL); - assert(stream); + if (!(stream = pa_stream_new(c, stream_name, &sample_spec, NULL))) { + fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); @@ -175,11 +191,20 @@ static void context_state_callback(pa_context *c, void *userdata) { if (mode == PLAYBACK) { pa_cvolume cv; - pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume), NULL); - } else - pa_stream_connect_record(stream, device, NULL, 0); + if ((r = pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { + fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + + } else { + if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) { + fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + } break; + } case PA_CONTEXT_TERMINATED: quit(0); @@ -188,8 +213,14 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_FAILED: default: fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); - quit(1); + goto fail; } + + return; + +fail: + quit(1); + } /* Connection draining complete */ @@ -216,8 +247,6 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else { - pa_operation_unref(o); - if (verbose) fprintf(stderr, "Draining connection to server.\n"); } @@ -241,9 +270,18 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even assert(buffer); if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { + pa_operation *o; + if (verbose) fprintf(stderr, "Got EOF.\n"); - pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL)); + + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { + fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + + pa_operation_unref(o); } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); -- cgit From 7f68c913f1c54114a538ccca680db3a3ba4d6e26 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 20:11:56 +0000 Subject: revive howl support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@566 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 344e3281..c1bab6b1 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -55,26 +55,21 @@ static void dump_server(const pa_browse_info *i) { } static void dump_device(const pa_browse_info *i) { - char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (i->sample_spec) pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec); - if (i->typeid) - pa_typeid_to_string(*i->typeid, t, sizeof(t)); - printf("device: %s\n" "description: %s\n" - "type: %s\n" "sample spec: %s\n", i->device, i->description ? i->description : "n/a", - i->typeid ? t : "n/a", i->sample_spec ? ss : "n/a"); } -static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_info *i, void *userdata) { +static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) { assert(b && i); switch (c) { @@ -96,10 +91,18 @@ static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_ dump_device(i); break; - case PA_BROWSE_REMOVE: - printf("\n=> removed service <%s>\n", i->name); + case PA_BROWSE_REMOVE_SERVER: + printf("\n=> removed server <%s>\n", i->name); break; - + + case PA_BROWSE_REMOVE_SINK: + printf("\n=> removed sink <%s>\n", i->name); + break; + + case PA_BROWSE_REMOVE_SOURCE: + printf("\n=> removed source <%s>\n", i->name); + break; + default: ; } -- cgit From 4a64b0d1167e980d81b798d813f35209895f0674 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 02:27:19 +0000 Subject: change pa_log() and friends to not require a trailing \n on all logged strings git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@574 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 20 ++++++++++---------- src/utils/pax11publish.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 4054bc2c..a71e0e93 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -46,12 +46,12 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { fd_set ifds, ofds; if (pa_pid_file_check_running(&pid) < 0) { - pa_log(__FILE__": no Polypaudio daemon running\n"); + pa_log(__FILE__": no Polypaudio daemon running"); goto fail; } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s\n", strerror(errno)); + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -63,7 +63,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect() failed: %s\n", strerror(errno)); + pa_log(__FILE__": connect() failed: %s", strerror(errno)); goto fail; } @@ -71,7 +71,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { break; if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { - pa_log(__FILE__": failed to kill Polypaudio daemon.\n"); + pa_log(__FILE__": failed to kill Polypaudio daemon."); goto fail; } @@ -79,7 +79,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { } if (i >= 5) { - pa_log(__FILE__": daemon not responding.\n"); + pa_log(__FILE__": daemon not responding."); goto fail; } @@ -94,7 +94,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select() failed: %s\n", strerror(errno)); + pa_log(__FILE__": select() failed: %s", strerror(errno)); goto fail; } @@ -106,7 +106,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); goto fail; } @@ -122,7 +122,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); goto fail; } @@ -135,7 +135,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); goto fail; } @@ -149,7 +149,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); goto fail; } diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 56b62d37..e4358894 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -90,7 +90,7 @@ int main(int argc, char *argv[]) { } if (!(d = XOpenDisplay(dname))) { - pa_log(__FILE__": XOpenDisplay() failed\n"); + pa_log(__FILE__": XOpenDisplay() failed"); goto finish; } -- cgit From 53a0056cdf3467cc98740e61b781935ef0ed5ac4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 00:25:05 +0000 Subject: update pacat.c for new latency API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@649 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 43e67144..8d9cff0b 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -339,28 +340,34 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, } /* Show the current latency */ -static void stream_get_latency_callback(pa_stream *s, const pa_latency_info *i, void *userdata) { +static void stream_update_latency_callback(pa_stream *s, int success, void *userdata) { pa_usec_t total; int negative = 0; + const pa_latency_info *i; + assert(s); - if (!i) { + if (!success || + !(i = pa_stream_get_latency_info(s)) || + pa_stream_get_latency(s, &total, &negative) < 0) { fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - total = pa_stream_get_latency(s, i, &negative); - fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", - (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, (float) total * (negative?-1:1), + (float) i->buffer_usec, + (float) i->sink_usec, + (float) i->source_usec, + (float) i->transport_usec, + (float) total * (negative?-1:1), i->synchronized_clocks ? "yes" : "no"); } /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); - pa_operation_unref(pa_stream_get_latency_info(stream, stream_get_latency_callback, NULL)); + pa_operation_unref(pa_stream_update_latency_info(stream, stream_update_latency_callback, NULL)); } @@ -511,6 +518,27 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); } + if (optind+1 < argc) { + fprintf(stderr, "Too many arguments.\n"); + goto quit; + } + + if (optind+1 == argc) { + int fd; + + if ((fd = open(argv[optind], O_RDONLY)) < 0) { + fprintf(stderr, "open(): %s\n", strerror(errno)); + goto quit; + } + + if (dup2(fd, 0) < 0) { + fprintf(stderr, "dup2(): %s\n", strerror(errno)); + goto quit; + } + + close(fd); + } + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); -- cgit From b8a729a00f170241599e670ee3f3f65457b4320f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 01:29:33 +0000 Subject: * update docs for reworked latency API * rename pa_latency_info to pa_timing_info, since that describes better what it is. Most people will only use pa_stream_get_time() anyway git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@651 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 8d9cff0b..441e2607 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -340,15 +340,15 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, } /* Show the current latency */ -static void stream_update_latency_callback(pa_stream *s, int success, void *userdata) { +static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { pa_usec_t total; int negative = 0; - const pa_latency_info *i; + const pa_timing_info *i; assert(s); if (!success || - !(i = pa_stream_get_latency_info(s)) || + !(i = pa_stream_get_timing_info(s)) || pa_stream_get_latency(s, &total, &negative) < 0) { fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); @@ -366,8 +366,7 @@ static void stream_update_latency_callback(pa_stream *s, int success, void *user /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { - fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); - pa_operation_unref(pa_stream_update_latency_info(stream, stream_update_latency_callback, NULL)); + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); } -- cgit From a546c76a1c0b85ec481d11e2f9a1524a7abde14b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 23:05:45 +0000 Subject: * show flags value when dumping sink/source info in pactl. * show volume for sources, too * show value of "mute" field for sinks/sources git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@662 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 907746aa..fcc677d9 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -175,7 +175,8 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ "Owner Module: %u\n" "Volume: %s\n" "Monitor Source: %u\n" - "Latency: %0.0f usec\n", + "Latency: %0.0f usec\n" + "Flags: %s%s\n", i->index, i->name, i->driver, @@ -183,14 +184,16 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, - pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), i->monitor_source, - (double) i->latency); + (double) i->latency, + i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + i->flags & PA_SINK_LATENCY ? "LATENCY" : ""); } static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (is_last < 0) { fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c))); @@ -218,8 +221,10 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int "Sample Specification: %s\n" "Channel Map: %s\n" "Owner Module: %u\n" + "Volume: %s\n" "Monitor of Sink: %s\n" - "Latency: %0.0f usec\n", + "Latency: %0.0f usec\n" + "Flags: %s%s\n", i->index, i->driver, i->name, @@ -227,9 +232,12 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", - (double) i->latency); - + (double) i->latency, + i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + i->flags & PA_SOURCE_LATENCY ? "LATENCY" : ""); + } static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) { -- cgit From 93327083d9273bcf2d6ce94b61449c181dcf6fa2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 19:42:14 +0000 Subject: when using record mode, allow file to save data to to be passed on the command line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@675 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 441e2607..e721befa 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -517,25 +517,25 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); } - if (optind+1 < argc) { - fprintf(stderr, "Too many arguments.\n"); - goto quit; - } - - if (optind+1 == argc) { - int fd; - - if ((fd = open(argv[optind], O_RDONLY)) < 0) { - fprintf(stderr, "open(): %s\n", strerror(errno)); - goto quit; - } - - if (dup2(fd, 0) < 0) { - fprintf(stderr, "dup2(): %s\n", strerror(errno)); + if (!(optind >= argc)) { + if (optind+1 == argc) { + int fd; + + if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT)) < 0) { + fprintf(stderr, "open(): %s\n", strerror(errno)); + goto quit; + } + + if (dup2(fd, mode == PLAYBACK ? 0 : 1) < 0) { + fprintf(stderr, "dup2(): %s\n", strerror(errno)); + goto quit; + } + + close(fd); + } else { + fprintf(stderr, "Too many arguments.\n"); goto quit; } - - close(fd); } /* Set up a new main loop */ -- cgit From d42794206db90b0a991c246d12afc409aafcafa5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:18:24 +0000 Subject: beefup pacat a little: * when -v is passed, show current playback time and latency * modify SIGUSR1 behaviour to show only playback time and latency git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@687 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 59 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index e721befa..2c12dbb3 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -36,6 +36,9 @@ #include #include #include +#include + +#define TIME_EVENT_USEC 50000 #if PA_API_VERSION != 8 #error Invalid Polypaudio API version @@ -153,7 +156,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) - fprintf(stderr, "Stream successfully created\n"); + fprintf(stderr, "Stream successfully created.\n"); break; case PA_STREAM_FAILED: @@ -341,34 +344,46 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, /* Show the current latency */ static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { - pa_usec_t total; + pa_usec_t latency, usec; int negative = 0; - const pa_timing_info *i; assert(s); if (!success || - !(i = pa_stream_get_timing_info(s)) || - pa_stream_get_latency(s, &total, &negative) < 0) { + pa_stream_get_time(s, &usec) < 0 || + pa_stream_get_latency(s, &latency, &negative) < 0) { fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", - (float) i->buffer_usec, - (float) i->sink_usec, - (float) i->source_usec, - (float) i->transport_usec, - (float) total * (negative?-1:1), - i->synchronized_clocks ? "yes" : "no"); + fprintf(stderr, "Time: %0.3f sec; Latency: %0.0f usec. \r", + (float) usec / 1000000, + (float) latency * (negative?-1:1)); } /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { + + if (!stream) + return; + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); } +static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { + struct timeval next; + + if (!stream) + return; + + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); + + pa_gettimeofday(&next); + pa_timeval_add(&next, TIME_EVENT_USEC); + + m->time_restart(e, &next); +} static void help(const char *argv0) { @@ -404,6 +419,7 @@ int main(int argc, char *argv[]) { pa_mainloop* m = NULL; int ret = 1, r, c; char *bn, *server = NULL; + pa_time_event *time_event = NULL; static const struct option long_options[] = { {"record", 0, NULL, 'r'}, @@ -561,7 +577,7 @@ int main(int argc, char *argv[]) { mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { - fprintf(stderr, "source_io() failed.\n"); + fprintf(stderr, "io_new() failed.\n"); goto quit; } @@ -576,6 +592,18 @@ int main(int argc, char *argv[]) { /* Connect the context */ pa_context_connect(context, server, 0, NULL); + if (verbose) { + struct timeval tv; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, TIME_EVENT_USEC); + + if (!(time_event = mainloop_api->time_new(mainloop_api, &tv, time_event_callback, NULL))) { + fprintf(stderr, "time_new() failed.\n"); + goto quit; + } + } + /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); @@ -593,6 +621,11 @@ quit: assert(mainloop_api); mainloop_api->io_free(stdio_event); } + + if (time_event) { + assert(mainloop_api); + mainloop_api->time_free(time_event); + } if (m) { pa_signal_done(); -- cgit From 0af582a8d6297f0e4b156001b49f38bba032b199 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:12:54 +0000 Subject: small fix to deal properly with slow links git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@691 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 2c12dbb3..4d3302ab 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -374,10 +374,13 @@ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int s static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct timeval next; - if (!stream) - return; - - pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); + if (stream) { + pa_operation *o; + if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) + fprintf(stderr, "pa_stream_update_timing_info() failed: %s\n", pa_strerror(pa_context_errno(context))); + else + pa_operation_unref(o); + } pa_gettimeofday(&next); pa_timeval_add(&next, TIME_EVENT_USEC); -- cgit From 4a8d3185492f381c88c737097123638bf9f6ed29 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:19:07 +0000 Subject: yet anotrher fix for slow links git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@692 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 4d3302ab..1e22656d 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -374,7 +374,7 @@ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int s static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct timeval next; - if (stream) { + if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) { pa_operation *o; if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) fprintf(stderr, "pa_stream_update_timing_info() failed: %s\n", pa_strerror(pa_context_errno(context))); -- cgit From 06bd27b0433e06f3af573ddc213e2577127972e4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:55:21 +0000 Subject: when storing recording data in file, create file with proper access rights git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@693 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 1e22656d..cce97442 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -540,7 +540,7 @@ int main(int argc, char *argv[]) { if (optind+1 == argc) { int fd; - if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT)) < 0) { + if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { fprintf(stderr, "open(): %s\n", strerror(errno)); goto quit; } -- cgit From 746adcfed5dc396bc4820724b2e951369fc63aeb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 19:31:50 +0000 Subject: fix a couple of issues I found when compiling polypaudio with gcc 2.95 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@754 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index a71e0e93..e640ddaf 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -36,7 +36,7 @@ #include #include -int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { pid_t pid ; int fd = -1; int ret = 1, i; -- cgit From c3cc14153a2f519b2333400bfa942f70bca58c95 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:07:33 +0000 Subject: allow specifying the channel map to use on the command line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@805 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index cce97442..a823c88b 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -66,6 +66,9 @@ static pa_sample_spec sample_spec = { .channels = 2 }; +static pa_channel_map channel_map; +static int channel_map_set = 0; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -184,7 +187,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - if (!(stream = pa_stream_new(c, stream_name, &sample_spec, NULL))) { + if (!(stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL))) { fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } @@ -405,7 +408,8 @@ static void help(const char *argv0) { " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" " float32be, ulaw, alaw (defaults to s16ne)\n" " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" - " (defaults to 2)\n", + " (defaults to 2)\n" + " --channel-map=CHANNELMAP Channel map to use instead of the default\n", argv0); } @@ -415,7 +419,8 @@ enum { ARG_VOLUME, ARG_SAMPLERATE, ARG_SAMPLEFORMAT, - ARG_CHANNELS + ARG_CHANNELS, + ARG_CHANNELMAP, }; int main(int argc, char *argv[]) { @@ -438,6 +443,7 @@ int main(int argc, char *argv[]) { {"rate", 1, NULL, ARG_SAMPLERATE}, {"format", 1, NULL, ARG_SAMPLEFORMAT}, {"channels", 1, NULL, ARG_CHANNELS}, + {"channel-map", 1, NULL, ARG_CHANNELMAP}, {NULL, 0, NULL, 0} }; @@ -514,6 +520,16 @@ int main(int argc, char *argv[]) { sample_spec.rate = atoi(optarg); break; + case ARG_CHANNELMAP: + + if (!pa_channel_map_parse(&channel_map, optarg)) { + fprintf(stderr, "Invalid channel map\n"); + goto quit; + } + + channel_map_set = 1; + break; + default: goto quit; } @@ -529,6 +545,11 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Invalid sample specification\n"); goto quit; } + + if (channel_map_set && channel_map.channels != sample_spec.channels) { + fprintf(stderr, "Channel map doesn't match sample specification\n"); + goto quit; + } if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; -- cgit From d78e466a2839ac9d71993cf069f7df4360ecea1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:27:59 +0000 Subject: fix volume range printed on --help git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@808 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index a823c88b..1ecc0db2 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -403,7 +403,7 @@ static void help(const char *argv0) { " -d, --device=DEVICE The name of the sink/source to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" - " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n" + " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" " float32be, ulaw, alaw (defaults to s16ne)\n" @@ -521,7 +521,6 @@ int main(int argc, char *argv[]) { break; case ARG_CHANNELMAP: - if (!pa_channel_map_parse(&channel_map, optarg)) { fprintf(stderr, "Invalid channel map\n"); goto quit; -- cgit From c27b1407f8197230136158eae2aeb75f526a12f3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:28:29 +0000 Subject: allow the user to specify an alternative channel map in paplay too git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@809 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'src/utils') diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 4efb4cf6..7f665413 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -53,7 +53,9 @@ static pa_volume_t volume = PA_VOLUME_NORM; static SNDFILE* sndfile = NULL; -static pa_sample_spec sample_spec = { 0, 0, 0 }; +static pa_sample_spec sample_spec = { 0, 0, 0 }; +static pa_channel_map channel_map; +static int channel_map_set = 0; static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames); @@ -161,7 +163,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &sample_spec, NULL); + stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); @@ -200,14 +202,16 @@ static void help(const char *argv0) { " -d, --device=DEVICE The name of the sink/source to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" - " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" + " --channel-map=CHANNELMAP Set the channel map to the use\n", argv0); } enum { ARG_VERSION = 256, ARG_STREAM_NAME, - ARG_VOLUME + ARG_VOLUME, + ARG_CHANNELMAP }; int main(int argc, char *argv[]) { @@ -226,6 +230,7 @@ int main(int argc, char *argv[]) { {"help", 0, NULL, 'h'}, {"verbose", 0, NULL, 'v'}, {"volume", 1, NULL, ARG_VOLUME}, + {"channel-map", 1, NULL, ARG_CHANNELMAP}, {NULL, 0, NULL, 0} }; @@ -277,6 +282,15 @@ int main(int argc, char *argv[]) { break; } + case ARG_CHANNELMAP: + if (!pa_channel_map_parse(&channel_map, optarg)) { + fprintf(stderr, "Invalid channel map\n"); + goto quit; + } + + channel_map_set = 1; + break; + default: goto quit; } @@ -322,6 +336,13 @@ int main(int argc, char *argv[]) { break; } + assert(pa_sample_spec_valid(&sample_spec)); + + if (channel_map_set && channel_map.channels != sample_spec.channels) { + fprintf(stderr, "Channel map doesn't match file.\n"); + goto quit; + } + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); -- cgit From cfb082a67c5bfad24fd2d322028d3e87d7c58da6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:17:17 +0000 Subject: take the filename specified on the command line as default stream name git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@863 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 1ecc0db2..c8890bbb 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -534,12 +534,6 @@ int main(int argc, char *argv[]) { } } - if (!client_name) - client_name = strdup(bn); - - if (!stream_name) - stream_name = strdup(client_name); - if (!pa_sample_spec_valid(&sample_spec)) { fprintf(stderr, "Invalid sample specification\n"); goto quit; @@ -571,12 +565,22 @@ int main(int argc, char *argv[]) { } close(fd); + + if (!stream_name) + stream_name = strdup(argv[optind]); + } else { fprintf(stderr, "Too many arguments.\n"); goto quit; } } - + + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) + stream_name = strdup(client_name); + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); -- cgit From c2c8539201307cf8bf500ce7b77c8f09eaa655b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 18:28:03 +0000 Subject: bump version number to 0.9 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@886 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index c8890bbb..529cebae 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -40,7 +40,7 @@ #define TIME_EVENT_USEC 50000 -#if PA_API_VERSION != 8 +#if PA_API_VERSION != 9 #error Invalid Polypaudio API version #endif diff --git a/src/utils/pactl.c b/src/utils/pactl.c index fcc677d9..7a3d3737 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -39,7 +39,7 @@ #include #include -#if PA_API_VERSION != 8 +#if PA_API_VERSION != 9 #error Invalid Polypaudio API version #endif diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 7f665413..ad9d4553 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -38,7 +38,7 @@ #include #include -#if PA_API_VERSION != 8 +#if PA_API_VERSION != 9 #error Invalid Polypaudio API version #endif -- cgit From 31a9d4fb301bdfed50bee2cf162cc98093bb19f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:06:12 +0000 Subject: when playing an ULAW or ALAW audio file, do not convert to S16NE unconditionally, instead use sf_read_raw() to read raw audio data git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@898 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 57 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'src/utils') diff --git a/src/utils/paplay.c b/src/utils/paplay.c index ad9d4553..d4af95c1 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -57,7 +57,7 @@ static pa_sample_spec sample_spec = { 0, 0, 0 }; static pa_channel_map channel_map; static int channel_map_set = 0; -static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames); +static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames) = NULL; /* A shortcut for terminating the application */ static void quit(int ret) { @@ -98,26 +98,30 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { /* This is called whenever new data may be written to the stream */ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { - size_t k; - sf_count_t f, n; + sf_count_t bytes; void *data; assert(s && length); if (!sndfile) return; - - k = pa_frame_size(&sample_spec); data = malloc(length); - n = length/k; - - f = readf_function(sndfile, data, n); + if (readf_function) { + size_t k = pa_frame_size(&sample_spec); - if (f > 0) - pa_stream_write(s, data, f*k, free, 0, PA_SEEK_RELATIVE); + if ((bytes = readf_function(sndfile, data, length/k)) > 0) + bytes *= k; + + } else + bytes = sf_read_raw(sndfile, data, length); - if (f < n) { + if (bytes > 0) + pa_stream_write(s, data, bytes, free, 0, PA_SEEK_RELATIVE); + else + free(data); + + if (bytes < length) { sf_close(sndfile); sndfile = NULL; pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); @@ -296,16 +300,8 @@ int main(int argc, char *argv[]) { } } - filename = optind < argc ? argv[optind] : "STDIN"; - - if (!client_name) - client_name = strdup(bn); - - if (!stream_name) - stream_name = strdup(filename); - memset(&sfinfo, 0, sizeof(sfinfo)); if (optind < argc) @@ -317,18 +313,27 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Failed to open file '%s'\n", filename); goto quit; } - + sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: - case SF_FORMAT_ULAW: - case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; + + case SF_FORMAT_ULAW: + sample_spec.format = PA_SAMPLE_ULAW; + readf_function = NULL; + break; + + case SF_FORMAT_ALAW: + sample_spec.format = PA_SAMPLE_ALAW; + readf_function = NULL; + break; + case SF_FORMAT_FLOAT: default: sample_spec.format = PA_SAMPLE_FLOAT32NE; @@ -343,6 +348,14 @@ int main(int argc, char *argv[]) { goto quit; } + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) { + const char *n = sf_get_string(sndfile, SF_STR_TITLE); + stream_name = strdup(n ? n : filename); + } + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); -- cgit From e6695538d721941132db2183e40f142b9e52076e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:54:41 +0000 Subject: * use S16NE for SF_FORMAT_PCM_S8 formats, too git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@899 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/paplay.c b/src/utils/paplay.c index d4af95c1..5f203615 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -317,24 +317,26 @@ int main(int argc, char *argv[]) { sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; + readf_function = NULL; + switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: + case SF_FORMAT_PCM_S8: sample_spec.format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; case SF_FORMAT_ULAW: sample_spec.format = PA_SAMPLE_ULAW; - readf_function = NULL; break; case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_ALAW; - readf_function = NULL; break; case SF_FORMAT_FLOAT: + case SF_FORMAT_DOUBLE: default: sample_spec.format = PA_SAMPLE_FLOAT32NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_float; -- cgit From fbdb06351385eb210c50ba6a1fc2b8c14575513e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 19:26:54 +0000 Subject: replace memory allocation function calls with pa_xXXXX() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@916 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 46 +++++++++++++++++++++------------------------- src/utils/pactl.c | 35 ++++++++++++++++------------------- src/utils/paplay.c | 36 +++++++++++++++++------------------- 3 files changed, 54 insertions(+), 63 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 529cebae..51b3a48e 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -34,8 +34,6 @@ #include #include -#include -#include #include #define TIME_EVENT_USEC 50000 @@ -97,7 +95,7 @@ static void do_stream_write(size_t length) { buffer_index += l; if (!buffer_length) { - free(buffer); + pa_xfree(buffer); buffer = NULL; buffer_index = buffer_length = 0; } @@ -141,8 +139,7 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { return; } - buffer = malloc(buffer_length = length); - assert(buffer); + buffer = pa_xmalloc(buffer_length = length); memcpy(buffer, data, length); buffer_index = 0; pa_stream_drop(s); @@ -273,8 +270,8 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; - buffer = malloc(l); - assert(buffer); + buffer = pa_xmalloc(l); + if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { pa_operation *o; @@ -331,7 +328,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve buffer_index += r; if (!buffer_length) { - free(buffer); + pa_xfree(buffer); buffer = NULL; buffer_length = buffer_index = 0; } @@ -342,7 +339,6 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, if (verbose) fprintf(stderr, "Got signal, exiting.\n"); quit(0); - } /* Show the current latency */ @@ -479,23 +475,23 @@ int main(int argc, char *argv[]) { break; case 'd': - free(device); - device = strdup(optarg); + pa_xfree(device); + device = pa_xstrdup(optarg); break; case 's': - free(server); - server = strdup(optarg); + pa_xfree(server); + server = pa_xstrdup(optarg); break; case 'n': - free(client_name); - client_name = strdup(optarg); + pa_xfree(client_name); + client_name = pa_xstrdup(optarg); break; case ARG_STREAM_NAME: - free(stream_name); - stream_name = strdup(optarg); + pa_xfree(stream_name); + stream_name = pa_xstrdup(optarg); break; case 'v': @@ -567,7 +563,7 @@ int main(int argc, char *argv[]) { close(fd); if (!stream_name) - stream_name = strdup(argv[optind]); + stream_name = pa_xstrdup(argv[optind]); } else { fprintf(stderr, "Too many arguments.\n"); @@ -576,10 +572,10 @@ int main(int argc, char *argv[]) { } if (!client_name) - client_name = strdup(bn); + client_name = pa_xstrdup(bn); if (!stream_name) - stream_name = strdup(client_name); + stream_name = pa_xstrdup(client_name); /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { @@ -659,12 +655,12 @@ quit: pa_mainloop_free(m); } - free(buffer); + pa_xfree(buffer); - free(server); - free(device); - free(client_name); - free(stream_name); + pa_xfree(server); + pa_xfree(device); + pa_xfree(client_name); + pa_xfree(stream_name); return ret; } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 7a3d3737..cc59e459 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -36,8 +36,6 @@ #include #include -#include -#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -511,19 +509,18 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { float *d; assert(s && length && sndfile); - d = malloc(length); - assert(d); + d = pa_xmalloc(length); assert(sample_length >= length); l = length/pa_frame_size(&sample_spec); if ((sf_readf_float(sndfile, d, l)) != l) { - free(d); + pa_xfree(d); fprintf(stderr, "Premature end of file\n"); quit(1); } - pa_stream_write(s, d, length, free, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE); sample_length -= length; @@ -652,13 +649,13 @@ int main(int argc, char *argv[]) { goto quit; case 's': - free(server); - server = strdup(optarg); + pa_xfree(server); + server = pa_xstrdup(optarg); break; case 'n': - free(client_name); - client_name = strdup(optarg); + pa_xfree(client_name); + client_name = pa_xstrdup(optarg); break; default: @@ -667,7 +664,7 @@ int main(int argc, char *argv[]) { } if (!client_name) - client_name = strdup(bn); + client_name = pa_xstrdup(bn); if (optind < argc) { if (!strcmp(argv[optind], "stat")) @@ -686,7 +683,7 @@ int main(int argc, char *argv[]) { } if (optind+2 < argc) - sample_name = strdup(argv[optind+2]); + sample_name = pa_xstrdup(argv[optind+2]); else { char *f = strrchr(argv[optind+1], '/'); size_t n; @@ -698,7 +695,7 @@ int main(int argc, char *argv[]) { n = strcspn(f, "."); strncpy(tmp, f, n); tmp[n] = 0; - sample_name = strdup(tmp); + sample_name = pa_xstrdup(tmp); } memset(&sfinfo, 0, sizeof(sfinfo)); @@ -719,10 +716,10 @@ int main(int argc, char *argv[]) { goto quit; } - sample_name = strdup(argv[optind+1]); + sample_name = pa_xstrdup(argv[optind+1]); if (optind+2 < argc) - device = strdup(argv[optind+2]); + device = pa_xstrdup(argv[optind+2]); } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; @@ -731,7 +728,7 @@ int main(int argc, char *argv[]) { goto quit; } - sample_name = strdup(argv[optind+1]); + sample_name = pa_xstrdup(argv[optind+1]); } } @@ -782,9 +779,9 @@ quit: if (sndfile) sf_close(sndfile); - free(server); - free(device); - free(sample_name); + pa_xfree(server); + pa_xfree(device); + pa_xfree(sample_name); return ret; } diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 5f203615..b66c13da 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -35,8 +35,6 @@ #include #include -#include -#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -105,7 +103,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { if (!sndfile) return; - data = malloc(length); + data = pa_xmalloc(length); if (readf_function) { size_t k = pa_frame_size(&sample_spec); @@ -117,9 +115,9 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { bytes = sf_read_raw(sndfile, data, length); if (bytes > 0) - pa_stream_write(s, data, bytes, free, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, data, bytes, pa_xfree, 0, PA_SEEK_RELATIVE); else - free(data); + pa_xfree(data); if (bytes < length) { sf_close(sndfile); @@ -257,23 +255,23 @@ int main(int argc, char *argv[]) { goto quit; case 'd': - free(device); - device = strdup(optarg); + pa_xfree(device); + device = pa_xstrdup(optarg); break; case 's': - free(server); - server = strdup(optarg); + pa_xfree(server); + server = pa_xstrdup(optarg); break; case 'n': - free(client_name); - client_name = strdup(optarg); + pa_xfree(client_name); + client_name = pa_xstrdup(optarg); break; case ARG_STREAM_NAME: - free(stream_name); - stream_name = strdup(optarg); + pa_xfree(stream_name); + stream_name = pa_xstrdup(optarg); break; case 'v': @@ -351,11 +349,11 @@ int main(int argc, char *argv[]) { } if (!client_name) - client_name = strdup(bn); + client_name = pa_xstrdup(bn); if (!stream_name) { const char *n = sf_get_string(sndfile, SF_STR_TITLE); - stream_name = strdup(n ? n : filename); + stream_name = pa_xstrdup(n ? n : filename); } if (verbose) { @@ -408,10 +406,10 @@ quit: pa_mainloop_free(m); } - free(server); - free(device); - free(client_name); - free(stream_name); + pa_xfree(server); + pa_xfree(device); + pa_xfree(client_name); + pa_xfree(stream_name); if (sndfile) sf_close(sndfile); -- cgit From c47e937011f00eebab7230cedb58fd59f16487b4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:09:57 +0000 Subject: split polypcore/util.[ch] into polypcore/core-util.[ch] and polyp/util.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@917 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index c1bab6b1..8063a28b 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -27,8 +27,7 @@ #include #include -#include -#include +#include #include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { @@ -108,7 +107,6 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows } } - int main(int argc, char *argv[]) { pa_mainloop *mainloop = NULL; pa_browser *browser = NULL; -- cgit From 53a285e75616281bcdd8b1dcf0e3b7ba59257516 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:44:55 +0000 Subject: fix include line for "core-util.h" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@923 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 1 - src/utils/pacmd.c | 2 +- src/utils/pax11publish.c | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 51b3a48e..b1f5bf59 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -34,7 +34,6 @@ #include #include -#include #define TIME_EVENT_USEC 50000 diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index e640ddaf..fefe7634 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index e4358894..ee0cb845 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include -- cgit From 24a781992bad4d66bb7bc3a2d1deeba7e959dbb1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 07:04:41 +0000 Subject: Don't include util.h from core-util.h as it is not needed by many users. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@929 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index fefe7634..539d205e 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include -- cgit From 83591883d8bcec475e74881b3f9cbcb84900c7ec Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 08:21:41 +0000 Subject: Make paplay convert names to UTF-8 before sending to the server. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@932 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src/utils') diff --git a/src/utils/paplay.c b/src/utils/paplay.c index b66c13da..effc2a11 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -236,6 +237,8 @@ int main(int argc, char *argv[]) { {NULL, 0, NULL, 0} }; + setlocale(LC_ALL, ""); + if (!(bn = strrchr(argv[0], '/'))) bn = argv[0]; else @@ -348,12 +351,23 @@ int main(int argc, char *argv[]) { goto quit; } - if (!client_name) - client_name = pa_xstrdup(bn); + if (!client_name) { + client_name = pa_locale_to_utf8(bn); + if (!client_name) + client_name = pa_utf8_filter(bn); + } if (!stream_name) { - const char *n = sf_get_string(sndfile, SF_STR_TITLE); - stream_name = pa_xstrdup(n ? n : filename); + const char *n; + + n = sf_get_string(sndfile, SF_STR_TITLE); + + if (!n) + n = filename; + + stream_name = pa_locale_to_utf8(n); + if (!stream_name) + stream_name = pa_utf8_filter(n); } if (verbose) { -- cgit From a3fe39ac4168d9521dc12c8e27eb8040ff078f5e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 19 May 2006 11:32:32 +0000 Subject: Fix some missing headers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@937 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pax11publish.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/utils') diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index ee0cb845..668361c6 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include -- cgit From 4e3dc7ce68561c16254712d713b2ccd472b8afe7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 22 May 2006 15:20:46 +0000 Subject: Wrap strerror() in a function that makes it thread safe and converts the output to UTF-8. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@945 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 539d205e..351d79da 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -53,7 +54,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", pa_cstrerror(errno)); goto fail; } @@ -65,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect() failed: %s", strerror(errno)); + pa_log(__FILE__": connect(): %s", pa_cstrerror(errno)); goto fail; } @@ -96,7 +97,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select() failed: %s", strerror(errno)); + pa_log(__FILE__": select(): %s", pa_cstrerror(errno)); goto fail; } @@ -108,7 +109,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); goto fail; } @@ -124,7 +125,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); goto fail; } @@ -137,7 +138,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); goto fail; } @@ -151,7 +152,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); goto fail; } -- cgit From 103154940d09855b102ab823f032e854f5327ba1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 14:42:23 +0000 Subject: add new padsp utility: a $LD_PRELOAD wrapper for using the OSS API with polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@950 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 1284 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils/padsp.in | 30 ++ 2 files changed, 1314 insertions(+) create mode 100644 src/utils/padsp.c create mode 100644 src/utils/padsp.in (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c new file mode 100644 index 00000000..06bdd575 --- /dev/null +++ b/src/utils/padsp.c @@ -0,0 +1,1284 @@ +/* $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 Lesser 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 Lesser 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 +#endif + +#ifdef _FILE_OFFSET_BITS +#undef _FILE_OFFSET_BITS +#endif + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +typedef enum { + FD_INFO_MIXER, + FD_INFO_PLAYBACK +} fd_info_type_t; + +typedef struct fd_info fd_info; + +struct fd_info { + pthread_mutex_t mutex; + int ref; + + fd_info_type_t type; + int app_fd, thread_fd; + + pa_sample_spec sample_spec; + size_t fragment_size; + unsigned n_fragments; + + pa_threaded_mainloop *mainloop; + pa_context *context; + pa_stream *stream; + + pa_io_event *io_event; + + void *buf; + + int operation_success; + + PA_LLIST_FIELDS(fd_info); +}; + +static int dsp_drain(fd_info *i); + +static pthread_mutex_t fd_infos_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t func_mutex = PTHREAD_MUTEX_INITIALIZER; + +static PA_LLIST_HEAD(fd_info, fd_infos) = NULL; + +static int (*_ioctl)(int, int, void*) = NULL; +static int (*_close)(int) = NULL; +static int (*_open)(const char *, int, mode_t) = NULL; +static FILE* (*_fopen)(const char *path, const char *mode) = NULL; +static int (*_open64)(const char *, int, mode_t) = NULL; +static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; +static int (*_fclose)(FILE *f) = NULL; + +#define LOAD_IOCTL_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_ioctl) \ + _ioctl = (int (*)(int, int, void*)) dlsym(RTLD_NEXT, "ioctl"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_OPEN_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_open) \ + _open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_OPEN64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_open64) \ + _open64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_CLOSE_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_close) \ + _close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_FOPEN_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_fopen) \ + _fopen = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_FOPEN64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_fopen64) \ + _fopen64 = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_FCLOSE_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_fclose) \ + _fclose = (int (*)(FILE *)) dlsym(RTLD_NEXT, "fclose"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +static void debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); + +static void debug(const char *format, ...) { + va_list ap; + if (getenv("PADSP_DEBUG")) { + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + } +} + +static pthread_key_t recursion_key; + +static void recursion_key_alloc(void) { + pthread_key_create(&recursion_key, NULL); +} + +static int function_enter(void) { + /* Avoid recursive calls */ + static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT; + pthread_once(&recursion_key_once, recursion_key_alloc); + + if (pthread_getspecific(recursion_key)) + return 0; + + pthread_setspecific(recursion_key, (void*) 1); + return 1; +} + +static void function_exit(void) { + pthread_setspecific(recursion_key, NULL); +} + +static void fd_info_free(fd_info *i) { + assert(i); + + debug(__FILE__": freeing fd info (fd=%i)\n", i->app_fd); + + dsp_drain(i); + + if (i->mainloop) + pa_threaded_mainloop_stop(i->mainloop); + + if (i->stream) { + pa_stream_disconnect(i->stream); + pa_stream_unref(i->stream); + } + + if (i->context) { + pa_context_disconnect(i->context); + pa_context_unref(i->context); + } + + if (i->mainloop) + pa_threaded_mainloop_free(i->mainloop); + + if (i->app_fd >= 0) { + LOAD_CLOSE_FUNC(); + _close(i->app_fd); + } + + if (i->thread_fd >= 0) { + LOAD_CLOSE_FUNC(); + _close(i->thread_fd); + } + + free(i->buf); + + pthread_mutex_destroy(&i->mutex); + free(i); +} + +static fd_info *fd_info_ref(fd_info *i) { + assert(i); + + pthread_mutex_lock(&i->mutex); + assert(i->ref >= 1); + i->ref++; + +/* debug(__FILE__": ref++, now %i\n", i->ref); */ + pthread_mutex_unlock(&i->mutex); + + return i; +} + +static void fd_info_unref(fd_info *i) { + int r; + pthread_mutex_lock(&i->mutex); + assert(i->ref >= 1); + r = --i->ref; +/* debug(__FILE__": ref--, now %i\n", i->ref); */ + pthread_mutex_unlock(&i->mutex); + + if (r <= 0) + fd_info_free(i); +} + +static void context_state_cb(pa_context *c, void *userdata) { + fd_info *i = userdata; + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal(i->mainloop, 0); + break; + + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + } +} + +static void reset_params(fd_info *i) { + assert(i); + + i->sample_spec.format = PA_SAMPLE_ULAW; + i->sample_spec.channels = 1; + i->sample_spec.rate = 8000; + i->fragment_size = 1024; + i->n_fragments = 0; +} + +static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { + fd_info *i; + int sfds[2] = { -1, -1 }; + + debug(__FILE__": fd_info_new()\n"); + + signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ + + if (!(i = malloc(sizeof(fd_info)))) { + *_errno = ENOMEM; + goto fail; + } + + i->app_fd = i->thread_fd = -1; + i->type = type; + + i->mainloop = NULL; + i->context = NULL; + i->stream = NULL; + i->io_event = NULL; + pthread_mutex_init(&i->mutex, NULL); + i->ref = 1; + i->buf = NULL; + PA_LLIST_INIT(fd_info, i); + + reset_params(i); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfds) < 0) { + *_errno = errno; + debug(__FILE__": socket() failed: %s\n", strerror(errno)); + goto fail; + } + + i->app_fd = sfds[0]; + i->thread_fd = sfds[1]; + + if (!(i->mainloop = pa_threaded_mainloop_new())) { + *_errno = EIO; + debug(__FILE__": pa_threaded_mainloop_new() failed\n"); + goto fail; + } + + if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), "oss"))) { + *_errno = EIO; + debug(__FILE__": pa_context_new() failed\n"); + goto fail; + } + + pa_context_set_state_callback(i->context, context_state_cb, i); + + if (pa_context_connect(i->context, NULL, 0, NULL) < 0) { + *_errno = ECONNREFUSED; + debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + pa_threaded_mainloop_lock(i->mainloop); + + if (pa_threaded_mainloop_start(i->mainloop) < 0) { + *_errno = EIO; + debug(__FILE__": pa_threaded_mainloop_start() failed\n"); + goto unlock_and_fail; + } + + /* Wait until the context is ready */ + pa_threaded_mainloop_wait(i->mainloop); + + if (pa_context_get_state(i->context) != PA_CONTEXT_READY) { + *_errno = ECONNREFUSED; + debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto unlock_and_fail; + } + + pa_threaded_mainloop_unlock(i->mainloop); + return i; + +unlock_and_fail: + + pa_threaded_mainloop_unlock(i->mainloop); + +fail: + + if (i) + fd_info_unref(i); + + return NULL; +} + +static void fd_info_add_to_list(fd_info *i) { + assert(i); + + pthread_mutex_lock(&fd_infos_mutex); + PA_LLIST_PREPEND(fd_info, fd_infos, i); + pthread_mutex_unlock(&fd_infos_mutex); + + fd_info_ref(i); +} + +static void fd_info_remove_from_list(fd_info *i) { + assert(i); + + pthread_mutex_lock(&fd_infos_mutex); + PA_LLIST_REMOVE(fd_info, fd_infos, i); + pthread_mutex_unlock(&fd_infos_mutex); + + fd_info_unref(i); +} + +static fd_info* fd_info_find(int fd) { + fd_info *i; + + pthread_mutex_lock(&fd_infos_mutex); + + for (i = fd_infos; i; i = i->next) + if (i->app_fd == fd) { + fd_info_ref(i); + break; + } + + pthread_mutex_unlock(&fd_infos_mutex); + + return i; +} + +static void fix_metrics(fd_info *i) { + size_t fs; + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + fs = pa_frame_size(&i->sample_spec); + i->fragment_size = (i->fragment_size/fs)*fs; + + if (i->n_fragments < 2) + i->n_fragments = 12; + + if (i->fragment_size <= 0) + if ((i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments) <= 0) + i->fragment_size = 1024; + + debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + debug(__FILE__": fixated metrics to %i fragments, %i bytes each.\n", i->n_fragments, i->fragment_size); +} + +static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { + fd_info *i = userdata; + assert(s); + + if (i->io_event) { + pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_enable(i->io_event, PA_IO_EVENT_INPUT); + } +} + +static void stream_latency_update_cb(pa_stream *s, void *userdata) { + fd_info *i = userdata; + assert(s); + + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static void fd_info_shutdown(fd_info *i) { + assert(i); + + if (i->io_event) { + pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_free(i->io_event); + i->io_event = NULL; + } + + if (i->thread_fd >= 0) { + close(i->thread_fd); + i->thread_fd = -1; + } +} + +static int fd_info_copy_data(fd_info *i, int force) { + size_t n; + + if (!i->stream) + return -1; + + if ((n = pa_stream_writable_size(i->stream)) == (size_t) -1) { + debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + while (n >= i->fragment_size || force) { + ssize_t r; + + if (!i->buf) { + if (!(i->buf = malloc(i->fragment_size))) { + debug(__FILE__": malloc() failed.\n"); + return -1; + } + } + + if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) { + + if (errno == EAGAIN) + break; + + debug(__FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); + return -1; + } + + if (pa_stream_write(i->stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { + debug(__FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + i->buf = NULL; + + assert(n >= (size_t) r); + n -= r; + } + + if (i->io_event) { + pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_enable(i->io_event, n >= i->fragment_size ? PA_IO_EVENT_INPUT : 0); + } + + return 0; +} + +static void stream_state_cb(pa_stream *s, void * userdata) { + fd_info *i = userdata; + assert(s); + + switch (pa_stream_get_state(s)) { + + case PA_STREAM_READY: + debug(__FILE__": stream established.\n"); + break; + + case PA_STREAM_FAILED: + debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + fd_info_shutdown(i); + break; + + case PA_STREAM_TERMINATED: + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; + } +} + +static int create_stream(fd_info *i) { + pa_buffer_attr attr; + int n; + + assert(i); + + fix_metrics(i); + + if (!(i->stream = pa_stream_new(i->context, "audio stream", &i->sample_spec, NULL))) { + debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + pa_stream_set_state_callback(i->stream, stream_state_cb, i); + pa_stream_set_write_callback(i->stream, stream_request_cb, i); + pa_stream_set_latency_update_callback(i->stream, stream_latency_update_cb, i); + + memset(&attr, 0, sizeof(attr)); + attr.maxlength = i->fragment_size * (i->n_fragments+1); + attr.tlength = i->fragment_size * i->n_fragments; + attr.prebuf = i->fragment_size; + attr.minreq = i->fragment_size; + + if (pa_stream_connect_playback(i->stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { + debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + n = i->fragment_size; + setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); + n = i->fragment_size; + setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); + + return 0; + +fail: + return -1; +} + +static void free_stream(fd_info *i) { + assert(i); + + if (i->stream) { + pa_stream_disconnect(i->stream); + pa_stream_unref(i->stream); + i->stream = NULL; + } +} + +static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + fd_info *i = userdata; + + pa_threaded_mainloop_signal(i->mainloop, 0); + + if (flags & PA_IO_EVENT_INPUT) { + + if (!i->stream) { + api->io_enable(e, 0); + + if (create_stream(i) < 0) + goto fail; + + } else { + if (fd_info_copy_data(i, 0) < 0) + goto fail; + } + + } else if (flags & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) + goto fail; + + return; + +fail: + /* We can't do anything better than removing the event source */ + fd_info_shutdown(i); +} + +static int dsp_open(int flags, int *_errno) { + fd_info *i; + pa_mainloop_api *api; + int ret; + int f; + + if ((flags != O_WRONLY) && (flags != (O_WRONLY|O_NONBLOCK))) { + *_errno = EACCES; + return -1; + } + + if (!(i = fd_info_new(FD_INFO_PLAYBACK, _errno))) + return -1; + + shutdown(i->thread_fd, SHUT_WR); + shutdown(i->app_fd, SHUT_RD); + + if ((flags & O_NONBLOCK) == O_NONBLOCK) { + if ((f = fcntl(i->app_fd, F_GETFL)) >= 0) + fcntl(i->app_fd, F_SETFL, f|O_NONBLOCK); + } + if ((f = fcntl(i->thread_fd, F_GETFL)) >= 0) + fcntl(i->thread_fd, F_SETFL, f|O_NONBLOCK); + + fcntl(i->app_fd, F_SETFD, FD_CLOEXEC); + fcntl(i->thread_fd, F_SETFD, FD_CLOEXEC); + + pa_threaded_mainloop_lock(i->mainloop); + api = pa_threaded_mainloop_get_api(i->mainloop); + if (!(i->io_event = api->io_new(api, i->thread_fd, PA_IO_EVENT_INPUT, io_event_cb, i))) + goto fail; + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); + + fd_info_add_to_list(i); + ret = i->app_fd; + fd_info_unref(i); + + return ret; + +fail: + pa_threaded_mainloop_unlock(i->mainloop); + + if (i) + fd_info_unref(i); + + *_errno = EIO; + + debug(__FILE__": dsp_open() failed\n"); + + return -1; +} + +static int mixer_open(int flags, int *_errno) { +/* fd_info *i; */ + + *_errno = ENOSYS; + return -1; + +/* if (!(i = fd_info_new(FD_INFO_MIXER))) */ +/* return -1; */ + +} + +int open(const char *filename, int flags, ...) { + va_list args; + mode_t mode = 0; + int r, _errno = 0; + + va_start(args, flags); + if (flags & O_CREAT) + mode = va_arg(args, mode_t); + va_end(args); + + if (!function_enter()) { + LOAD_OPEN_FUNC(); + return _open(filename, flags, mode); + } + + debug(__FILE__": open()\n"); + + if (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0) { + r = dsp_open(flags, &_errno); + } else if (strcmp(filename, "/dev/mixer") == 0) { + r = mixer_open(flags, &_errno); + } else { + function_exit(); + LOAD_OPEN_FUNC(); + return _open(filename, flags, mode); + } + + function_exit(); + + if (_errno) + errno = _errno; + + return r; +} + +static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { + *_errno = ENOSYS; + return -1; +} + +static int map_format(int *fmt, pa_sample_spec *ss) { + + switch (*fmt) { + case AFMT_MU_LAW: + ss->format = PA_SAMPLE_ULAW; + break; + + case AFMT_A_LAW: + ss->format = PA_SAMPLE_ALAW; + break; + + case AFMT_S8: + *fmt = AFMT_U8; + /* fall through */ + case AFMT_U8: + ss->format = PA_SAMPLE_U8; + break; + + case AFMT_U16_BE: + *fmt = AFMT_S16_BE; + /* fall through */ + case AFMT_S16_BE: + ss->format = PA_SAMPLE_S16BE; + break; + + case AFMT_U16_LE: + *fmt = AFMT_S16_LE; + /* fall through */ + case AFMT_S16_LE: + ss->format = PA_SAMPLE_S16LE; + break; + + default: + ss->format = PA_SAMPLE_S16NE; + *fmt = AFMT_S16_NE; + break; + } + + return 0; +} + +static int map_format_back(pa_sample_format_t format) { + switch (format) { + case PA_SAMPLE_S16LE: return AFMT_S16_LE; + case PA_SAMPLE_S16BE: return AFMT_S16_BE; + case PA_SAMPLE_ULAW: return AFMT_MU_LAW; + case PA_SAMPLE_ALAW: return AFMT_A_LAW; + case PA_SAMPLE_U8: return AFMT_U8; + default: + abort(); + } +} + +static void success_cb(pa_stream *s, int success, void *userdata) { + fd_info *i = userdata; + + assert(s); + assert(i); + + i->operation_success = success; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static int dsp_empty_socket(fd_info *i) { + int ret = -1; + + /* Empty the socket */ + for (;;) { + int l; + + if (i->thread_fd < 0) + break; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + break; + } + + if (!l) + break; + + pa_threaded_mainloop_wait(i->mainloop); + } + + return ret; +} + +static int dsp_drain(fd_info *i) { + pa_operation *o = NULL; + int r = -1; + + if (!i->mainloop) + return 0; + + debug(__FILE__": Draining.\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + if (dsp_empty_socket(i) < 0) + goto fail; + + if (!i->stream) + goto fail; + + debug(__FILE__": Really draining.\n"); + + if (!(o = pa_stream_drain(i->stream, success_cb, i))) { + debug(__FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) + goto fail; + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (!i->operation_success) { + debug(__FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + r = 0; + +fail: + + if (o) + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(i->mainloop); + + return 0; +} + +static int dsp_trigger(fd_info *i) { + pa_operation *o = NULL; + int r = -1; + + fd_info_copy_data(i, 1); + + if (!i->stream) + return 0; + + pa_threaded_mainloop_lock(i->mainloop); + + if (dsp_empty_socket(i) < 0) + goto fail; + + debug(__FILE__": Triggering.\n"); + + if (!(o = pa_stream_trigger(i->stream, success_cb, i))) { + debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + i->operation_success = 0; + while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) + goto fail; + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (!i->operation_success) { + debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + r = 0; + +fail: + + if (o) + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(i->mainloop); + + return 0; +} + +static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { + int ret = -1; + + switch (request) { + case SNDCTL_DSP_SETFMT: { + debug(__FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + if (*(int*) argp == AFMT_QUERY) + *(int*) argp = map_format_back(i->sample_spec.format); + else { + map_format((int*) argp, &i->sample_spec); + free_stream(i); + } + + pa_threaded_mainloop_unlock(i->mainloop); + break; + } + + case SNDCTL_DSP_SPEED: { + pa_sample_spec ss; + int valid; + + debug(__FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + ss = i->sample_spec; + ss.rate = *(int*) argp; + + if ((valid = pa_sample_spec_valid(&ss))) { + i->sample_spec = ss; + free_stream(i); + } + + pa_threaded_mainloop_unlock(i->mainloop); + + if (!valid) { + *_errno = EINVAL; + goto fail; + } + + break; + } + + case SNDCTL_DSP_STEREO: + debug(__FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + i->sample_spec.channels = *(int*) argp ? 2 : 1; + free_stream(i); + + pa_threaded_mainloop_unlock(i->mainloop); + return 0; + + case SNDCTL_DSP_CHANNELS: { + pa_sample_spec ss; + int valid; + + debug(__FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + ss = i->sample_spec; + ss.channels = *(int*) argp; + + if ((valid = pa_sample_spec_valid(&ss))) { + i->sample_spec = ss; + free_stream(i); + } + + pa_threaded_mainloop_unlock(i->mainloop); + + if (!valid) { + *_errno = EINVAL; + goto fail; + } + + break; + } + + case SNDCTL_DSP_GETBLKSIZE: + debug(__FILE__": SNDCTL_DSP_GETBLKSIZE\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + fix_metrics(i); + *(int*) argp = i->fragment_size; + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SNDCTL_DSP_SETFRAGMENT: + debug(__FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + i->fragment_size = 1 << (*(int*) argp); + i->n_fragments = (*(int*) argp) >> 16; + + free_stream(i); + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SNDCTL_DSP_GETCAPS: + debug(__FILE__": SNDCTL_DSP_CAPS\n"); + + *(int*) argp = DSP_CAP_MULTI; + break; + + case SNDCTL_DSP_GETODELAY: { + int l; + + debug(__FILE__": SNDCTL_DSP_GETODELAY\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + *(int*) argp = 0; + + for (;;) { + pa_usec_t usec; + if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) + break; + + if (pa_stream_get_latency(i->stream, &usec, NULL) >= 0) { + *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec); + break; + } + + if (pa_context_errno(i->context) != PA_ERR_NODATA) { + debug(__FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); + break; + } + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) + debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + else + *(int*) argp += l; + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": ODELAY: %i\n", *(int*) argp); + + break; + } + + case SNDCTL_DSP_RESET: { + debug(__FILE__": SNDCTL_DSP_RESET\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + free_stream(i); + reset_params(i); + + pa_threaded_mainloop_unlock(i->mainloop); + break; + } + + case SNDCTL_DSP_GETFMTS: { + debug(__FILE__": SNDCTL_DSP_GETFMTS\n"); + + *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE; + break; + } + + case SNDCTL_DSP_POST: + debug(__FILE__": SNDCTL_DSP_POST\n"); + + if (dsp_trigger(i) < 0) + *_errno = EIO; + break; + + case SNDCTL_DSP_SYNC: + debug(__FILE__": SNDCTL_DSP_SYNC\n"); + + if (dsp_drain(i) < 0) + *_errno = EIO; + + break; + + case SNDCTL_DSP_GETOSPACE: { + audio_buf_info *bi = (audio_buf_info*) argp; + int l; + size_t k = 0; + + debug(__FILE__": SNDCTL_DSP_GETOSPACE\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + fix_metrics(i); + + if (i->stream) { + if ((k = pa_stream_writable_size(i->stream)) == (size_t) -1) + debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + } else + k = i->fragment_size * i->n_fragments; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + l = 0; + } + + bi->fragsize = i->fragment_size; + bi->fragstotal = i->n_fragments; + bi->bytes = k > (size_t) l ? k - l : 0; + bi->fragments = bi->bytes / bi->fragsize; + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments); + + break; + } + + default: + debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + + *_errno = EINVAL; + goto fail; + } + + ret = 0; + +fail: + + return ret; +} + +int ioctl(int fd, unsigned long request, ...) { + fd_info *i; + va_list args; + void *argp; + int r, _errno = 0; + + debug(__FILE__": ioctl()\n"); + + va_start(args, request); + argp = va_arg(args, void *); + va_end(args); + + if (!function_enter()) { + LOAD_IOCTL_FUNC(); + return _ioctl(fd, request, argp); + } + + if (!(i = fd_info_find(fd))) { + function_exit(); + LOAD_IOCTL_FUNC(); + return _ioctl(fd, request, argp); + } + + if (i->type == FD_INFO_MIXER) + r = mixer_ioctl(i, request, argp, &_errno); + else + r = dsp_ioctl(i, request, argp, &_errno); + + fd_info_unref(i); + + if (_errno) + errno = _errno; + + function_exit(); + + return r; +} + +int close(int fd) { + fd_info *i; + + debug(__FILE__": close()\n"); + + if (!function_enter()) { + LOAD_CLOSE_FUNC(); + return _close(fd); + } + + if (!(i = fd_info_find(fd))) { + function_exit(); + LOAD_CLOSE_FUNC(); + return _close(fd); + } + + fd_info_remove_from_list(i); + fd_info_unref(i); + + function_exit(); + + return 0; +} + +int open64(const char *filename, int flags, ...) { + va_list args; + mode_t mode = 0; + + debug(__FILE__": open64()\n"); + + va_start(args, flags); + if (flags & O_CREAT) + mode = va_arg(args, mode_t); + va_end(args); + + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_OPEN64_FUNC(); + return _open64(filename, flags, mode); + } + + return open(filename, flags, mode); +} + +FILE* fopen(const char *filename, const char *mode) { + FILE *f = NULL; + int fd; + + debug(__FILE__": fopen()\n"); + + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_FOPEN_FUNC(); + return _fopen(filename, mode); + } + + if (strcmp(mode, "wb") != 0) { + errno = EACCES; + return NULL; + } + + if ((fd = open(filename, O_WRONLY)) < 0) + return NULL; + + if (!(f = fdopen(fd, "wb"))) { + close(fd); + return NULL; + } + + return f; +} + +FILE *fopen64(const char *filename, const char *mode) { + + debug(__FILE__": fopen64()\n"); + + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_FOPEN64_FUNC(); + return _fopen64(filename, mode); + } + + return fopen(filename, mode); +} + +int fclose(FILE *f) { + fd_info *i; + + debug(__FILE__": fclose()\n"); + + if (!function_enter()) { + LOAD_FCLOSE_FUNC(); + return _fclose(f); + } + + if (!(i = fd_info_find(fileno(f)))) { + function_exit(); + LOAD_FCLOSE_FUNC(); + return _fclose(f); + } + + fd_info_remove_from_list(i); + + /* Dirty trick to avoid that the fd is not freed twice, once by us + * and once by the real fclose() */ + i->app_fd = -1; + + fd_info_unref(i); + + function_exit(); + + LOAD_FCLOSE_FUNC(); + return _fclose(f); +} diff --git a/src/utils/padsp.in b/src/utils/padsp.in new file mode 100644 index 00000000..d82e92fe --- /dev/null +++ b/src/utils/padsp.in @@ -0,0 +1,30 @@ +#!/bin/sh + +# $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 Lesser 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 Lesser 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. + +if [ x"$LD_PRELOAD" = x ] ; then + LD_PRELOAD="@LIBPOLYPDSP@" +else + LD_PRELOAD="$LD_PRELOAD @LIBPOLYPDSP@" +fi + +export LD_PRELOAD + +exec "$@" -- cgit From 7906985d2af27a187eac7260f641a07c39bb705e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 23 May 2006 15:24:29 +0000 Subject: Cast size_t to long to be more compatible with 64-bit systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@951 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 06bdd575..63f79eb1 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -417,7 +417,7 @@ static void fix_metrics(fd_info *i) { i->fragment_size = 1024; debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); - debug(__FILE__": fixated metrics to %i fragments, %i bytes each.\n", i->n_fragments, i->fragment_size); + debug(__FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); } static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { -- cgit From e99afdae388018f119c16c3a331e01898ab9a90a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 16:37:33 +0000 Subject: pass the binary name as client name to polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@952 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 63f79eb1..ec073a28 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -278,9 +278,21 @@ static void reset_params(fd_info *i) { i->n_fragments = 0; } +static char *client_name(char *buf, size_t n) { + char p[PATH_MAX]; + + if (pa_get_binary_name(p, sizeof(p))) + snprintf(buf, n, "oss[%s]", pa_path_get_filename(p)); + else + snprintf(buf, n, "oss"); + + return buf; +} + static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { fd_info *i; int sfds[2] = { -1, -1 }; + char name[64]; debug(__FILE__": fd_info_new()\n"); @@ -320,7 +332,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { goto fail; } - if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), "oss"))) { + if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), client_name(name, sizeof(name))))) { *_errno = EIO; debug(__FILE__": pa_context_new() failed\n"); goto fail; -- cgit From 23b123d361959553fc9e467dd4b605adee00f07e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 23:06:28 +0000 Subject: - use pthread_atfork() to disable open sound streams in the child after a fork. Obviusly sound won't work in child process but at least we don't leak fds from the parent. Now any operation on the device fd in the child will result in an EBADF error, which seems somewhat clean to me. - flush our unix socket properly on RESET ioctl git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@953 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 6 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index ec073a28..a69676ab 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -60,6 +60,7 @@ typedef struct fd_info fd_info; struct fd_info { pthread_mutex_t mutex; int ref; + int unusable; fd_info_type_t type; int app_fd, thread_fd; @@ -82,6 +83,7 @@ struct fd_info { }; static int dsp_drain(fd_info *i); +static void fd_info_remove_from_list(fd_info *i); static pthread_mutex_t fd_infos_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t func_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -289,14 +291,101 @@ static char *client_name(char *buf, size_t n) { return buf; } +static void atfork_prepare(void) { + fd_info *i; + + debug(__FILE__": atfork_prepare() enter\n"); + + function_enter(); + + pthread_mutex_lock(&fd_infos_mutex); + + for (i = fd_infos; i; i = i->next) { + pthread_mutex_lock(&i->mutex); + pa_threaded_mainloop_lock(i->mainloop); + } + + pthread_mutex_lock(&func_mutex); + + + debug(__FILE__": atfork_prepare() exit\n"); +} + +static void atfork_parent(void) { + fd_info *i; + + debug(__FILE__": atfork_parent() enter\n"); + + pthread_mutex_unlock(&func_mutex); + + for (i = fd_infos; i; i = i->next) { + pa_threaded_mainloop_unlock(i->mainloop); + pthread_mutex_unlock(&i->mutex); + } + + pthread_mutex_unlock(&fd_infos_mutex); + + function_exit(); + + debug(__FILE__": atfork_parent() exit\n"); +} + +static void atfork_child(void) { + fd_info *i; + + debug(__FILE__": atfork_child() enter\n"); + + /* We do only the bare minimum to get all fds closed */ + pthread_mutex_init(&func_mutex, NULL); + pthread_mutex_init(&fd_infos_mutex, NULL); + + for (i = fd_infos; i; i = i->next) { + pthread_mutex_init(&i->mutex, NULL); + + if (i->context) { + pa_context_disconnect(i->context); + pa_context_unref(i->context); + i->context = NULL; + } + + if (i->stream) { + pa_stream_unref(i->stream); + i->stream = NULL; + } + + if (i->app_fd >= 0) { + close(i->app_fd); + i->app_fd = -1; + } + + if (i->thread_fd >= 0) { + close(i->thread_fd); + i->thread_fd = -1; + } + + i->unusable = 1; + } + + function_exit(); + + debug(__FILE__": atfork_child() exit\n"); +} + +static void install_atfork(void) { + pthread_atfork(atfork_prepare, atfork_parent, atfork_child); +} + static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { fd_info *i; int sfds[2] = { -1, -1 }; char name[64]; + static pthread_once_t install_atfork_once = PTHREAD_ONCE_INIT; debug(__FILE__": fd_info_new()\n"); signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ + + pthread_once(&install_atfork_once, install_atfork); if (!(i = malloc(sizeof(fd_info)))) { *_errno = ENOMEM; @@ -313,6 +402,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { pthread_mutex_init(&i->mutex, NULL); i->ref = 1; i->buf = NULL; + i->unusable = 0; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -404,7 +494,7 @@ static fd_info* fd_info_find(int fd) { pthread_mutex_lock(&fd_infos_mutex); for (i = fd_infos; i; i = i->next) - if (i->app_fd == fd) { + if (i->app_fd == fd && !i->unusable) { fd_info_ref(i); break; } @@ -546,7 +636,7 @@ static int create_stream(fd_info *i) { fix_metrics(i); - if (!(i->stream = pa_stream_new(i->context, "audio stream", &i->sample_spec, NULL))) { + if (!(i->stream = pa_stream_new(i->context, "Audio Stream", &i->sample_spec, NULL))) { debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -784,6 +874,30 @@ static void success_cb(pa_stream *s, int success, void *userdata) { pa_threaded_mainloop_signal(i->mainloop, 0); } +static int dsp_flush_socket(fd_info *i) { + int l; + + if (i->thread_fd < 0) + return -1; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + return -1; + } + + while (l > 0) { + char buf[1024]; + size_t k; + + k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l; + if (read(i->thread_fd, buf, k) < 0) + debug(__FILE__": read(): %s\n", strerror(errno)); + l -= k; + } + + return 0; +} + static int dsp_empty_socket(fd_info *i) { int ret = -1; @@ -791,7 +905,7 @@ static int dsp_empty_socket(fd_info *i) { for (;;) { int l; - if (i->thread_fd < 0) + if (i->thread_fd < 0 || !i->stream) break; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { @@ -861,8 +975,6 @@ static int dsp_trigger(fd_info *i) { pa_operation *o = NULL; int r = -1; - fd_info_copy_data(i, 1); - if (!i->stream) return 0; @@ -926,6 +1038,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_SPEED: { pa_sample_spec ss; int valid; + char t[256]; debug(__FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); @@ -939,13 +1052,15 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_stream(i); } + debug(__FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + pa_threaded_mainloop_unlock(i->mainloop); if (!valid) { *_errno = EINVAL; goto fail; } - + break; } @@ -1063,6 +1178,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); free_stream(i); + dsp_flush_socket(i); reset_params(i); pa_threaded_mainloop_unlock(i->mainloop); -- cgit From 46fee4641864df8972beb95f9d9af5670198add9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 23:57:50 +0000 Subject: implement emulation of /dev/sndstat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@954 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 15 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index a69676ab..ed34ac8a 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -771,11 +771,83 @@ static int mixer_open(int flags, int *_errno) { } +static int sndstat_open(int flags, int *_errno) { + static const char sndstat[] = + "Sound Driver:3.8.1a-980706 (Polypaudio Virtual OSS)\n" + "Kernel: POSIX\n" + "Config options: 0\n" + "\n" + "Installed drivers:\n" + "Type 255: Polypaudio Virtual OSS\n" + "\n" + "Card config:\n" + "Polypaudio Virtual OSS\n" + "\n" + "Audio devices:\n" + "0: Polypaudio Virtual OSS\n" + "\n" + "Synth devices: NOT ENABLED IN CONFIG\n" + "\n" + "Midi devices:\n" + "\n" + "Timers:\n" + "\n" + "\Mixers:\n" + "0: Polypaudio Virtual OSS\n"; + + char fn[] = "/tmp/padsp-sndstat-XXXXXX"; + mode_t u; + int fd = -1; + int e; + + debug(__FILE__": sndstat_open()\n"); + + if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) { + *_errno = EACCES; + debug(__FILE__": bad access!\n"); + goto fail; + } + + u = umask(0077); + fd = mkstemp(fn); + e = errno; + umask(u); + + if (fd < 0) { + *_errno = e; + debug(__FILE__": mkstemp() failed: %s\n", strerror(errno)); + goto fail; + } + + unlink(fn); + + if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) { + *_errno = errno; + debug(__FILE__": write() failed: %s\n", strerror(errno)); + goto fail; + } + + if (lseek(fd, SEEK_SET, 0) < 0) { + *_errno = errno; + debug(__FILE__": lseek() failed: %s\n", strerror(errno)); + goto fail; + } + + return fd; + +fail: + if (fd >= 0) + close(fd); + return -1; +} + int open(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; int r, _errno = 0; + debug(__FILE__": open(%s)\n", filename); + va_start(args, flags); if (flags & O_CREAT) mode = va_arg(args, mode_t); @@ -786,12 +858,12 @@ int open(const char *filename, int flags, ...) { return _open(filename, flags, mode); } - debug(__FILE__": open()\n"); - if (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0) { r = dsp_open(flags, &_errno); } else if (strcmp(filename, "/dev/mixer") == 0) { r = mixer_open(flags, &_errno); + } else if (strcmp(filename, "/dev/sndstat") == 0) { + r = sndstat_open(flags, &_errno); } else { function_exit(); LOAD_OPEN_FUNC(); @@ -1321,7 +1393,7 @@ int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; - debug(__FILE__": open64()\n"); + debug(__FILE__": open64(%s)\n", filename); va_start(args, flags); if (flags & O_CREAT) @@ -1330,6 +1402,7 @@ int open64(const char *filename, int flags, ...) { if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && strcmp(filename, "/dev/mixer") != 0) { LOAD_OPEN64_FUNC(); return _open64(filename, flags, mode); @@ -1341,25 +1414,38 @@ int open64(const char *filename, int flags, ...) { FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; + mode_t m; + + debug(__FILE__": fopen(%s)\n", filename); - debug(__FILE__": fopen()\n"); + if (strcmp(filename, "/dev/dsp") == 0 || + strcmp(filename, "/dev/adsp") == 0) { - if (strcmp(filename, "/dev/dsp") != 0 && - strcmp(filename, "/dev/adsp") != 0 && - strcmp(filename, "/dev/mixer") != 0) { + if (strcmp(mode, "wb") != 0) { + errno = EACCES; + return NULL; + } + + m = O_WRONLY; + } else if (strcmp(filename, "/dev/sndstat") == 0) { + + if (strcmp(mode, "r") != 0) { + errno = EACCES; + return NULL; + } + + m = O_RDONLY; + } else if (strcmp(filename, "/dev/mixer") != 0) + m = O_RDWR; + else { LOAD_FOPEN_FUNC(); return _fopen(filename, mode); } - if (strcmp(mode, "wb") != 0) { - errno = EACCES; - return NULL; - } - - if ((fd = open(filename, O_WRONLY)) < 0) + if ((fd = open(filename, m)) < 0) return NULL; - if (!(f = fdopen(fd, "wb"))) { + if (!(f = fdopen(fd, mode))) { close(fd); return NULL; } @@ -1369,10 +1455,11 @@ FILE* fopen(const char *filename, const char *mode) { FILE *fopen64(const char *filename, const char *mode) { - debug(__FILE__": fopen64()\n"); + debug(__FILE__": fopen64(%s)\n", filename); if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && strcmp(filename, "/dev/mixer") != 0) { LOAD_FOPEN64_FUNC(); return _fopen64(filename, mode); -- cgit From 440b901a4d445de6695e3fa41853a694d677516e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 May 2006 00:42:30 +0000 Subject: fix playback of small sound files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@955 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index ed34ac8a..d9325df4 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -977,7 +977,7 @@ static int dsp_empty_socket(fd_info *i) { for (;;) { int l; - if (i->thread_fd < 0 || !i->stream) + if (i->thread_fd < 0) break; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { @@ -985,8 +985,10 @@ static int dsp_empty_socket(fd_info *i) { break; } - if (!l) + if (!l) { + ret = 0; break; + } pa_threaded_mainloop_wait(i->mainloop); } -- cgit From ca08e57470d0a6ce1bcbfb853288aa7d3a08efe1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 May 2006 02:13:29 +0000 Subject: implement a /dev/mixer interface git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@956 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 286 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 261 insertions(+), 25 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d9325df4..b85d9c4d 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -79,6 +79,10 @@ struct fd_info { int operation_success; + pa_cvolume volume; + uint32_t sink_index; + int volume_modify_count; + PA_LLIST_FIELDS(fd_info); }; @@ -154,6 +158,21 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \ +if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ + debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + goto label; \ +} \ +} while(0); + +#define STREAM_CHECK_DEAD_GOTO(i, label) do { \ +if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ + !(i)->stream || pa_stream_get_state((i)->stream) != PA_STREAM_READY) { \ + debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + goto label; \ +} \ +} while(0); + static void debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); static void debug(const char *format, ...) { @@ -375,6 +394,26 @@ static void install_atfork(void) { pthread_atfork(atfork_prepare, atfork_parent, atfork_child); } +static void stream_success_cb(pa_stream *s, int success, void *userdata) { + fd_info *i = userdata; + + assert(s); + assert(i); + + i->operation_success = success; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static void context_success_cb(pa_context *c, int success, void *userdata) { + fd_info *i = userdata; + + assert(c); + assert(i); + + i->operation_success = success; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { fd_info *i; int sfds[2] = { -1, -1 }; @@ -403,6 +442,9 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->ref = 1; i->buf = NULL; i->unusable = 0; + pa_cvolume_reset(&i->volume, 2); + i->volume_modify_count = 0; + i->sink_index = (uint32_t) -1; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -760,15 +802,118 @@ fail: return -1; } +static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, void *userdata) { + fd_info *i = userdata; + + if (!si && eol < 0) { + i->operation_success = 0; + pa_threaded_mainloop_signal(i->mainloop, 0); + return; + } + + if (eol) + return; + + if (!pa_cvolume_equal(&i->volume, &si->volume)) + i->volume_modify_count++; + + i->volume = si->volume; + i->sink_index = si->index; + + i->operation_success = 1; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + fd_info *i = userdata; + pa_operation *o = NULL; + + if (i->sink_index != idx) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + if (!(o = pa_context_get_sink_info_by_index(i->context, i->sink_index, sink_info_cb, i))) { + debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + return; + } + + pa_operation_unref(o); +} + static int mixer_open(int flags, int *_errno) { -/* fd_info *i; */ + fd_info *i; + pa_operation *o; + int ret; - *_errno = ENOSYS; - return -1; + if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) + return -1; + + pa_threaded_mainloop_lock(i->mainloop); + + pa_context_set_subscribe_callback(i->context, subscribe_cb, i); + + if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK, context_success_cb, i))) { + debug(__FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(i->mainloop); + CONTEXT_CHECK_DEAD_GOTO(i, fail); + } + + if (!i->operation_success) { + debug(__FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + /* Get sink info */ + + pa_operation_unref(o); + if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) { + debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } -/* if (!(i = fd_info_new(FD_INFO_MIXER))) */ -/* return -1; */ + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(i->mainloop); + CONTEXT_CHECK_DEAD_GOTO(i, fail); + } + + if (!i->operation_success) { + debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); + + fd_info_add_to_list(i); + ret = i->app_fd; + fd_info_unref(i); + + return ret; + +fail: + pa_threaded_mainloop_unlock(i->mainloop); + if (i) + fd_info_unref(i); + + *_errno = EIO; + + debug(__FILE__": mixer_open() failed\n"); + + return -1; } static int sndstat_open(int flags, int *_errno) { @@ -879,8 +1024,109 @@ int open(const char *filename, int flags, ...) { } static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { - *_errno = ENOSYS; - return -1; + int ret = -1; + + switch (request) { + case SOUND_MIXER_READ_DEVMASK : + debug(__FILE__": SOUND_MIXER_READ_DEVMASK\n"); + + *(int*) argp = SOUND_MASK_PCM; + break; + + case SOUND_MIXER_READ_RECMASK : + debug(__FILE__": SOUND_MIXER_READ_RECMASK\n"); + + *(int*) argp = 0; + break; + + case SOUND_MIXER_READ_STEREODEVS: + debug(__FILE__": SOUND_MIXER_READ_STEREODEVS\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = i->volume.channels > 1 ? SOUND_MASK_PCM : 0; + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SOUND_MIXER_READ_RECSRC: + debug(__FILE__": SOUND_MIXER_READ_RECSRC\n"); + + *(int*) argp = 0; + break; + + case SOUND_MIXER_CAPS: + debug(__FILE__": SOUND_MIXER_CAPS\n"); + + *(int*) argp = 0; + break; + + case SOUND_MIXER_READ_PCM: + + debug(__FILE__": SOUND_MIXER_READ_PCM\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + *(int*) argp = + ((i->volume.values[0]*100/PA_VOLUME_NORM) << 8) | + ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM)); + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SOUND_MIXER_WRITE_PCM: { + pa_cvolume v; + + debug(__FILE__": SOUND_MIXER_WRITE_PCM\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + v = i->volume; + + i->volume.values[0] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; + i->volume.values[1] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + + if (!pa_cvolume_equal(&i->volume, &v)) { + pa_operation *o; + + if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) + debug(__FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); + else + pa_operation_unref(o); + + /* We don't wait for completion here */ + i->volume_modify_count++; + } + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + } + + case SOUND_MIXER_INFO: { + mixer_info *mi = argp; + + memset(mi, 0, sizeof(mixer_info)); + strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); + strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name)); + pa_threaded_mainloop_lock(i->mainloop); + mi->modify_counter = i->volume_modify_count; + pa_threaded_mainloop_unlock(i->mainloop); + break; + } + + default: + debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + + *_errno = EINVAL; + goto fail; + } + + ret = 0; + +fail: + + return ret; } static int map_format(int *fmt, pa_sample_spec *ss) { @@ -936,16 +1182,6 @@ static int map_format_back(pa_sample_format_t format) { } } -static void success_cb(pa_stream *s, int success, void *userdata) { - fd_info *i = userdata; - - assert(s); - assert(i); - - i->operation_success = success; - pa_threaded_mainloop_signal(i->mainloop, 0); -} - static int dsp_flush_socket(fd_info *i) { int l; @@ -1015,15 +1251,14 @@ static int dsp_drain(fd_info *i) { debug(__FILE__": Really draining.\n"); - if (!(o = pa_stream_drain(i->stream, success_cb, i))) { + if (!(o = pa_stream_drain(i->stream, stream_success_cb, i))) { debug(__FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) - goto fail; + STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1059,15 +1294,14 @@ static int dsp_trigger(fd_info *i) { debug(__FILE__": Triggering.\n"); - if (!(o = pa_stream_trigger(i->stream, success_cb, i))) { + if (!(o = pa_stream_trigger(i->stream, stream_success_cb, i))) { debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { - if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) - goto fail; + STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1218,8 +1452,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) for (;;) { pa_usec_t usec; - if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) - break; + + STREAM_CHECK_DEAD_GOTO(i, exit_loop); if (pa_stream_get_latency(i->stream, &usec, NULL) >= 0) { *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec); @@ -1234,6 +1468,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_wait(i->mainloop); } + exit_loop: + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); else -- cgit From c4328cdfddb16cf43ae4037b087cf2c58d7c531d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 24 May 2006 08:14:19 +0000 Subject: Fix stray \ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@957 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b85d9c4d..10b08eae 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -937,7 +937,7 @@ static int sndstat_open(int flags, int *_errno) { "\n" "Timers:\n" "\n" - "\Mixers:\n" + "Mixers:\n" "0: Polypaudio Virtual OSS\n"; char fn[] = "/tmp/padsp-sndstat-XXXXXX"; -- cgit From 3fa19ab457ff71d148a6dff5eb7362582e82ce61 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 24 May 2006 13:23:15 +0000 Subject: Fix warnings. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@959 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 10b08eae..87d0b257 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -102,11 +102,18 @@ static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; static int (*_fclose)(FILE *f) = NULL; +/* dlsym() violates ISO C, so confide the breakage into this function to + * avoid warnings. */ +typedef void (*fnptr)(void); +static inline fnptr dlsym_fn(void *handle, const char *symbol) { + return (fnptr) (long) dlsym(handle, symbol); +} + #define LOAD_IOCTL_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_ioctl) \ - _ioctl = (int (*)(int, int, void*)) dlsym(RTLD_NEXT, "ioctl"); \ + _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -114,7 +121,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_open) \ - _open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open"); \ + _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -122,7 +129,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_open64) \ - _open64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open64"); \ + _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -130,7 +137,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_close) \ - _close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); \ + _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -138,7 +145,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_fopen) \ - _fopen = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen"); \ + _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -146,7 +153,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_fopen64) \ - _fopen64 = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen64"); \ + _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -154,7 +161,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_fclose) \ - _fclose = (int (*)(FILE *)) dlsym(RTLD_NEXT, "fclose"); \ + _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) -- cgit From 59d00e2f49f709630cd3c55b28e752fa5d7919fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 00:25:03 +0000 Subject: * issue volume updates syncrhonously * correct channel order of OSS volumes (swap left,right) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@962 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 87d0b257..d372b697 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1074,8 +1074,8 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = - ((i->volume.values[0]*100/PA_VOLUME_NORM) << 8) | - ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM)); + ((i->volume.values[0]*100/PA_VOLUME_NORM)) | + ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8); pa_threaded_mainloop_unlock(i->mainloop); @@ -1090,16 +1090,29 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno v = i->volume; - i->volume.values[0] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; - i->volume.values[1] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + i->volume.values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + i->volume.values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; if (!pa_cvolume_equal(&i->volume, &v)) { pa_operation *o; if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) debug(__FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); - else + else { + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + CONTEXT_CHECK_DEAD_GOTO(i, exit_loop); + + pa_threaded_mainloop_wait(i->mainloop); + } + exit_loop: + + if (!i->operation_success) + debug(__FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); + pa_operation_unref(o); + } /* We don't wait for completion here */ i->volume_modify_count++; -- cgit From 2bb05ea6678ff27f37ac082d01dcb9fd14889613 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 00:40:04 +0000 Subject: fix evil, evil typo that cause all gtk2 based apps to crash git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@963 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d372b697..746965d7 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1693,7 +1693,7 @@ FILE* fopen(const char *filename, const char *mode) { } m = O_RDONLY; - } else if (strcmp(filename, "/dev/mixer") != 0) + } else if (strcmp(filename, "/dev/mixer") == 0) m = O_RDWR; else { LOAD_FOPEN_FUNC(); -- cgit From 2bbd7bac63a48361d3d848ba1d3838a0ef5eb2bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 01:14:06 +0000 Subject: add support to disable emulation of /dev/dsp,/dev/mixer,/dev/sndstat selectively by either passing an environment variable or by defining a symbol __padsp_disable__ in the process git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@964 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 746965d7..2f0f7260 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -191,6 +191,61 @@ static void debug(const char *format, ...) { } } +static int padsp_disabled(void) { + static int *sym; + static int sym_resolved = 0; + + /* If the current process has a symbol __padsp_disabled__ we use + * it to detect whether we should enable our stuff or not. A + * program needs to be compiled with -rdynamic for this to work! + * The symbol must be an int containing a three bit bitmask: bit 1 + * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat + * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value + * 7 disables padsp entirely. */ + + pthread_mutex_lock(&func_mutex); + if (!sym_resolved) { + sym = (int*) dlsym_fn(RTLD_DEFAULT, "__padsp_disabled__"); + sym_resolved = 1; + + } + pthread_mutex_unlock(&func_mutex); + + if (!sym) + return 0; + + return *sym; +} + +static int dsp_cloak_enable(void) { + if (padsp_disabled() & 1) + return 0; + + if (getenv("PADSP_NO_DSP")) + return 0; + + return 1; +} + +static int sndstat_cloak_enable(void) { + if (padsp_disabled() & 2) + return 0; + + if (getenv("PADSP_NO_SNDSTAT")) + return 0; + + return 1; +} + +static int mixer_cloak_enable(void) { + if (padsp_disabled() & 4) + return 0; + + if (getenv("PADSP_NO_MIXER")) + return 0; + + return 1; +} static pthread_key_t recursion_key; static void recursion_key_alloc(void) { @@ -1010,11 +1065,11 @@ int open(const char *filename, int flags, ...) { return _open(filename, flags, mode); } - if (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0) { + if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) { r = dsp_open(flags, &_errno); - } else if (strcmp(filename, "/dev/mixer") == 0) { + } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) { r = mixer_open(flags, &_errno); - } else if (strcmp(filename, "/dev/sndstat") == 0) { + } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) { r = sndstat_open(flags, &_errno); } else { function_exit(); -- cgit From ae80ab396e9aa764b16b436b7b7c66011dce513c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 01:19:56 +0000 Subject: read stream and client name from $PADSP_STREAM_NAME resp. $PADSP_CLIENT_NAME, if available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@965 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 2f0f7260..5987ec5f 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -201,7 +201,7 @@ static int padsp_disabled(void) { * The symbol must be an int containing a three bit bitmask: bit 1 * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value - * 7 disables padsp entirely. */ + * of 7 disables padsp entirely. */ pthread_mutex_lock(&func_mutex); if (!sym_resolved) { @@ -363,15 +363,28 @@ static void reset_params(fd_info *i) { static char *client_name(char *buf, size_t n) { char p[PATH_MAX]; + const char *e; + + if ((e = getenv("PADSP_CLIENT_NAME"))) + return e; if (pa_get_binary_name(p, sizeof(p))) - snprintf(buf, n, "oss[%s]", pa_path_get_filename(p)); + snprintf(buf, n, "OSS Emulation[%s]", pa_path_get_filename(p)); else - snprintf(buf, n, "oss"); + snprintf(buf, n, "OSS"); return buf; } +static char *stream_name(void) { + const char *e; + + if ((e = getenv("PADSP_STREAM_NAME"))) + return e; + + return "Audio Stream"; +} + static void atfork_prepare(void) { fd_info *i; @@ -740,7 +753,7 @@ static int create_stream(fd_info *i) { fix_metrics(i); - if (!(i->stream = pa_stream_new(i->context, "Audio Stream", &i->sample_spec, NULL))) { + if (!(i->stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } -- cgit From 0387b30994185a44e6df737c529ddda24325c671 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 13:56:14 +0000 Subject: Use only the basename of libpolypdsp.so so that it will work on multi-arch systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@969 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 30 ++++++++++++++++++++++++++++++ src/utils/padsp.in | 30 ------------------------------ 2 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 src/utils/padsp delete mode 100644 src/utils/padsp.in (limited to 'src/utils') diff --git a/src/utils/padsp b/src/utils/padsp new file mode 100644 index 00000000..9f38cf3d --- /dev/null +++ b/src/utils/padsp @@ -0,0 +1,30 @@ +#!/bin/sh + +# $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 Lesser 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 Lesser 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. + +if [ x"$LD_PRELOAD" = x ] ; then + LD_PRELOAD="libpolypdsp.so" +else + LD_PRELOAD="$LD_PRELOAD libpolypdsp.so" +fi + +export LD_PRELOAD + +exec "$@" diff --git a/src/utils/padsp.in b/src/utils/padsp.in deleted file mode 100644 index d82e92fe..00000000 --- a/src/utils/padsp.in +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -# $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 Lesser 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 Lesser 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. - -if [ x"$LD_PRELOAD" = x ] ; then - LD_PRELOAD="@LIBPOLYPDSP@" -else - LD_PRELOAD="$LD_PRELOAD @LIBPOLYPDSP@" -fi - -export LD_PRELOAD - -exec "$@" -- cgit From ea7995b764ed716bbe17576ebdba3a435de095d3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 15:44:24 +0000 Subject: Fix padsp script so that it accepts parameters, setting relevant environment variables as needed. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@970 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp b/src/utils/padsp index 9f38cf3d..dc89bfb7 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -19,6 +19,57 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. +while getopts 'hs:n:m:MSDd' param ; do + case $param in + s) + POLYP_SERVER="$OPTARG" + export POLYP_SERVER + ;; + n) + PA_CLIENT_NAME="$OPTARG" + export PA_CLIENT_NAME + ;; + m) + PA_STREAM_NAME="$OPTARG" + export PA_STREAM_NAME + ;; + M) + PA_NO_MIXER=1 + export PA_NO_MIXER + ;; + S) + PA_NO_SNDSTAT=1 + export PA_NO_SNDSTAT + ;; + D) + PA_NO_DSP=1 + export PA_NO_DSP + ;; + d) + PADSP_DEBUG=1 + export PADSP_DEBUG + ;; + *) + echo "$0 - redirect OSS audio devices to Polypaudio" + echo " " + echo "$0 [options] application [arguments]" + echo " " + echo "options:" + echo " -h show brief help" + echo " -s [:] contact a specific Polypaudio server" + echo " -n client name to report to the server" + echo " -m stream name to report to the server" + echo " -M disable /dev/mixer emulation" + echo " -S disable /dev/sndstat emulation" + echo " -D disable /dev/dsp emulation" + echo " -d enable debug output" + exit 0 + ;; + esac +done + +shift $(( $OPTIND - 1 )) + if [ x"$LD_PRELOAD" = x ] ; then LD_PRELOAD="libpolypdsp.so" else -- cgit From 4413b89d7a45587b545a31463ad2196767f45563 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 17:16:55 +0000 Subject: * split pa_cstrerror() into its own file polypcore/core-error.[ch] * fix building of padsp * remove a warning when compiling padsp.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@972 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 14 +++++++------- src/utils/padsp.c | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 351d79da..ad50c77c 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -54,7 +54,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", pa_cstrerror(errno)); + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -66,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": connect(): %s", strerror(errno)); goto fail; } @@ -97,7 +97,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": select(): %s", strerror(errno)); goto fail; } @@ -109,7 +109,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": read(): %s", strerror(errno)); goto fail; } @@ -125,7 +125,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": read(): %s", strerror(errno)); goto fail; } @@ -138,7 +138,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": write(): %s", strerror(errno)); goto fail; } @@ -152,7 +152,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": write(): %s", strerror(errno)); goto fail; } diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 5987ec5f..c1cc9c92 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -361,7 +361,7 @@ static void reset_params(fd_info *i) { i->n_fragments = 0; } -static char *client_name(char *buf, size_t n) { +static const char *client_name(char *buf, size_t n) { char p[PATH_MAX]; const char *e; @@ -376,7 +376,7 @@ static char *client_name(char *buf, size_t n) { return buf; } -static char *stream_name(void) { +static const char *stream_name(void) { const char *e; if ((e = getenv("PADSP_STREAM_NAME"))) -- cgit From f3b72593b545c66eeb5c7858958f0b2c44fd730e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 17:18:42 +0000 Subject: really fix a superfluous warning when building padsp.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@973 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c1cc9c92..5f3f9158 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -205,7 +205,7 @@ static int padsp_disabled(void) { pthread_mutex_lock(&func_mutex); if (!sym_resolved) { - sym = (int*) dlsym_fn(RTLD_DEFAULT, "__padsp_disabled__"); + sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__"); sym_resolved = 1; } -- cgit From b754d5095e8c1bbf41e7c0147dfb2328145a2c83 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 17:27:06 +0000 Subject: Wrong prefix used in the padsp script. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@975 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp b/src/utils/padsp index dc89bfb7..b43535b6 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -26,24 +26,24 @@ while getopts 'hs:n:m:MSDd' param ; do export POLYP_SERVER ;; n) - PA_CLIENT_NAME="$OPTARG" - export PA_CLIENT_NAME + PADSP_CLIENT_NAME="$OPTARG" + export PADSP_CLIENT_NAME ;; m) - PA_STREAM_NAME="$OPTARG" - export PA_STREAM_NAME + PADSP_STREAM_NAME="$OPTARG" + export PADSP_STREAM_NAME ;; M) - PA_NO_MIXER=1 - export PA_NO_MIXER + PADSP_NO_MIXER=1 + export PADSP_NO_MIXER ;; S) - PA_NO_SNDSTAT=1 - export PA_NO_SNDSTAT + PADSP_NO_SNDSTAT=1 + export PADSP_NO_SNDSTAT ;; D) - PA_NO_DSP=1 - export PA_NO_DSP + PADSP_NO_DSP=1 + export PADSP_NO_DSP ;; d) PADSP_DEBUG=1 -- cgit From 7d975345a555fc20e5019307c7dc01545552e42d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 23:20:28 +0000 Subject: * add new API function pa_stream_get_buffer_attr(). * modify pacat.c to make use of that new API * extend protocol to allow transfer of the necessary information * update protocol version accordingly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@976 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index b1f5bf59..83c3d3ca 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -154,8 +154,26 @@ static void stream_state_callback(pa_stream *s, void *userdata) { break; case PA_STREAM_READY: - if (verbose) + if (verbose) { + pa_buffer_attr *a; + fprintf(stderr, "Stream successfully created.\n"); + + if (!(a = pa_stream_get_buffer_attr(s))) + fprintf(stderr, "pa_stream_get_buffer_attr() failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + else { + + if (mode == PLAYBACK) + fprintf(stderr, "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n", a->maxlength, a->tlength, a->prebuf, a->minreq); + else { + assert(mode == RECORD); + fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); + } + + } + + } + break; case PA_STREAM_FAILED: -- cgit From 6aeaaf94a8af3c3b0607bc4a9f57923c569d71de Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 07:24:47 +0000 Subject: Returned buffer attr is const. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@979 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 83c3d3ca..99e54e64 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -155,7 +155,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) { - pa_buffer_attr *a; + const pa_buffer_attr *a; fprintf(stderr, "Stream successfully created.\n"); -- cgit From 7d90e3a32d52a5d94b536c0286d3e87f4df01fd0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 09:21:03 +0000 Subject: Fix typos. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@980 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 5f3f9158..b3e443d3 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1129,8 +1129,8 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno *(int*) argp = 0; break; - case SOUND_MIXER_CAPS: - debug(__FILE__": SOUND_MIXER_CAPS\n"); + case SOUND_MIXER_READ_CAPS: + debug(__FILE__": SOUND_MIXER_READ_CAPS\n"); *(int*) argp = 0; break; @@ -1204,7 +1204,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno } default: - debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + debug(__FILE__": unknown ioctl 0x%08lx\n", request); *_errno = EINVAL; goto fail; -- cgit From 12dc4c21ac4e31becf687513ac9852a3ae6893e5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 12:18:07 +0000 Subject: Fix the fix_metrics() function so that we don't get a tiny buffer by default. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@981 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b3e443d3..8bad126b 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -357,7 +357,7 @@ static void reset_params(fd_info *i) { i->sample_spec.format = PA_SAMPLE_ULAW; i->sample_spec.channels = 1; i->sample_spec.rate = 8000; - i->fragment_size = 1024; + i->fragment_size = 0; i->n_fragments = 0; } @@ -627,13 +627,23 @@ static void fix_metrics(fd_info *i) { fs = pa_frame_size(&i->sample_spec); i->fragment_size = (i->fragment_size/fs)*fs; - - if (i->n_fragments < 2) - i->n_fragments = 12; - if (i->fragment_size <= 0) - if ((i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments) <= 0) + /* Number of fragments set? */ + if (i->n_fragments < 2) { + if (i->fragment_size > 0) { + i->n_fragments = pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size; + if (i->n_fragments < 2) + i->n_fragments = 2; + } else + i->n_fragments = 12; + } + + /* Fragment size set? */ + if (i->fragment_size <= 0) { + i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments; + if (i->fragment_size < 1024) i->fragment_size = 1024; + } debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); debug(__FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); -- cgit From 0f13c43797dd291b02a6b0fa1c9933a35da95c01 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Jun 2006 13:21:14 +0000 Subject: Catch the access() system call as some applications do this to test if they can open /dev/dsp. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1016 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 8bad126b..da8f6786 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -101,6 +101,7 @@ static FILE* (*_fopen)(const char *path, const char *mode) = NULL; static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; static int (*_fclose)(FILE *f) = NULL; +static int (*_access)(const char *, int) = NULL; /* dlsym() violates ISO C, so confide the breakage into this function to * avoid warnings. */ @@ -141,6 +142,14 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define LOAD_ACCESS_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_access) \ + _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + #define LOAD_FOPEN_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ @@ -1725,6 +1734,25 @@ int close(int fd) { return 0; } +int access(const char *pathname, int mode) { + debug(__FILE__": access()\n"); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_ACCESS_FUNC(); + return _access(pathname, mode); + } + + if (mode & (W_OK | X_OK)) { + errno = EACCES; + return -1; + } + + return 0; +} + int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; -- cgit From 3fa491dc905edb8f54b10bff0b896e8ad7f733c6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 15 Jun 2006 14:47:14 +0000 Subject: Make debug output in padsp a bit less verbose. Specifying -d twice will give original output. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1018 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 6 +- src/utils/padsp.c | 258 +++++++++++++++++++++++++++++------------------------- 2 files changed, 146 insertions(+), 118 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp b/src/utils/padsp index b43535b6..27f99336 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -46,7 +46,11 @@ while getopts 'hs:n:m:MSDd' param ; do export PADSP_NO_DSP ;; d) - PADSP_DEBUG=1 + if [ x"$PADSP_DEBUG" = x ]; then + PADSP_DEBUG=1 + else + PADSP_DEBUG=$(( $PADSP_DEBUG + 1 )) + fi export PADSP_DEBUG ;; *) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index da8f6786..4fe8205e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -176,7 +176,7 @@ do { \ #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ - debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); @@ -184,20 +184,34 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ #define STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ !(i)->stream || pa_stream_get_state((i)->stream) != PA_STREAM_READY) { \ - debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); -static void debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -static void debug(const char *format, ...) { +#define DEBUG_LEVEL_ALWAYS 0 +#define DEBUG_LEVEL_NORMAL 1 +#define DEBUG_LEVEL_VERBOSE 2 + +static void debug(int level, const char *format, ...) { va_list ap; - if (getenv("PADSP_DEBUG")) { - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - } + const char *dlevel_s; + int dlevel; + + dlevel_s = getenv("PADSP_DEBUG"); + if (!dlevel_s) + return; + + dlevel = atoi(dlevel_s); + + if (dlevel < level) + return; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); } static int padsp_disabled(void) { @@ -280,7 +294,7 @@ static void function_exit(void) { static void fd_info_free(fd_info *i) { assert(i); - debug(__FILE__": freeing fd info (fd=%i)\n", i->app_fd); + debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd); dsp_drain(i); @@ -323,7 +337,7 @@ static fd_info *fd_info_ref(fd_info *i) { assert(i->ref >= 1); i->ref++; -/* debug(__FILE__": ref++, now %i\n", i->ref); */ + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref++, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); return i; @@ -334,7 +348,7 @@ static void fd_info_unref(fd_info *i) { pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); r = --i->ref; -/* debug(__FILE__": ref--, now %i\n", i->ref); */ + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); if (r <= 0) @@ -397,7 +411,7 @@ static const char *stream_name(void) { static void atfork_prepare(void) { fd_info *i; - debug(__FILE__": atfork_prepare() enter\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n"); function_enter(); @@ -411,13 +425,13 @@ static void atfork_prepare(void) { pthread_mutex_lock(&func_mutex); - debug(__FILE__": atfork_prepare() exit\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n"); } static void atfork_parent(void) { fd_info *i; - debug(__FILE__": atfork_parent() enter\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n"); pthread_mutex_unlock(&func_mutex); @@ -430,13 +444,13 @@ static void atfork_parent(void) { function_exit(); - debug(__FILE__": atfork_parent() exit\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n"); } static void atfork_child(void) { fd_info *i; - debug(__FILE__": atfork_child() enter\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n"); /* We do only the bare minimum to get all fds closed */ pthread_mutex_init(&func_mutex, NULL); @@ -471,7 +485,7 @@ static void atfork_child(void) { function_exit(); - debug(__FILE__": atfork_child() exit\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() exit\n"); } static void install_atfork(void) { @@ -504,7 +518,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { char name[64]; static pthread_once_t install_atfork_once = PTHREAD_ONCE_INIT; - debug(__FILE__": fd_info_new()\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": fd_info_new()\n"); signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ @@ -535,7 +549,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfds) < 0) { *_errno = errno; - debug(__FILE__": socket() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": socket() failed: %s\n", strerror(errno)); goto fail; } @@ -544,13 +558,13 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (!(i->mainloop = pa_threaded_mainloop_new())) { *_errno = EIO; - debug(__FILE__": pa_threaded_mainloop_new() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_new() failed\n"); goto fail; } if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), client_name(name, sizeof(name))))) { *_errno = EIO; - debug(__FILE__": pa_context_new() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_new() failed\n"); goto fail; } @@ -558,7 +572,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (pa_context_connect(i->context, NULL, 0, NULL) < 0) { *_errno = ECONNREFUSED; - debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -566,7 +580,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (pa_threaded_mainloop_start(i->mainloop) < 0) { *_errno = EIO; - debug(__FILE__": pa_threaded_mainloop_start() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_start() failed\n"); goto unlock_and_fail; } @@ -575,7 +589,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (pa_context_get_state(i->context) != PA_CONTEXT_READY) { *_errno = ECONNREFUSED; - debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto unlock_and_fail; } @@ -654,8 +668,8 @@ static void fix_metrics(fd_info *i) { i->fragment_size = 1024; } - debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); - debug(__FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); + debug(DEBUG_LEVEL_NORMAL, __FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); } static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { @@ -699,7 +713,7 @@ static int fd_info_copy_data(fd_info *i, int force) { return -1; if ((n = pa_stream_writable_size(i->stream)) == (size_t) -1) { - debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); return -1; } @@ -708,7 +722,7 @@ static int fd_info_copy_data(fd_info *i, int force) { if (!i->buf) { if (!(i->buf = malloc(i->fragment_size))) { - debug(__FILE__": malloc() failed.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n"); return -1; } } @@ -718,12 +732,12 @@ static int fd_info_copy_data(fd_info *i, int force) { if (errno == EAGAIN) break; - debug(__FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } if (pa_stream_write(i->stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { - debug(__FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); return -1; } @@ -749,11 +763,11 @@ static void stream_state_cb(pa_stream *s, void * userdata) { switch (pa_stream_get_state(s)) { case PA_STREAM_READY: - debug(__FILE__": stream established.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n"); break; case PA_STREAM_FAILED: - debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); fd_info_shutdown(i); break; @@ -773,7 +787,7 @@ static int create_stream(fd_info *i) { fix_metrics(i); if (!(i->stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { - debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -788,7 +802,7 @@ static int create_stream(fd_info *i) { attr.minreq = i->fragment_size; if (pa_stream_connect_playback(i->stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { - debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -847,7 +861,10 @@ static int dsp_open(int flags, int *_errno) { int ret; int f; + debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n"); + if ((flags != O_WRONLY) && (flags != (O_WRONLY|O_NONBLOCK))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access flags: %x\n", flags); *_errno = EACCES; return -1; } @@ -875,7 +892,7 @@ static int dsp_open(int flags, int *_errno) { pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); + debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); fd_info_add_to_list(i); ret = i->app_fd; @@ -891,7 +908,7 @@ fail: *_errno = EIO; - debug(__FILE__": dsp_open() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n"); return -1; } @@ -929,7 +946,7 @@ static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, ui return; if (!(o = pa_context_get_sink_info_by_index(i->context, i->sink_index, sink_info_cb, i))) { - debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); return; } @@ -941,6 +958,8 @@ static int mixer_open(int flags, int *_errno) { pa_operation *o; int ret; + debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n"); + if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) return -1; @@ -949,7 +968,7 @@ static int mixer_open(int flags, int *_errno) { pa_context_set_subscribe_callback(i->context, subscribe_cb, i); if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK, context_success_cb, i))) { - debug(__FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } @@ -961,7 +980,7 @@ static int mixer_open(int flags, int *_errno) { } if (!i->operation_success) { - debug(__FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } @@ -970,7 +989,7 @@ static int mixer_open(int flags, int *_errno) { pa_operation_unref(o); if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) { - debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } @@ -982,14 +1001,14 @@ static int mixer_open(int flags, int *_errno) { } if (!i->operation_success) { - debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); + debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); fd_info_add_to_list(i); ret = i->app_fd; @@ -1005,7 +1024,7 @@ fail: *_errno = EIO; - debug(__FILE__": mixer_open() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n"); return -1; } @@ -1039,11 +1058,11 @@ static int sndstat_open(int flags, int *_errno) { int fd = -1; int e; - debug(__FILE__": sndstat_open()\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n"); if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) { *_errno = EACCES; - debug(__FILE__": bad access!\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access!\n"); goto fail; } @@ -1054,7 +1073,7 @@ static int sndstat_open(int flags, int *_errno) { if (fd < 0) { *_errno = e; - debug(__FILE__": mkstemp() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": mkstemp() failed: %s\n", strerror(errno)); goto fail; } @@ -1062,13 +1081,13 @@ static int sndstat_open(int flags, int *_errno) { if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) { *_errno = errno; - debug(__FILE__": write() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": write() failed: %s\n", strerror(errno)); goto fail; } if (lseek(fd, SEEK_SET, 0) < 0) { *_errno = errno; - debug(__FILE__": lseek() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": lseek() failed: %s\n", strerror(errno)); goto fail; } @@ -1085,7 +1104,7 @@ int open(const char *filename, int flags, ...) { mode_t mode = 0; int r, _errno = 0; - debug(__FILE__": open(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); va_start(args, flags); if (flags & O_CREAT) @@ -1122,19 +1141,19 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno switch (request) { case SOUND_MIXER_READ_DEVMASK : - debug(__FILE__": SOUND_MIXER_READ_DEVMASK\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n"); *(int*) argp = SOUND_MASK_PCM; break; case SOUND_MIXER_READ_RECMASK : - debug(__FILE__": SOUND_MIXER_READ_RECMASK\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECMASK\n"); *(int*) argp = 0; break; case SOUND_MIXER_READ_STEREODEVS: - debug(__FILE__": SOUND_MIXER_READ_STEREODEVS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n"); pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = i->volume.channels > 1 ? SOUND_MASK_PCM : 0; @@ -1143,20 +1162,20 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno break; case SOUND_MIXER_READ_RECSRC: - debug(__FILE__": SOUND_MIXER_READ_RECSRC\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECSRC\n"); *(int*) argp = 0; break; case SOUND_MIXER_READ_CAPS: - debug(__FILE__": SOUND_MIXER_READ_CAPS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_CAPS\n"); *(int*) argp = 0; break; case SOUND_MIXER_READ_PCM: - debug(__FILE__": SOUND_MIXER_READ_PCM\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1171,7 +1190,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_WRITE_PCM: { pa_cvolume v; - debug(__FILE__": SOUND_MIXER_WRITE_PCM\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1184,7 +1203,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_operation *o; if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) - debug(__FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); else { i->operation_success = 0; @@ -1196,7 +1215,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno exit_loop: if (!i->operation_success) - debug(__FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); pa_operation_unref(o); } @@ -1213,6 +1232,8 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_INFO: { mixer_info *mi = argp; + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_INFO\n"); + memset(mi, 0, sizeof(mixer_info)); strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name)); @@ -1223,7 +1244,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno } default: - debug(__FILE__": unknown ioctl 0x%08lx\n", request); + debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); *_errno = EINVAL; goto fail; @@ -1296,7 +1317,7 @@ static int dsp_flush_socket(fd_info *i) { return -1; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); return -1; } @@ -1306,7 +1327,7 @@ static int dsp_flush_socket(fd_info *i) { k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l; if (read(i->thread_fd, buf, k) < 0) - debug(__FILE__": read(): %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", strerror(errno)); l -= k; } @@ -1324,7 +1345,7 @@ static int dsp_empty_socket(fd_info *i) { break; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); break; } @@ -1346,7 +1367,7 @@ static int dsp_drain(fd_info *i) { if (!i->mainloop) return 0; - debug(__FILE__": Draining.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1356,10 +1377,10 @@ static int dsp_drain(fd_info *i) { if (!i->stream) goto fail; - debug(__FILE__": Really draining.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n"); if (!(o = pa_stream_drain(i->stream, stream_success_cb, i))) { - debug(__FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1371,7 +1392,7 @@ static int dsp_drain(fd_info *i) { } if (!i->operation_success) { - debug(__FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1399,10 +1420,10 @@ static int dsp_trigger(fd_info *i) { if (dsp_empty_socket(i) < 0) goto fail; - debug(__FILE__": Triggering.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n"); if (!(o = pa_stream_trigger(i->stream, stream_success_cb, i))) { - debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1414,7 +1435,7 @@ static int dsp_trigger(fd_info *i) { } if (!i->operation_success) { - debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1435,7 +1456,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) switch (request) { case SNDCTL_DSP_SETFMT: { - debug(__FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1455,7 +1476,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) int valid; char t[256]; - debug(__FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1467,7 +1488,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_stream(i); } - debug(__FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); pa_threaded_mainloop_unlock(i->mainloop); @@ -1480,7 +1501,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } case SNDCTL_DSP_STEREO: - debug(__FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1494,7 +1515,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_sample_spec ss; int valid; - debug(__FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1517,7 +1538,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } case SNDCTL_DSP_GETBLKSIZE: - debug(__FILE__": SNDCTL_DSP_GETBLKSIZE\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETBLKSIZE\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1529,7 +1550,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; case SNDCTL_DSP_SETFRAGMENT: - debug(__FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1543,7 +1564,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; case SNDCTL_DSP_GETCAPS: - debug(__FILE__": SNDCTL_DSP_CAPS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); *(int*) argp = DSP_CAP_MULTI; break; @@ -1551,7 +1572,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETODELAY: { int l; - debug(__FILE__": SNDCTL_DSP_GETODELAY\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1568,7 +1589,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } if (pa_context_errno(i->context) != PA_ERR_NODATA) { - debug(__FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); break; } @@ -1578,19 +1599,19 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) exit_loop: if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) - debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); else *(int*) argp += l; pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": ODELAY: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": ODELAY: %i\n", *(int*) argp); break; } case SNDCTL_DSP_RESET: { - debug(__FILE__": SNDCTL_DSP_RESET\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1603,21 +1624,21 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } case SNDCTL_DSP_GETFMTS: { - debug(__FILE__": SNDCTL_DSP_GETFMTS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n"); *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE; break; } case SNDCTL_DSP_POST: - debug(__FILE__": SNDCTL_DSP_POST\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n"); if (dsp_trigger(i) < 0) *_errno = EIO; break; case SNDCTL_DSP_SYNC: - debug(__FILE__": SNDCTL_DSP_SYNC\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n"); if (dsp_drain(i) < 0) *_errno = EIO; @@ -1629,7 +1650,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) int l; size_t k = 0; - debug(__FILE__": SNDCTL_DSP_GETOSPACE\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1637,12 +1658,12 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if (i->stream) { if ((k = pa_stream_writable_size(i->stream)) == (size_t) -1) - debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); } else k = i->fragment_size * i->n_fragments; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); l = 0; } @@ -1653,13 +1674,13 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments); + debug(DEBUG_LEVEL_NORMAL, __FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments); break; } default: - debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); *_errno = EINVAL; goto fail; @@ -1678,7 +1699,7 @@ int ioctl(int fd, unsigned long request, ...) { void *argp; int r, _errno = 0; - debug(__FILE__": ioctl()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ioctl()\n"); va_start(args, request); argp = va_arg(args, void *); @@ -1713,7 +1734,7 @@ int ioctl(int fd, unsigned long request, ...) { int close(int fd) { fd_info *i; - debug(__FILE__": close()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": close()\n"); if (!function_enter()) { LOAD_CLOSE_FUNC(); @@ -1735,7 +1756,7 @@ int close(int fd) { } int access(const char *pathname, int mode) { - debug(__FILE__": access()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); if (strcmp(pathname, "/dev/dsp") != 0 && strcmp(pathname, "/dev/adsp") != 0 && @@ -1746,10 +1767,13 @@ int access(const char *pathname, int mode) { } if (mode & (W_OK | X_OK)) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = EACCESS\n", pathname, mode); errno = EACCES; return -1; } + debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = OK\n", pathname, mode); + return 0; } @@ -1757,7 +1781,7 @@ int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; - debug(__FILE__": open64(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); va_start(args, flags); if (flags & O_CREAT) @@ -1780,31 +1804,31 @@ FILE* fopen(const char *filename, const char *mode) { int fd; mode_t m; - debug(__FILE__": fopen(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename); - if (strcmp(filename, "/dev/dsp") == 0 || - strcmp(filename, "/dev/adsp") == 0) { - - if (strcmp(mode, "wb") != 0) { - errno = EACCES; - return NULL; - } + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_FOPEN_FUNC(); + return _fopen(filename, mode); + } + switch (mode[0]) { + case 'r': + m = O_RDONLY; + break; + case 'w': + case 'a': m = O_WRONLY; - } else if (strcmp(filename, "/dev/sndstat") == 0) { - - if (strcmp(mode, "r") != 0) { - errno = EACCES; - return NULL; - } + break; + default: + errno = EINVAL; + return NULL; + } - m = O_RDONLY; - } else if (strcmp(filename, "/dev/mixer") == 0) + if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+')) m = O_RDWR; - else { - LOAD_FOPEN_FUNC(); - return _fopen(filename, mode); - } if ((fd = open(filename, m)) < 0) return NULL; @@ -1819,7 +1843,7 @@ FILE* fopen(const char *filename, const char *mode) { FILE *fopen64(const char *filename, const char *mode) { - debug(__FILE__": fopen64(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename); if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && @@ -1835,7 +1859,7 @@ FILE *fopen64(const char *filename, const char *mode) { int fclose(FILE *f) { fd_info *i; - debug(__FILE__": fclose()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fclose()\n"); if (!function_enter()) { LOAD_FCLOSE_FUNC(); -- cgit From 6684264b69a17ec907c903c6f9ca9b99dbd29be2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 16 Jun 2006 21:07:32 +0000 Subject: Record support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1021 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 567 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 435 insertions(+), 132 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 4fe8205e..b0e76327 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -52,7 +52,7 @@ typedef enum { FD_INFO_MIXER, - FD_INFO_PLAYBACK + FD_INFO_STREAM, } fd_info_type_t; typedef struct fd_info fd_info; @@ -71,16 +71,18 @@ struct fd_info { pa_threaded_mainloop *mainloop; pa_context *context; - pa_stream *stream; + pa_stream *play_stream; + pa_stream *rec_stream; pa_io_event *io_event; void *buf; + size_t rec_offset; int operation_success; - pa_cvolume volume; - uint32_t sink_index; + pa_cvolume sink_volume, source_volume; + uint32_t sink_index, source_index; int volume_modify_count; PA_LLIST_FIELDS(fd_info); @@ -181,9 +183,17 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ } \ } while(0); -#define STREAM_CHECK_DEAD_GOTO(i, label) do { \ +#define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ - !(i)->stream || pa_stream_get_state((i)->stream) != PA_STREAM_READY) { \ + !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + goto label; \ +} \ +} while(0); + +#define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \ +if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ + !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ @@ -301,9 +311,14 @@ static void fd_info_free(fd_info *i) { if (i->mainloop) pa_threaded_mainloop_stop(i->mainloop); - if (i->stream) { - pa_stream_disconnect(i->stream); - pa_stream_unref(i->stream); + if (i->play_stream) { + pa_stream_disconnect(i->play_stream); + pa_stream_unref(i->play_stream); + } + + if (i->rec_stream) { + pa_stream_disconnect(i->rec_stream); + pa_stream_unref(i->rec_stream); } if (i->context) { @@ -465,9 +480,14 @@ static void atfork_child(void) { i->context = NULL; } - if (i->stream) { - pa_stream_unref(i->stream); - i->stream = NULL; + if (i->play_stream) { + pa_stream_unref(i->play_stream); + i->play_stream = NULL; + } + + if (i->rec_stream) { + pa_stream_unref(i->rec_stream); + i->rec_stream = NULL; } if (i->app_fd >= 0) { @@ -534,15 +554,19 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->mainloop = NULL; i->context = NULL; - i->stream = NULL; + i->play_stream = NULL; + i->rec_stream = NULL; i->io_event = NULL; pthread_mutex_init(&i->mutex, NULL); i->ref = 1; i->buf = NULL; + i->rec_offset = 0; i->unusable = 0; - pa_cvolume_reset(&i->volume, 2); + pa_cvolume_reset(&i->sink_volume, 2); + pa_cvolume_reset(&i->source_volume, 2); i->volume_modify_count = 0; i->sink_index = (uint32_t) -1; + i->source_index = (uint32_t) -1; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -678,8 +702,36 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { if (i->io_event) { pa_mainloop_api *api; + pa_io_event_flags_t flags; + size_t n; + api = pa_threaded_mainloop_get_api(i->mainloop); - api->io_enable(i->io_event, PA_IO_EVENT_INPUT); + + flags = 0; + + if (s == i->play_stream) { + n = pa_stream_writable_size(i->play_stream); + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + } + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_INPUT; + } + + if (s == i->rec_stream) { + n = pa_stream_readable_size(i->rec_stream); + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + } + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_OUTPUT; + } + + api->io_enable(i->io_event, flags); } } @@ -708,49 +760,114 @@ static void fd_info_shutdown(fd_info *i) { static int fd_info_copy_data(fd_info *i, int force) { size_t n; + pa_io_event_flags_t flags; - if (!i->stream) + if (!i->play_stream && !i->rec_stream) return -1; - if ((n = pa_stream_writable_size(i->stream)) == (size_t) -1) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); - return -1; - } - - while (n >= i->fragment_size || force) { - ssize_t r; - - if (!i->buf) { - if (!(i->buf = malloc(i->fragment_size))) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n"); + flags = 0; + + if (i->play_stream) { + n = pa_stream_writable_size(i->play_stream); + + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + return -1; + } + + while (n >= i->fragment_size || force) { + ssize_t r; + + if (!i->buf) { + if (!(i->buf = malloc(i->fragment_size))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n"); + return -1; + } + } + + if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) { + + if (errno == EAGAIN) + break; + + debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } - } - - if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) { - if (errno == EAGAIN) - break; - - debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); - return -1; + if (pa_stream_write(i->play_stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + i->buf = NULL; + + assert(n >= (size_t) r); + n -= r; } - - if (pa_stream_write(i->stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_INPUT; + } + + if (i->rec_stream) { + n = pa_stream_readable_size(i->rec_stream); + + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); return -1; } - i->buf = NULL; + while (n >= i->fragment_size || force) { + ssize_t r; + const void *data; + const char *buf; + size_t len; + + if (pa_stream_peek(i->rec_stream, &data, &len) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + if (!data) + break; - assert(n >= (size_t) r); - n -= r; + buf = (const char*)data + i->rec_offset; + + if ((r = write(i->thread_fd, buf, len - i->rec_offset)) <= 0) { + + if (errno == EAGAIN) + break; + + debug(DEBUG_LEVEL_NORMAL, __FILE__": write(): %s\n", strerror(errno)); + return -1; + } + + assert((size_t)r <= len - i->rec_offset); + i->rec_offset += r; + + if (i->rec_offset == len) { + if (pa_stream_drop(i->rec_stream) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + i->rec_offset = 0; + } + + assert(n >= (size_t) r); + n -= r; + } + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_OUTPUT; } if (i->io_event) { pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); - api->io_enable(i->io_event, n >= i->fragment_size ? PA_IO_EVENT_INPUT : 0); + api->io_enable(i->io_event, flags); } return 0; @@ -778,7 +895,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { } } -static int create_stream(fd_info *i) { +static int create_playback_stream(fd_info *i) { pa_buffer_attr attr; int n; @@ -786,14 +903,14 @@ static int create_stream(fd_info *i) { fix_metrics(i); - if (!(i->stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { + if (!(i->play_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } - pa_stream_set_state_callback(i->stream, stream_state_cb, i); - pa_stream_set_write_callback(i->stream, stream_request_cb, i); - pa_stream_set_latency_update_callback(i->stream, stream_latency_update_cb, i); + pa_stream_set_state_callback(i->play_stream, stream_state_cb, i); + pa_stream_set_write_callback(i->play_stream, stream_request_cb, i); + pa_stream_set_latency_update_callback(i->play_stream, stream_latency_update_cb, i); memset(&attr, 0, sizeof(attr)); attr.maxlength = i->fragment_size * (i->n_fragments+1); @@ -801,7 +918,7 @@ static int create_stream(fd_info *i) { attr.prebuf = i->fragment_size; attr.minreq = i->fragment_size; - if (pa_stream_connect_playback(i->stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { + if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -817,13 +934,56 @@ fail: return -1; } -static void free_stream(fd_info *i) { +static int create_record_stream(fd_info *i) { + pa_buffer_attr attr; + int n; + assert(i); - if (i->stream) { - pa_stream_disconnect(i->stream); - pa_stream_unref(i->stream); - i->stream = NULL; + fix_metrics(i); + + if (!(i->rec_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + pa_stream_set_state_callback(i->rec_stream, stream_state_cb, i); + pa_stream_set_read_callback(i->rec_stream, stream_request_cb, i); + pa_stream_set_latency_update_callback(i->rec_stream, stream_latency_update_cb, i); + + memset(&attr, 0, sizeof(attr)); + attr.maxlength = i->fragment_size * (i->n_fragments+1); + attr.fragsize = i->fragment_size; + + if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + n = i->fragment_size; + setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); + n = i->fragment_size; + setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); + + return 0; + +fail: + return -1; +} + +static void free_streams(fd_info *i) { + assert(i); + + if (i->play_stream) { + pa_stream_disconnect(i->play_stream); + pa_stream_unref(i->play_stream); + i->play_stream = NULL; + } + + if (i->rec_stream) { + pa_stream_disconnect(i->rec_stream); + pa_stream_unref(i->rec_stream); + i->rec_stream = NULL; } } @@ -834,17 +994,24 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even if (flags & PA_IO_EVENT_INPUT) { - if (!i->stream) { - api->io_enable(e, 0); - - if (create_stream(i) < 0) + if (!i->play_stream) { + if (create_playback_stream(i) < 0) goto fail; - } else { if (fd_info_copy_data(i, 0) < 0) goto fail; } + } else if (flags & PA_IO_EVENT_OUTPUT) { + + if (!i->rec_stream) { + if (create_record_stream(i) < 0) + goto fail; + } else { + if (fd_info_copy_data(i, 0) < 0) + goto fail; + } + } else if (flags & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) goto fail; @@ -860,21 +1027,13 @@ static int dsp_open(int flags, int *_errno) { pa_mainloop_api *api; int ret; int f; + pa_io_event_flags_t ioflags; debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n"); - if ((flags != O_WRONLY) && (flags != (O_WRONLY|O_NONBLOCK))) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access flags: %x\n", flags); - *_errno = EACCES; - return -1; - } - - if (!(i = fd_info_new(FD_INFO_PLAYBACK, _errno))) + if (!(i = fd_info_new(FD_INFO_STREAM, _errno))) return -1; - shutdown(i->thread_fd, SHUT_WR); - shutdown(i->app_fd, SHUT_RD); - if ((flags & O_NONBLOCK) == O_NONBLOCK) { if ((f = fcntl(i->app_fd, F_GETFL)) >= 0) fcntl(i->app_fd, F_SETFL, f|O_NONBLOCK); @@ -887,7 +1046,26 @@ static int dsp_open(int flags, int *_errno) { pa_threaded_mainloop_lock(i->mainloop); api = pa_threaded_mainloop_get_api(i->mainloop); - if (!(i->io_event = api->io_new(api, i->thread_fd, PA_IO_EVENT_INPUT, io_event_cb, i))) + + switch (flags & O_ACCMODE) { + case O_RDONLY: + ioflags = PA_IO_EVENT_OUTPUT; + shutdown(i->thread_fd, SHUT_RD); + shutdown(i->app_fd, SHUT_WR); + break; + case O_WRONLY: + ioflags = PA_IO_EVENT_INPUT; + shutdown(i->thread_fd, SHUT_WR); + shutdown(i->app_fd, SHUT_RD); + break; + case O_RDWR: + ioflags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT; + break; + default: + return -1; + } + + if (!(i->io_event = api->io_new(api, i->thread_fd, ioflags, io_event_cb, i))) goto fail; pa_threaded_mainloop_unlock(i->mainloop); @@ -925,16 +1103,38 @@ static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, v if (eol) return; - if (!pa_cvolume_equal(&i->volume, &si->volume)) + if (!pa_cvolume_equal(&i->sink_volume, &si->volume)) i->volume_modify_count++; - i->volume = si->volume; + i->sink_volume = si->volume; i->sink_index = si->index; i->operation_success = 1; pa_threaded_mainloop_signal(i->mainloop, 0); } +static void source_info_cb(pa_context *context, const pa_source_info *si, int eol, void *userdata) { + fd_info *i = userdata; + + if (!si && eol < 0) { + i->operation_success = 0; + pa_threaded_mainloop_signal(i->mainloop, 0); + return; + } + + if (eol) + return; + + if (!pa_cvolume_equal(&i->source_volume, &si->volume)) + i->volume_modify_count++; + + i->source_volume = si->volume; + i->source_index = si->index; + + i->operation_success = 1; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { fd_info *i = userdata; pa_operation *o = NULL; @@ -955,7 +1155,7 @@ static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, ui static int mixer_open(int flags, int *_errno) { fd_info *i; - pa_operation *o; + pa_operation *o = NULL; int ret; debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n"); @@ -967,7 +1167,7 @@ static int mixer_open(int flags, int *_errno) { pa_context_set_subscribe_callback(i->context, subscribe_cb, i); - if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK, context_success_cb, i))) { + if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; @@ -979,6 +1179,9 @@ static int mixer_open(int flags, int *_errno) { CONTEXT_CHECK_DEAD_GOTO(i, fail); } + pa_operation_unref(o); + o = NULL; + if (!i->operation_success) { debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; @@ -987,7 +1190,6 @@ static int mixer_open(int flags, int *_errno) { /* Get sink info */ - pa_operation_unref(o); if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; @@ -1000,12 +1202,38 @@ static int mixer_open(int flags, int *_errno) { CONTEXT_CHECK_DEAD_GOTO(i, fail); } + pa_operation_unref(o); + o = NULL; + if (!i->operation_success) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } + /* Get source info */ + + if (!(o = pa_context_get_source_info_by_name(i->context, NULL, source_info_cb, i))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(i->mainloop); + CONTEXT_CHECK_DEAD_GOTO(i, fail); + } + + pa_operation_unref(o); + o = NULL; + + if (!i->operation_success) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + pa_threaded_mainloop_unlock(i->mainloop); debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); @@ -1017,6 +1245,9 @@ static int mixer_open(int flags, int *_errno) { return ret; fail: + if (o) + pa_operation_unref(o); + pa_threaded_mainloop_unlock(i->mainloop); if (i) @@ -1143,20 +1374,24 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_READ_DEVMASK : debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n"); - *(int*) argp = SOUND_MASK_PCM; + *(int*) argp = SOUND_MASK_PCM | SOUND_MASK_IGAIN; break; case SOUND_MIXER_READ_RECMASK : debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECMASK\n"); - *(int*) argp = 0; + *(int*) argp = SOUND_MASK_IGAIN; break; case SOUND_MIXER_READ_STEREODEVS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n"); pa_threaded_mainloop_lock(i->mainloop); - *(int*) argp = i->volume.channels > 1 ? SOUND_MASK_PCM : 0; + *(int*) argp = 0; + if (i->sink_volume.channels > 1) + *(int*) argp |= SOUND_MASK_PCM; + if (i->source_volume.channels > 1) + *(int*) argp |= SOUND_MASK_IGAIN; pa_threaded_mainloop_unlock(i->mainloop); break; @@ -1164,9 +1399,13 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_READ_RECSRC: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECSRC\n"); - *(int*) argp = 0; + *(int*) argp = SOUND_MASK_IGAIN; break; - + + case SOUND_MIXER_WRITE_RECSRC: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_RECSRC\n"); + break; + case SOUND_MIXER_READ_CAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_CAPS\n"); @@ -1174,35 +1413,61 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno break; case SOUND_MIXER_READ_PCM: - - debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n"); - + case SOUND_MIXER_READ_IGAIN: { + pa_cvolume *v; + + if (request == SOUND_MIXER_READ_PCM) + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n"); + else + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_IGAIN\n"); + pa_threaded_mainloop_lock(i->mainloop); + if (request == SOUND_MIXER_READ_PCM) + v = &i->sink_volume; + else + v = &i->source_volume; + *(int*) argp = - ((i->volume.values[0]*100/PA_VOLUME_NORM)) | - ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8); - + ((v->values[0]*100/PA_VOLUME_NORM)) | + ((v->values[v->channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8); + pa_threaded_mainloop_unlock(i->mainloop); - + break; + } + + case SOUND_MIXER_WRITE_PCM: + case SOUND_MIXER_WRITE_IGAIN: { + pa_cvolume v, *pv; + + if (request == SOUND_MIXER_READ_PCM) + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); + else + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_IGAIN\n"); - case SOUND_MIXER_WRITE_PCM: { - pa_cvolume v; - - debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); - pa_threaded_mainloop_lock(i->mainloop); - v = i->volume; - - i->volume.values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; - i->volume.values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; + if (request == SOUND_MIXER_READ_PCM) { + v = i->sink_volume; + pv = &i->sink_volume; + } else { + v = i->source_volume; + pv = &i->source_volume; + } + + pv->values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + pv->values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; - if (!pa_cvolume_equal(&i->volume, &v)) { + if (!pa_cvolume_equal(pv, &v)) { pa_operation *o; - - if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) + + if (request == SOUND_MIXER_READ_PCM) + o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, NULL, NULL); + else + o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, NULL, NULL); + + if (!o) debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); else { @@ -1310,13 +1575,10 @@ static int map_format_back(pa_sample_format_t format) { } } -static int dsp_flush_socket(fd_info *i) { +static int dsp_flush_fd(int fd) { int l; - - if (i->thread_fd < 0) - return -1; - if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + if (ioctl(fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); return -1; } @@ -1326,7 +1588,7 @@ static int dsp_flush_socket(fd_info *i) { size_t k; k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l; - if (read(i->thread_fd, buf, k) < 0) + if (read(fd, buf, k) < 0) debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", strerror(errno)); l -= k; } @@ -1334,6 +1596,27 @@ static int dsp_flush_socket(fd_info *i) { return 0; } +static int dsp_flush_socket(fd_info *i) { + int res = 0; + + if ((i->thread_fd < 0) && (i->app_fd < 0)) + return -1; + + if (i->thread_fd >= 0) + res = dsp_flush_fd(i->thread_fd); + + if (res < 0) + return res; + + if (i->app_fd >= 0) + res = dsp_flush_fd(i->app_fd); + + if (res < 0) + return res; + + return 0; +} + static int dsp_empty_socket(fd_info *i) { int ret = -1; @@ -1374,19 +1657,19 @@ static int dsp_drain(fd_info *i) { if (dsp_empty_socket(i) < 0) goto fail; - if (!i->stream) + if (!i->play_stream) goto fail; debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n"); - if (!(o = pa_stream_drain(i->stream, stream_success_cb, i))) { + if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - STREAM_CHECK_DEAD_GOTO(i, fail); + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1412,7 +1695,7 @@ static int dsp_trigger(fd_info *i) { pa_operation *o = NULL; int r = -1; - if (!i->stream) + if (!i->play_stream) return 0; pa_threaded_mainloop_lock(i->mainloop); @@ -1422,14 +1705,14 @@ static int dsp_trigger(fd_info *i) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n"); - if (!(o = pa_stream_trigger(i->stream, stream_success_cb, i))) { + if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { - STREAM_CHECK_DEAD_GOTO(i, fail); + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1464,7 +1747,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *(int*) argp = map_format_back(i->sample_spec.format); else { map_format((int*) argp, &i->sample_spec); - free_stream(i); + free_streams(i); } pa_threaded_mainloop_unlock(i->mainloop); @@ -1485,7 +1768,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if ((valid = pa_sample_spec_valid(&ss))) { i->sample_spec = ss; - free_stream(i); + free_streams(i); } debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); @@ -1506,7 +1789,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); i->sample_spec.channels = *(int*) argp ? 2 : 1; - free_stream(i); + free_streams(i); pa_threaded_mainloop_unlock(i->mainloop); return 0; @@ -1524,7 +1807,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if ((valid = pa_sample_spec_valid(&ss))) { i->sample_spec = ss; - free_stream(i); + free_streams(i); } pa_threaded_mainloop_unlock(i->mainloop); @@ -1557,7 +1840,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->fragment_size = 1 << (*(int*) argp); i->n_fragments = (*(int*) argp) >> 16; - free_stream(i); + free_streams(i); pa_threaded_mainloop_unlock(i->mainloop); @@ -1566,7 +1849,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - *(int*) argp = DSP_CAP_MULTI; + *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_MULTI; break; case SNDCTL_DSP_GETODELAY: { @@ -1581,9 +1864,9 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) for (;;) { pa_usec_t usec; - STREAM_CHECK_DEAD_GOTO(i, exit_loop); + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop); - if (pa_stream_get_latency(i->stream, &usec, NULL) >= 0) { + if (pa_stream_get_latency(i->play_stream, &usec, NULL) >= 0) { *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec); break; } @@ -1615,7 +1898,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); - free_stream(i); + free_streams(i); dsp_flush_socket(i); reset_params(i); @@ -1645,31 +1928,51 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; - case SNDCTL_DSP_GETOSPACE: { + case SNDCTL_DSP_GETOSPACE: + case SNDCTL_DSP_GETISPACE: { audio_buf_info *bi = (audio_buf_info*) argp; int l; size_t k = 0; - debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n"); + if (request == SNDCTL_DSP_GETOSPACE) + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n"); + else + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETISPACE\n"); pa_threaded_mainloop_lock(i->mainloop); fix_metrics(i); - - if (i->stream) { - if ((k = pa_stream_writable_size(i->stream)) == (size_t) -1) - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); - } else - k = i->fragment_size * i->n_fragments; - - if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); - l = 0; + + if (request == SNDCTL_DSP_GETOSPACE) { + if (i->play_stream) { + if ((k = pa_stream_writable_size(i->play_stream)) == (size_t) -1) + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + } else + k = i->fragment_size * i->n_fragments; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); + l = 0; + } + + bi->bytes = k > (size_t) l ? k - l : 0; + } else { + if (i->rec_stream) { + if ((k = pa_stream_readable_size(i->rec_stream)) == (size_t) -1) + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + } else + k = 0; + + if (ioctl(i->app_fd, SIOCINQ, &l) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); + l = 0; + } + + bi->bytes = k + l; } bi->fragsize = i->fragment_size; bi->fragstotal = i->n_fragments; - bi->bytes = k > (size_t) l ? k - l : 0; bi->fragments = bi->bytes / bi->fragsize; pa_threaded_mainloop_unlock(i->mainloop); -- cgit From e66b0e6d3f235a65913c17a549bed74fd414445a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 16 Jun 2006 21:08:35 +0000 Subject: Creating a stream might take some time, so check that it's in the right state before transferring data. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1022 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b0e76327..be935060 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -767,7 +767,7 @@ static int fd_info_copy_data(fd_info *i, int force) { flags = 0; - if (i->play_stream) { + if ((i->play_stream) && (pa_stream_get_state(i->play_stream) == PA_STREAM_READY)) { n = pa_stream_writable_size(i->play_stream); if (n == (size_t)-1) { @@ -810,7 +810,7 @@ static int fd_info_copy_data(fd_info *i, int force) { flags |= PA_IO_EVENT_INPUT; } - if (i->rec_stream) { + if ((i->rec_stream) && (pa_stream_get_state(i->rec_stream) == PA_STREAM_READY)) { n = pa_stream_readable_size(i->rec_stream); if (n == (size_t)-1) { -- cgit From 8485a477053f7ea9549a1ca588c32b5379ba2d36 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 16 Jun 2006 21:11:45 +0000 Subject: /dev/dsp should default to U8, not mulaw. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1023 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index be935060..e25fdfd8 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -392,7 +392,7 @@ static void context_state_cb(pa_context *c, void *userdata) { static void reset_params(fd_info *i) { assert(i); - i->sample_spec.format = PA_SAMPLE_ULAW; + i->sample_spec.format = PA_SAMPLE_U8; i->sample_spec.channels = 1; i->sample_spec.rate = 8000; i->fragment_size = 0; -- cgit From c6d4cc0af9497a4376fa1dcb33a28c9a54264109 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 19 Jun 2006 16:39:28 +0000 Subject: Handle clients that just want to set fragment size (and not count). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1030 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index e25fdfd8..56acbb28 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1839,7 +1839,11 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->fragment_size = 1 << (*(int*) argp); i->n_fragments = (*(int*) argp) >> 16; - + + /* 0x7FFF means that we can set whatever we like */ + if (i->n_fragments == 0x7FFF) + i->n_fragments = 12; + free_streams(i); pa_threaded_mainloop_unlock(i->mainloop); -- cgit From f44ba092651aa75055e109e04b4164ea92ae7fdc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 21:53:48 +0000 Subject: big s/polyp/pulse/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1033 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/Makefile | 2 +- src/utils/pabrowse.c | 12 ++++++------ src/utils/pacat.c | 12 ++++++------ src/utils/pacmd.c | 18 +++++++++--------- src/utils/pactl.c | 12 ++++++------ src/utils/padsp | 12 ++++++------ src/utils/padsp.c | 14 +++++++------- src/utils/paplay.c | 12 ++++++------ src/utils/pax11publish.c | 22 +++++++++++----------- 9 files changed, 58 insertions(+), 58 deletions(-) (limited to 'src/utils') diff --git a/src/utils/Makefile b/src/utils/Makefile index cd2a5c9a..c110232d 120000 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1 +1 @@ -../polyp/Makefile \ No newline at end of file +../pulse/Makefile \ No newline at end of file diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 8063a28b..954e4e6c 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,8 +27,8 @@ #include #include -#include -#include +#include +#include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got signal, exiting\n"); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 99e54e64..5e4596d1 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,7 +33,7 @@ #include #include -#include +#include #define TIME_EVENT_USEC 50000 @@ -479,7 +479,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("pacat "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + printf("pacat "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index ad50c77c..e4a0970d 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,12 +32,12 @@ #include #include -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { pid_t pid ; diff --git a/src/utils/pactl.c b/src/utils/pactl.c index cc59e459..6e40f3fe 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,7 +35,7 @@ #include -#include +#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -644,7 +644,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("pactl "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + printf("pactl "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/src/utils/padsp b/src/utils/padsp index 27f99336..6e7e9f06 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -2,20 +2,20 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser 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 +# PulseAudio 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 Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. @@ -75,9 +75,9 @@ done shift $(( $OPTIND - 1 )) if [ x"$LD_PRELOAD" = x ] ; then - LD_PRELOAD="libpolypdsp.so" + LD_PRELOAD="libpulsedsp.so" else - LD_PRELOAD="$LD_PRELOAD libpolypdsp.so" + LD_PRELOAD="$LD_PRELOAD libpulsedsp.so" fi export LD_PRELOAD diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 56acbb28..13f571e1 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -46,9 +46,9 @@ #include -#include -#include -#include +#include +#include +#include typedef enum { FD_INFO_MIXER, diff --git a/src/utils/paplay.c b/src/utils/paplay.c index effc2a11..4b4a1ea6 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,7 +35,7 @@ #include -#include +#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -253,7 +253,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("paplay "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + printf("paplay "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 668361c6..770455b9 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 + PulseAudio 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 Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,15 +31,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "../polyp/client-conf.h" +#include "../pulse/client-conf.h" int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; -- cgit From 10b5e997d7a8a4e955ce49cc816fdcd36225ff6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 22:11:49 +0000 Subject: replace a few remaining uppercase "Polypaudio" occurences with "PulseAudio" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1036 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- src/utils/pacmd.c | 4 ++-- src/utils/pactl.c | 2 +- src/utils/padsp | 4 ++-- src/utils/padsp.c | 12 ++++++------ src/utils/paplay.c | 2 +- src/utils/pax11publish.c | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 5e4596d1..10edd71d 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -38,7 +38,7 @@ #define TIME_EVENT_USEC 50000 #if PA_API_VERSION != 9 -#error Invalid Polypaudio API version +#error Invalid PulseAudio API version #endif static enum { RECORD, PLAYBACK } mode = PLAYBACK; diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index e4a0970d..fe8038e0 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -49,7 +49,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { fd_set ifds, ofds; if (pa_pid_file_check_running(&pid) < 0) { - pa_log(__FILE__": no Polypaudio daemon running"); + pa_log(__FILE__": no PulseAudio daemon running"); goto fail; } @@ -74,7 +74,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { break; if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { - pa_log(__FILE__": failed to kill Polypaudio daemon."); + pa_log(__FILE__": failed to kill PulseAudio daemon."); goto fail; } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 6e40f3fe..94d22f98 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -38,7 +38,7 @@ #include #if PA_API_VERSION != 9 -#error Invalid Polypaudio API version +#error Invalid PulseAudio API version #endif #define BUFSIZE 1024 diff --git a/src/utils/padsp b/src/utils/padsp index 6e7e9f06..d9ebcbc5 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -54,13 +54,13 @@ while getopts 'hs:n:m:MSDd' param ; do export PADSP_DEBUG ;; *) - echo "$0 - redirect OSS audio devices to Polypaudio" + echo "$0 - redirect OSS audio devices to PulseAudio" echo " " echo "$0 [options] application [arguments]" echo " " echo "options:" echo " -h show brief help" - echo " -s [:] contact a specific Polypaudio server" + echo " -s [:] contact a specific PulseAudio server" echo " -n client name to report to the server" echo " -m stream name to report to the server" echo " -M disable /dev/mixer emulation" diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 13f571e1..d9dcc764 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1262,18 +1262,18 @@ fail: static int sndstat_open(int flags, int *_errno) { static const char sndstat[] = - "Sound Driver:3.8.1a-980706 (Polypaudio Virtual OSS)\n" + "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n" "Kernel: POSIX\n" "Config options: 0\n" "\n" "Installed drivers:\n" - "Type 255: Polypaudio Virtual OSS\n" + "Type 255: PulseAudio Virtual OSS\n" "\n" "Card config:\n" - "Polypaudio Virtual OSS\n" + "PulseAudio Virtual OSS\n" "\n" "Audio devices:\n" - "0: Polypaudio Virtual OSS\n" + "0: PulseAudio Virtual OSS\n" "\n" "Synth devices: NOT ENABLED IN CONFIG\n" "\n" @@ -1282,7 +1282,7 @@ static int sndstat_open(int flags, int *_errno) { "Timers:\n" "\n" "Mixers:\n" - "0: Polypaudio Virtual OSS\n"; + "0: PulseAudio Virtual OSS\n"; char fn[] = "/tmp/padsp-sndstat-XXXXXX"; mode_t u; @@ -1501,7 +1501,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno memset(mi, 0, sizeof(mixer_info)); strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); - strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name)); + strncpy(mi->name, "PulseAudio Virtual OSS", sizeof(mi->name)); pa_threaded_mainloop_lock(i->mainloop); mi->modify_counter = i->volume_modify_count; pa_threaded_mainloop_unlock(i->mainloop); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 4b4a1ea6..7b34016c 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -38,7 +38,7 @@ #include #if PA_API_VERSION != 9 -#error Invalid Polypaudio API version +#error Invalid PulseAudio API version #endif static pa_context *context = NULL; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 770455b9..d2ed6c93 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -54,10 +54,10 @@ int main(int argc, char *argv[]) { break; case 'h': printf("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n\n" - " -d Show current Polypaudio data attached to X11 display (default)\n" - " -e Export local Polypaudio data to X11 display\n" - " -i Import Polypaudio data from X11 display to local environment variables and cookie file.\n" - " -r Remove Polypaudio data from X11 display\n", + " -d Show current PulseAudio data attached to X11 display (default)\n" + " -e Export local PulseAudio data to X11 display\n" + " -i Import PulseAudio data from X11 display to local environment variables and cookie file.\n" + " -r Remove PulseAudio data from X11 display\n", pa_path_get_filename(argv[0])); ret = 0; goto finish; -- cgit From 230f97a4a4dc22510a19add8b2df0533a359846c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:56:54 +0000 Subject: s/POLYP/PULSE/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1041 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- src/utils/pax11publish.c | 60 ++++++++++++++++++++++++------------------------ 2 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d9dcc764..af89f8fb 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1500,7 +1500,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_INFO\n"); memset(mi, 0, sizeof(mixer_info)); - strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); + strncpy(mi->id, "PULSEAUDIO", sizeof(mi->id)); strncpy(mi->name, "PulseAudio Virtual OSS", sizeof(mi->name)); pa_threaded_mainloop_lock(i->mainloop); mi->modify_counter = i->volume_modify_count; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index d2ed6c93..2a0d21d6 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -99,13 +99,13 @@ int main(int argc, char *argv[]) { switch (mode) { case DUMP: { char t[1024]; - if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) printf("Server: %s\n", t); - if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) printf("Source: %s\n", t); - if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SINK", t, sizeof(t))) printf("Sink: %s\n", t); - if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_COOKIE", t, sizeof(t))) printf("Cookie: %s\n", t); break; @@ -113,14 +113,14 @@ int main(int argc, char *argv[]) { case IMPORT: { char t[1024]; - if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) - printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); - if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) - printf("POLYP_SOURCE='%s'\nexport POLYP_SOURCE\n", t); - if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) - printf("POLYP_SINK='%s'\nexport POLYP_SINK\n", t); - - if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) + printf("PULSE_SERVER='%s'\nexport PULSE_SERVER\n", t); + if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) + printf("PULSE_SOURCE='%s'\nexport PULSE_SOURCE\n", t); + if (pa_x11_get_prop(d, "PULSE_SINK", t, sizeof(t))) + printf("PULSE_SINK='%s'\nexport PULSE_SINK\n", t); + + if (pa_x11_get_prop(d, "PULSE_COOKIE", t, sizeof(t))) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; size_t l; if ((l = pa_parsehex(t, cookie, sizeof(cookie))) != sizeof(cookie)) { @@ -153,16 +153,16 @@ int main(int argc, char *argv[]) { goto finish; } - pa_x11_del_prop(d, "POLYP_SERVER"); - pa_x11_del_prop(d, "POLYP_SINK"); - pa_x11_del_prop(d, "POLYP_SOURCE"); - pa_x11_del_prop(d, "POLYP_ID"); - pa_x11_del_prop(d, "POLYP_COOKIE"); + pa_x11_del_prop(d, "PULSE_SERVER"); + pa_x11_del_prop(d, "PULSE_SINK"); + pa_x11_del_prop(d, "PULSE_SOURCE"); + pa_x11_del_prop(d, "PULSE_ID"); + pa_x11_del_prop(d, "PULSE_COOKIE"); if (server) - pa_x11_set_prop(d, "POLYP_SERVER", server); + pa_x11_set_prop(d, "PULSE_SERVER", server); else if (conf->default_server) - pa_x11_set_prop(d, "POLYP_SERVER", conf->default_server); + pa_x11_set_prop(d, "PULSE_SERVER", conf->default_server); else { char hn[256]; if (!pa_get_fqdn(hn, sizeof(hn))) { @@ -170,18 +170,18 @@ int main(int argc, char *argv[]) { goto finish; } - pa_x11_set_prop(d, "POLYP_SERVER", hn); + pa_x11_set_prop(d, "PULSE_SERVER", hn); } if (sink) - pa_x11_set_prop(d, "POLYP_SINK", sink); + pa_x11_set_prop(d, "PULSE_SINK", sink); else if (conf->default_sink) - pa_x11_set_prop(d, "POLYP_SINK", conf->default_sink); + pa_x11_set_prop(d, "PULSE_SINK", conf->default_sink); if (source) - pa_x11_set_prop(d, "POLYP_SOURCE", source); + pa_x11_set_prop(d, "PULSE_SOURCE", source); if (conf->default_source) - pa_x11_set_prop(d, "POLYP_SOURCE", conf->default_source); + pa_x11_set_prop(d, "PULSE_SOURCE", conf->default_source); pa_client_conf_free(conf); @@ -190,16 +190,16 @@ int main(int argc, char *argv[]) { goto finish; } - pa_x11_set_prop(d, "POLYP_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); + pa_x11_set_prop(d, "PULSE_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); break; } case REMOVE: - pa_x11_del_prop(d, "POLYP_SERVER"); - pa_x11_del_prop(d, "POLYP_SINK"); - pa_x11_del_prop(d, "POLYP_SOURCE"); - pa_x11_del_prop(d, "POLYP_ID"); - pa_x11_del_prop(d, "POLYP_COOKIE"); + pa_x11_del_prop(d, "PULSE_SERVER"); + pa_x11_del_prop(d, "PULSE_SINK"); + pa_x11_del_prop(d, "PULSE_SOURCE"); + pa_x11_del_prop(d, "PULSE_ID"); + pa_x11_del_prop(d, "PULSE_COOKIE"); break; default: -- cgit From 3ff68bd7a57186c6c6def975be3fc7e826c8bbcd Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 13:02:34 +0000 Subject: Fix the final few occurences of polyp. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1042 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp b/src/utils/padsp index d9ebcbc5..bae5a728 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -22,8 +22,8 @@ while getopts 'hs:n:m:MSDd' param ; do case $param in s) - POLYP_SERVER="$OPTARG" - export POLYP_SERVER + PULSE_SERVER="$OPTARG" + export PULSE_SERVER ;; n) PADSP_CLIENT_NAME="$OPTARG" -- cgit From 07edf591771e719a5616ca11319f644fbf66f576 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 15:36:28 +0000 Subject: Make fix_metrics() exit early so that it doesn't spam the output needlessly. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1046 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index af89f8fb..3b8ecbf1 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -673,6 +673,13 @@ static void fix_metrics(fd_info *i) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; fs = pa_frame_size(&i->sample_spec); + + /* Don't fix things more than necessary */ + if ((i->fragment_size % fs) == 0 && + i->n_fragments >= 2 && + i->fragment_size > 0) + return; + i->fragment_size = (i->fragment_size/fs)*fs; /* Number of fragments set? */ -- cgit From 1040b69cf2fc6175a1069226a93ec66f1a092ad0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 15:45:10 +0000 Subject: Warn when applications use SNDCTL_DSP_GET[IO]PTR even when they shouldn't. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1047 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 3b8ecbf1..3b2294f7 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1992,10 +1992,19 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } - + + case SNDCTL_DSP_GETIPTR: + debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); + goto inval; + + case SNDCTL_DSP_GETOPTR: + debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETOPTR\n"); + goto inval; + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); +inval: *_errno = EINVAL; goto fail; } -- cgit From 320bedb58032d33a2bd31978c95b8f17d07c9872 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 16:43:46 +0000 Subject: Fix handling of the io flags in duplex mode. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1048 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 3b2294f7..f493f7e5 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -75,6 +75,7 @@ struct fd_info { pa_stream *rec_stream; pa_io_event *io_event; + pa_io_event_flags_t io_flags; void *buf; size_t rec_offset; @@ -557,6 +558,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->play_stream = NULL; i->rec_stream = NULL; i->io_event = NULL; + i->io_flags = 0; pthread_mutex_init(&i->mutex, NULL); i->ref = 1; i->buf = NULL; @@ -709,13 +711,10 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { if (i->io_event) { pa_mainloop_api *api; - pa_io_event_flags_t flags; size_t n; api = pa_threaded_mainloop_get_api(i->mainloop); - flags = 0; - if (s == i->play_stream) { n = pa_stream_writable_size(i->play_stream); if (n == (size_t)-1) { @@ -724,7 +723,9 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_INPUT; + i->io_flags |= PA_IO_EVENT_INPUT; + else + i->io_flags &= ~PA_IO_EVENT_INPUT; } if (s == i->rec_stream) { @@ -735,10 +736,12 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_OUTPUT; + i->io_flags |= PA_IO_EVENT_OUTPUT; + else + i->io_flags &= ~PA_IO_EVENT_OUTPUT; } - api->io_enable(i->io_event, flags); + api->io_enable(i->io_event, i->io_flags); } } @@ -757,6 +760,7 @@ static void fd_info_shutdown(fd_info *i) { api = pa_threaded_mainloop_get_api(i->mainloop); api->io_free(i->io_event); i->io_event = NULL; + i->io_flags = 0; } if (i->thread_fd >= 0) { @@ -767,13 +771,10 @@ static void fd_info_shutdown(fd_info *i) { static int fd_info_copy_data(fd_info *i, int force) { size_t n; - pa_io_event_flags_t flags; if (!i->play_stream && !i->rec_stream) return -1; - flags = 0; - if ((i->play_stream) && (pa_stream_get_state(i->play_stream) == PA_STREAM_READY)) { n = pa_stream_writable_size(i->play_stream); @@ -814,7 +815,9 @@ static int fd_info_copy_data(fd_info *i, int force) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_INPUT; + i->io_flags |= PA_IO_EVENT_INPUT; + else + i->io_flags &= ~PA_IO_EVENT_INPUT; } if ((i->rec_stream) && (pa_stream_get_state(i->rec_stream) == PA_STREAM_READY)) { @@ -867,14 +870,16 @@ static int fd_info_copy_data(fd_info *i, int force) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_OUTPUT; + i->io_flags |= PA_IO_EVENT_OUTPUT; + else + i->io_flags &= ~PA_IO_EVENT_OUTPUT; } if (i->io_event) { pa_mainloop_api *api; api = pa_threaded_mainloop_get_api(i->mainloop); - api->io_enable(i->io_event, flags); + api->io_enable(i->io_event, i->io_flags); } return 0; @@ -1034,7 +1039,6 @@ static int dsp_open(int flags, int *_errno) { pa_mainloop_api *api; int ret; int f; - pa_io_event_flags_t ioflags; debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n"); @@ -1056,23 +1060,23 @@ static int dsp_open(int flags, int *_errno) { switch (flags & O_ACCMODE) { case O_RDONLY: - ioflags = PA_IO_EVENT_OUTPUT; + i->io_flags = PA_IO_EVENT_OUTPUT; shutdown(i->thread_fd, SHUT_RD); shutdown(i->app_fd, SHUT_WR); break; case O_WRONLY: - ioflags = PA_IO_EVENT_INPUT; + i->io_flags = PA_IO_EVENT_INPUT; shutdown(i->thread_fd, SHUT_WR); shutdown(i->app_fd, SHUT_RD); break; case O_RDWR: - ioflags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT; + i->io_flags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT; break; default: return -1; } - if (!(i->io_event = api->io_new(api, i->thread_fd, ioflags, io_event_cb, i))) + if (!(i->io_event = api->io_new(api, i->thread_fd, i->io_flags, io_event_cb, i))) goto fail; pa_threaded_mainloop_unlock(i->mainloop); -- cgit From 1fd18d6b5fce487faea673d093019395ec783fbc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 17:35:10 +0000 Subject: * add proper error handling to pabrowse.c * properly destroy pa_browser object on exit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1071 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 954e4e6c..450182f5 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -107,10 +107,18 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows } } +static void error_callback(pa_browser *b, const char *s, void *userdata) { + pa_mainloop_api*m = userdata; + + fprintf(stderr, "Failure: %s\n", s); + m->quit(m, 1); +} + int main(int argc, char *argv[]) { pa_mainloop *mainloop = NULL; pa_browser *browser = NULL; int ret = 1, r; + const char *s; if (!(mainloop = pa_mainloop_new())) goto finish; @@ -121,15 +129,22 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGTERM, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - if (!(browser = pa_browser_new(pa_mainloop_get_api(mainloop)))) + if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) { + fprintf(stderr, "pa_browse_new_full(): %s\n", s); goto finish; + } pa_browser_set_callback(browser, browser_callback, NULL); + pa_browser_set_error_callback(browser, error_callback, pa_mainloop_get_api(mainloop)); ret = 0; pa_mainloop_run(mainloop, &ret); finish: + + if (browser) + pa_browser_unref(browser); + if (mainloop) { pa_signal_done(); pa_mainloop_free(mainloop); -- cgit From a87c43d61e950b60b44e7e786116dd1e2fad4dc6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 00:18:21 +0000 Subject: Don't call pa_path_get_filename() anymore since it is implicitly called by pa_get_binary_name() anyway git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1078 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index f493f7e5..b1636754 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -408,7 +408,7 @@ static const char *client_name(char *buf, size_t n) { return e; if (pa_get_binary_name(p, sizeof(p))) - snprintf(buf, n, "OSS Emulation[%s]", pa_path_get_filename(p)); + snprintf(buf, n, "OSS Emulation[%s]", p); else snprintf(buf, n, "OSS"); -- cgit From 3b2843d5a8d50d6f9c3f5bedd63e3cc429c7ea13 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:29:09 +0000 Subject: show value of PA_SINK_HARDWARE/PA_SOURCE_HARDWARE in pactl git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1093 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 94d22f98..25ef324d 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -174,7 +174,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ "Volume: %s\n" "Monitor Source: %u\n" "Latency: %0.0f usec\n" - "Flags: %s%s\n", + "Flags: %s%s%s\n", i->index, i->name, i->driver, @@ -186,7 +186,8 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ i->monitor_source, (double) i->latency, i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", - i->flags & PA_SINK_LATENCY ? "LATENCY" : ""); + i->flags & PA_SINK_LATENCY ? "LATENCY " : "", + i->flags & PA_SINK_HARDWARE ? "HARDWARE" : ""); } @@ -222,7 +223,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int "Volume: %s\n" "Monitor of Sink: %s\n" "Latency: %0.0f usec\n" - "Flags: %s%s\n", + "Flags: %s%s%s\n", i->index, i->driver, i->name, @@ -234,7 +235,8 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", (double) i->latency, i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", - i->flags & PA_SOURCE_LATENCY ? "LATENCY" : ""); + i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", + i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : ""); } -- cgit From ba31adcf3ebb542931fb6d66f2e1fc7689dfc712 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 23:20:27 +0000 Subject: make pulseaudio compile again on FreeBSD (patch from Diego "Flameeyes" Petteno) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1096 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b1636754..32cb5f9a 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,9 @@ #include #include +#ifdef __linux__ #include +#endif #include #include @@ -101,8 +104,10 @@ static int (*_ioctl)(int, int, void*) = NULL; static int (*_close)(int) = NULL; static int (*_open)(const char *, int, mode_t) = NULL; static FILE* (*_fopen)(const char *path, const char *mode) = NULL; +#ifdef HAVE_OPEN64 static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; +#endif static int (*_fclose)(FILE *f) = NULL; static int (*_access)(const char *, int) = NULL; @@ -1302,7 +1307,11 @@ static int sndstat_open(int flags, int *_errno) { debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n"); - if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) { + if (flags != O_RDONLY +#ifdef O_LARGEFILE + && flags != (O_RDONLY|O_LARGEFILE) +#endif + ) { *_errno = EACCES; debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access!\n"); goto fail; @@ -1349,8 +1358,12 @@ int open(const char *filename, int flags, ...) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); va_start(args, flags); - if (flags & O_CREAT) + if (flags & O_CREAT) { + if (sizeof(mode_t) < sizeof(int)) + mode = va_arg(args, int); + else mode = va_arg(args, mode_t); + } va_end(args); if (!function_enter()) { @@ -1587,6 +1600,7 @@ static int map_format_back(pa_sample_format_t format) { } static int dsp_flush_fd(int fd) { +#ifdef SIOCINQ int l; if (ioctl(fd, SIOCINQ, &l) < 0) { @@ -1605,6 +1619,10 @@ static int dsp_flush_fd(int fd) { } return 0; +#else +# warning "Your platform does not support SIOCINQ, something might not work as intended." + return 0; +#endif } static int dsp_flush_socket(fd_info *i) { @@ -1629,6 +1647,7 @@ static int dsp_flush_socket(fd_info *i) { } static int dsp_empty_socket(fd_info *i) { +#ifdef SIOCINQ int ret = -1; /* Empty the socket */ @@ -1652,6 +1671,10 @@ static int dsp_empty_socket(fd_info *i) { } return ret; +#else +# warning "Your platform does not support SIOCINQ, something might not work as intended." + return 0; +#endif } static int dsp_drain(fd_info *i) { @@ -1864,7 +1887,11 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_MULTI; + *(int*) argp = DSP_CAP_DUPLEX +#ifdef DSP_CAP_MULTI + | DSP_CAP_MULTI +#endif + ; break; case SNDCTL_DSP_GETODELAY: { @@ -1895,11 +1922,15 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } exit_loop: - + +#ifdef SIOCINQ if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); else *(int*) argp += l; +#else +# warning "Your platform does not support SIOCINQ, something might not work as intended." +#endif pa_threaded_mainloop_unlock(i->mainloop); @@ -1946,7 +1977,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETOSPACE: case SNDCTL_DSP_GETISPACE: { audio_buf_info *bi = (audio_buf_info*) argp; - int l; + int l = 0; size_t k = 0; if (request == SNDCTL_DSP_GETOSPACE) @@ -1965,10 +1996,14 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } else k = i->fragment_size * i->n_fragments; +#ifdef SIOCINQ if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); l = 0; } +#else +# warning "Your platform does not dsp_flush_fd, something might not work as intended." +#endif bi->bytes = k > (size_t) l ? k - l : 0; } else { @@ -1978,11 +2013,14 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } else k = 0; +#ifdef SIOCINQ if (ioctl(i->app_fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); l = 0; } - +#else +# warning "Your platform does not dsp_flush_fd, something might not work as intended." +#endif bi->bytes = k + l; } @@ -2104,6 +2142,8 @@ int access(const char *pathname, int mode) { return 0; } +#ifdef HAVE_OPEN64 + int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; @@ -2126,6 +2166,8 @@ int open64(const char *filename, int flags, ...) { return open(filename, flags, mode); } +#endif + FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; @@ -2168,6 +2210,8 @@ FILE* fopen(const char *filename, const char *mode) { return f; } +#ifdef HAVE_OPEN64 + FILE *fopen64(const char *filename, const char *mode) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename); @@ -2183,6 +2227,8 @@ FILE *fopen64(const char *filename, const char *mode) { return fopen(filename, mode); } +#endif + int fclose(FILE *f) { fd_info *i; -- cgit From b325e07c7337a533792aac2d19ac6ff364c92fb6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:02:24 +0000 Subject: handle EOF correctly if it is read before the stream was created git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1164 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 10edd71d..dda5c192 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -291,18 +291,22 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { - pa_operation *o; - if (verbose) fprintf(stderr, "Got EOF.\n"); - - if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { - fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); - quit(1); - return; - } - pa_operation_unref(o); + if (stream) { + pa_operation *o; + + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { + fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + + pa_operation_unref(o); + } else + quit(0); + } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); -- cgit From bc30e2d9346edad2c8a755656e9aec803227bde1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:55:42 +0000 Subject: add new "move-sink-input" command to pactl git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1178 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 25ef324d..3674f950 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -46,7 +46,8 @@ static pa_context *context = NULL; static pa_mainloop_api *mainloop_api = NULL; -static char *device = NULL, *sample_name = NULL; +static char *device = NULL, *sample_name = NULL, *sink_name = NULL; +static uint32_t sink_input_idx = PA_INVALID_INDEX; static SNDFILE *sndfile = NULL; static pa_stream *sample_stream = NULL; @@ -64,7 +65,8 @@ static enum { UPLOAD_SAMPLE, PLAY_SAMPLE, REMOVE_SAMPLE, - LIST + LIST, + MOVE_SINK_INPUT } action = NONE; static void quit(int ret) { @@ -581,6 +583,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL)); break; + case MOVE_SINK_INPUT: + pa_operation_unref(pa_context_move_sink_input_by_name(c, sink_input_idx, sink_name, simple_callback, NULL)); + break; + default: assert(0); } @@ -609,12 +615,13 @@ static void help(const char *argv0) { "%s [options] exit\n" "%s [options] upload-sample FILENAME [NAME]\n" "%s [options] play-sample NAME [SINK]\n" + "%s [options] move-sink-input NAME [SINK]\n" "%s [options] remove-sample NAME\n\n" " -h, --help Show this help\n" " --version Show version\n\n" " -s, --server=SERVER The name of the server to connect to\n" " -n, --client-name=NAME How to call this client on the server\n", - argv0, argv0, argv0, argv0, argv0, argv0); + argv0, argv0, argv0, argv0, argv0, argv0, argv0); } enum { ARG_VERSION = 256 }; @@ -731,6 +738,15 @@ int main(int argc, char *argv[]) { } sample_name = pa_xstrdup(argv[optind+1]); + } else if (!strcmp(argv[optind], "move-sink-input")) { + action = MOVE_SINK_INPUT; + if (optind+2 >= argc) { + fprintf(stderr, "You have to specify a sink input index and a sink\n"); + goto quit; + } + + sink_input_idx = atoi(argv[optind+1]); + sink_name = pa_xstrdup(argv[optind+2]); } } @@ -784,6 +800,7 @@ quit: pa_xfree(server); pa_xfree(device); pa_xfree(sample_name); + pa_xfree(sink_name); return ret; } -- cgit From 7f93d08d4014cc68965611068c47834c1e5547ef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Aug 2006 21:04:43 +0000 Subject: bump API and protocol version. Return PA_ERR_NOTSUPPORTED if pa_context_move_sink_input_by_*()is called for servers that don't support it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1179 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index dda5c192..1c581f4d 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -37,7 +37,7 @@ #define TIME_EVENT_USEC 50000 -#if PA_API_VERSION != 9 +#if PA_API_VERSION < 9 #error Invalid PulseAudio API version #endif diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 3674f950..0fde33eb 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -37,7 +37,7 @@ #include -#if PA_API_VERSION != 9 +#if PA_API_VERSION < 10 #error Invalid PulseAudio API version #endif diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 7b34016c..0386c9df 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -37,7 +37,7 @@ #include -#if PA_API_VERSION != 9 +#if PA_API_VERSION < 9 #error Invalid PulseAudio API version #endif -- cgit From ad95c96a7278ac2e7d213e9575c2db1503d422fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:33:54 +0000 Subject: implement "pactl move-source-output" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1185 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 0fde33eb..f6f75498 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -46,8 +46,8 @@ static pa_context *context = NULL; static pa_mainloop_api *mainloop_api = NULL; -static char *device = NULL, *sample_name = NULL, *sink_name = NULL; -static uint32_t sink_input_idx = PA_INVALID_INDEX; +static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL; +static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX; static SNDFILE *sndfile = NULL; static pa_stream *sample_stream = NULL; @@ -66,7 +66,8 @@ static enum { PLAY_SAMPLE, REMOVE_SAMPLE, LIST, - MOVE_SINK_INPUT + MOVE_SINK_INPUT, + MOVE_SOURCE_OUTPUT } action = NONE; static void quit(int ret) { @@ -587,6 +588,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_move_sink_input_by_name(c, sink_input_idx, sink_name, simple_callback, NULL)); break; + case MOVE_SOURCE_OUTPUT: + pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL)); + break; + default: assert(0); } @@ -615,7 +620,8 @@ static void help(const char *argv0) { "%s [options] exit\n" "%s [options] upload-sample FILENAME [NAME]\n" "%s [options] play-sample NAME [SINK]\n" - "%s [options] move-sink-input NAME [SINK]\n" + "%s [options] move-sink-input ID SINK\n" + "%s [options] move-source-output ID SOURCE\n" "%s [options] remove-sample NAME\n\n" " -h, --help Show this help\n" " --version Show version\n\n" @@ -747,6 +753,15 @@ int main(int argc, char *argv[]) { sink_input_idx = atoi(argv[optind+1]); sink_name = pa_xstrdup(argv[optind+2]); + } else if (!strcmp(argv[optind], "move-source-output")) { + action = MOVE_SOURCE_OUTPUT; + if (optind+2 >= argc) { + fprintf(stderr, "You have to specify a source output index and a source\n"); + goto quit; + } + + source_output_idx = atoi(argv[optind+1]); + source_name = pa_xstrdup(argv[optind+2]); } } @@ -801,6 +816,7 @@ quit: pa_xfree(device); pa_xfree(sample_name); pa_xfree(sink_name); + pa_xfree(source_name); return ret; } -- cgit From b5cbea940ea70b8ed92fa3be6b742e8a14897337 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:14:06 +0000 Subject: fix bad printf() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1236 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index f6f75498..028f71c8 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -627,7 +627,7 @@ static void help(const char *argv0) { " --version Show version\n\n" " -s, --server=SERVER The name of the server to connect to\n" " -n, --client-name=NAME How to call this client on the server\n", - argv0, argv0, argv0, argv0, argv0, argv0, argv0); + argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); } enum { ARG_VERSION = 256 }; -- cgit From e385d93e5aad6a6fce754c00c804ff1d6a6746d4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:38:40 +0000 Subject: remove all occurences of pa_logXXX(__FILE__": and replace them by pa_logXXX(" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 20 ++++++++++---------- src/utils/pax11publish.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index fe8038e0..b9912701 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -49,12 +49,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { fd_set ifds, ofds; if (pa_pid_file_check_running(&pid) < 0) { - pa_log(__FILE__": no PulseAudio daemon running"); + pa_log("no PulseAudio daemon running"); goto fail; } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); + pa_log("socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -66,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect(): %s", strerror(errno)); + pa_log("connect(): %s", strerror(errno)); goto fail; } @@ -74,7 +74,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { break; if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { - pa_log(__FILE__": failed to kill PulseAudio daemon."); + pa_log("failed to kill PulseAudio daemon."); goto fail; } @@ -82,7 +82,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { } if (i >= 5) { - pa_log(__FILE__": daemon not responding."); + pa_log("daemon not responding."); goto fail; } @@ -97,7 +97,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select(): %s", strerror(errno)); + pa_log("select(): %s", strerror(errno)); goto fail; } @@ -109,7 +109,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", strerror(errno)); + pa_log("read(): %s", strerror(errno)); goto fail; } @@ -125,7 +125,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", strerror(errno)); + pa_log("read(): %s", strerror(errno)); goto fail; } @@ -138,7 +138,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write(): %s", strerror(errno)); + pa_log("write(): %s", strerror(errno)); goto fail; } @@ -152,7 +152,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write(): %s", strerror(errno)); + pa_log("write(): %s", strerror(errno)); goto fail; } diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 2a0d21d6..6a3c6dbc 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) { } if (!(d = XOpenDisplay(dname))) { - pa_log(__FILE__": XOpenDisplay() failed"); + pa_log("XOpenDisplay() failed"); goto finish; } -- cgit From 26201b27ec3233bb0f28539d63e49bb00d285d2a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 21 Aug 2006 22:37:09 +0000 Subject: fix pactl output (sink drivers and names where switched) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1306 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 028f71c8..110585f7 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -228,8 +228,8 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int "Latency: %0.0f usec\n" "Flags: %s%s%s\n", i->index, - i->driver, i->name, + i->driver, i->description, pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), -- cgit From 078420a9d2b2532062f30263d067e76735a30349 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 30 Aug 2006 13:02:29 +0000 Subject: We need to have a callback when changing volume or we might deadlock. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1345 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 32cb5f9a..c765b693 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1487,9 +1487,9 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_operation *o; if (request == SOUND_MIXER_READ_PCM) - o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, NULL, NULL); + o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, context_success_cb, i); else - o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, NULL, NULL); + o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, context_success_cb, i); if (!o) debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); -- cgit From 0f6098bf6428b17bbff2b2d6f4e8ead0d43d7f3a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 31 Aug 2006 15:31:33 +0000 Subject: work around bug in firefox which apparently misuses access() as NULL pointer test. Original patch by "alon". (Closes #27) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1352 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c765b693..ddb732f0 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2121,6 +2121,13 @@ int close(int fd) { } int access(const char *pathname, int mode) { + + if (!pathname) { + /* Firefox needs this. See #27 */ + errno = EFAULT; + return -1; + } + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); if (strcmp(pathname, "/dev/dsp") != 0 && -- cgit From 5fa9cdb6b4be9f5998af462a858124a528914bf3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 12:03:18 +0000 Subject: Merge FreeBSD compatibility patch (from Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1359 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index ddb732f0..dfef3f3a 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -53,6 +53,11 @@ #include #include +/* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */ +#if !defined(SIOCINQ) && defined(FIONREAD) +# define SIOCINQ FIONREAD +#endif + typedef enum { FD_INFO_MIXER, FD_INFO_STREAM, -- cgit From 65691997782da950f1e2f38700321e635cc5f37c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 19:47:53 +0000 Subject: implement a few more ioctl()s, including a subset of SNDCTL_DSP_GETOPTR. Just enough to make JavaSound work. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1373 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 0 src/utils/padsp.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 5 deletions(-) mode change 100644 => 100755 src/utils/padsp (limited to 'src/utils') diff --git a/src/utils/padsp b/src/utils/padsp old mode 100644 new mode 100755 diff --git a/src/utils/padsp.c b/src/utils/padsp.c index dfef3f3a..b20f0d06 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -93,6 +93,8 @@ struct fd_info { pa_cvolume sink_volume, source_volume; uint32_t sink_index, source_index; int volume_modify_count; + + int optr_n_blocks; PA_LLIST_FIELDS(fd_info); }; @@ -579,6 +581,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->volume_modify_count = 0; i->sink_index = (uint32_t) -1; i->source_index = (uint32_t) -1; + i->optr_n_blocks = 0; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -1952,6 +1955,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_streams(i); dsp_flush_socket(i); reset_params(i); + + i->optr_n_blocks = 0; pa_threaded_mainloop_unlock(i->mainloop); break; @@ -2040,14 +2045,76 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } + case SOUND_PCM_READ_RATE: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_RATE\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = i->sample_spec.rate; + pa_threaded_mainloop_unlock(i->mainloop); + break; + + case SOUND_PCM_READ_CHANNELS: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_CHANNELS\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = i->sample_spec.channels; + pa_threaded_mainloop_unlock(i->mainloop); + break; + + case SOUND_PCM_READ_BITS: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_BITS\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = pa_sample_size(&i->sample_spec)*8; + pa_threaded_mainloop_unlock(i->mainloop); + break; + + case SNDCTL_DSP_GETOPTR: { + count_info *info; + + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); + + info = (count_info*) argp; + memset(info, 0, sizeof(*info)); + + pa_threaded_mainloop_lock(i->mainloop); + + for (;;) { + pa_usec_t usec; + + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop); + + if (pa_stream_get_time(i->play_stream, &usec) >= 0) { + size_t k = pa_usec_to_bytes(usec, &i->sample_spec); + int m; + + info->bytes = (int) k; + m = k / i->fragment_size; + info->blocks = m - i->optr_n_blocks; + i->optr_n_blocks = m; + + break; + } + + if (pa_context_errno(i->context) != PA_ERR_NODATA) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); + break; + } + + pa_threaded_mainloop_wait(i->mainloop); + } + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr); + + break; + } + case SNDCTL_DSP_GETIPTR: debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); goto inval; - - case SNDCTL_DSP_GETOPTR: - debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETOPTR\n"); - goto inval; - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); -- cgit From 66ec460845d2e3df08a447b3ba93ee1006b04846 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 21:37:09 +0000 Subject: fix a bogus debug line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1374 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b20f0d06..883ffbd9 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2072,7 +2072,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETOPTR: { count_info *info; - debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOPTR\n"); info = (count_info*) argp; memset(info, 0, sizeof(*info)); -- cgit From 5f828c2c3df6a788b5f8be3422bd355b91104791 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 14 Sep 2006 14:56:31 +0000 Subject: Fix debug output for SNDCTL_DSP_SETFRAGMENT. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1396 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 883ffbd9..d947f697 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1875,7 +1875,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; case SNDCTL_DSP_SETFRAGMENT: - debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); -- cgit From 29ab939570ee739570a6bfaa6569bd6f6135df56 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 14 Sep 2006 16:00:57 +0000 Subject: Stop using x86-isms and use ISO C (oversized shifts are undefined). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1397 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d947f697..c7bfe5ab 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1879,7 +1879,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); - i->fragment_size = 1 << (*(int*) argp); + i->fragment_size = 1 << ((*(int*) argp) & 31); i->n_fragments = (*(int*) argp) >> 16; /* 0x7FFF means that we can set whatever we like */ -- cgit From 6ca819354cabdaeda0b122535a50fa49924d8d2d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 6 Nov 2006 10:17:39 +0000 Subject: The OSS spec is unclear what should happen when a reset is requested. Let's have a nicer attitude and keep as much settings as possible. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1406 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c7bfe5ab..5d96a984 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1003,12 +1003,21 @@ static void free_streams(fd_info *i) { pa_stream_disconnect(i->play_stream); pa_stream_unref(i->play_stream); i->play_stream = NULL; + i->io_flags |= PA_IO_EVENT_INPUT; } if (i->rec_stream) { pa_stream_disconnect(i->rec_stream); pa_stream_unref(i->rec_stream); i->rec_stream = NULL; + i->io_flags |= PA_IO_EVENT_OUTPUT; + } + + if (i->io_event) { + pa_mainloop_api *api; + + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_enable(i->io_event, i->io_flags); } } @@ -1954,7 +1963,6 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_streams(i); dsp_flush_socket(i); - reset_params(i); i->optr_n_blocks = 0; -- cgit From d4ca81fc2e8f480ec3f244b5f23e9303b5816452 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 6 Nov 2006 13:16:15 +0000 Subject: Fix some missing line breaks. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1410 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 5d96a984..a8ac8667 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -191,7 +191,7 @@ do { \ #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ - debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); @@ -199,7 +199,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \ - debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); @@ -207,7 +207,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \ - debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); -- cgit From 521daf6f0ac4fa6a2fbfb5d523c0c743342dca2b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 13:43:45 +0000 Subject: Huge trailing whitespace cleanup. Let's keep the tree pure from here on, mmmkay? git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1418 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 18 +-- src/utils/pacat.c | 86 +++++++-------- src/utils/pacmd.c | 40 +++---- src/utils/pactl.c | 76 ++++++------- src/utils/padsp.c | 278 +++++++++++++++++++++++------------------------ src/utils/paplay.c | 48 ++++---- src/utils/pax11publish.c | 24 ++-- 7 files changed, 285 insertions(+), 285 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 450182f5..f756ac01 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -40,7 +40,7 @@ static void dump_server(const pa_browse_info *i) { if (i->cookie) snprintf(t, sizeof(t), "0x%08x", *i->cookie); - + printf("server: %s\n" "server-version: %s\n" "user-name: %s\n" @@ -65,7 +65,7 @@ static void dump_device(const pa_browse_info *i) { i->device, i->description ? i->description : "n/a", i->sample_spec ? ss : "n/a"); - + } static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) { @@ -89,7 +89,7 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows dump_server(i); dump_device(i); break; - + case PA_BROWSE_REMOVE_SERVER: printf("\n=> removed server <%s>\n", i->name); break; @@ -109,7 +109,7 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows static void error_callback(pa_browser *b, const char *s, void *userdata) { pa_mainloop_api*m = userdata; - + fprintf(stderr, "Failure: %s\n", s); m->quit(m, 1); } @@ -128,7 +128,7 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGINT, exit_signal_callback, NULL); pa_signal_new(SIGTERM, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - + if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) { fprintf(stderr, "pa_browse_new_full(): %s\n", s); goto finish; @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) { pa_browser_set_callback(browser, browser_callback, NULL); pa_browser_set_error_callback(browser, error_callback, pa_mainloop_get_api(mainloop)); - + ret = 0; pa_mainloop_run(mainloop, &ret); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 1c581f4d..cb103c99 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -79,20 +79,20 @@ static void do_stream_write(size_t length) { if (!buffer || !buffer_length) return; - + l = length; if (l > buffer_length) l = buffer_length; - + if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { fprintf(stderr, "pa_stream_write() failed: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - + buffer_length -= l; buffer_index += l; - + if (!buffer_length) { pa_xfree(buffer); buffer = NULL; @@ -126,7 +126,7 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { quit(1); return; } - + assert(data && length); if (buffer) { @@ -156,7 +156,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; - + fprintf(stderr, "Stream successfully created.\n"); if (!(a = pa_stream_get_buffer_attr(s))) @@ -169,13 +169,13 @@ static void stream_state_callback(pa_stream *s, void *userdata) { assert(mode == RECORD); fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } - + } } - + break; - + case PA_STREAM_FAILED: default: fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); @@ -192,10 +192,10 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; - + case PA_CONTEXT_READY: { int r; - + assert(c && !stream); if (verbose) @@ -216,17 +216,17 @@ static void context_state_callback(pa_context *c, void *userdata) { fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } - + } else { if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) { fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } } - + break; } - + case PA_CONTEXT_TERMINATED: quit(0); break; @@ -238,10 +238,10 @@ static void context_state_callback(pa_context *c, void *userdata) { } return; - + fail: quit(1); - + } /* Connection draining complete */ @@ -257,14 +257,14 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); quit(1); } - - if (verbose) + + if (verbose) fprintf(stderr, "Playback stream drained.\n"); pa_stream_disconnect(stream); pa_stream_unref(stream); stream = NULL; - + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else { @@ -286,7 +286,7 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; - + buffer = pa_xmalloc(l); if ((r = read(fd, buffer, l)) <= 0) { @@ -296,17 +296,17 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if (stream) { pa_operation *o; - + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - + pa_operation_unref(o); } else quit(0); - + } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); @@ -335,7 +335,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve } assert(buffer_length); - + if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); quit(1); @@ -366,7 +366,7 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { pa_usec_t latency, usec; int negative = 0; - + assert(s); if (!success || @@ -387,13 +387,13 @@ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int s if (!stream) return; - + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); } static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct timeval next; - + if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) { pa_operation *o; if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) @@ -481,7 +481,7 @@ int main(int argc, char *argv[]) { help(bn); ret = 0; goto quit; - + case ARG_VERSION: printf("pacat "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; @@ -525,7 +525,7 @@ int main(int argc, char *argv[]) { break; } - case ARG_CHANNELS: + case ARG_CHANNELS: sample_spec.channels = atoi(optarg); break; @@ -545,7 +545,7 @@ int main(int argc, char *argv[]) { channel_map_set = 1; break; - + default: goto quit; } @@ -560,7 +560,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Channel map doesn't match sample specification\n"); goto quit; } - + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); @@ -570,22 +570,22 @@ int main(int argc, char *argv[]) { if (!(optind >= argc)) { if (optind+1 == argc) { int fd; - + if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { fprintf(stderr, "open(): %s\n", strerror(errno)); goto quit; } - + if (dup2(fd, mode == PLAYBACK ? 0 : 1) < 0) { fprintf(stderr, "dup2(): %s\n", strerror(errno)); goto quit; } - + close(fd); if (!stream_name) stream_name = pa_xstrdup(argv[optind]); - + } else { fprintf(stderr, "Too many arguments.\n"); goto quit; @@ -616,7 +616,7 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + if (!(stdio_event = mainloop_api->io_new(mainloop_api, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, @@ -641,7 +641,7 @@ int main(int argc, char *argv[]) { pa_gettimeofday(&tv); pa_timeval_add(&tv, TIME_EVENT_USEC); - + if (!(time_event = mainloop_api->time_new(mainloop_api, &tv, time_event_callback, NULL))) { fprintf(stderr, "time_new() failed.\n"); goto quit; @@ -653,7 +653,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "pa_mainloop_run() failed.\n"); goto quit; } - + quit: if (stream) pa_stream_unref(stream); @@ -670,7 +670,7 @@ quit: assert(mainloop_api); mainloop_api->time_free(time_event); } - + if (m) { pa_signal_done(); pa_mainloop_free(m); @@ -682,6 +682,6 @@ quit: pa_xfree(device); pa_xfree(client_name); pa_xfree(stream_name); - + return ret; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index b9912701..d25b26c3 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -64,12 +64,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (i = 0; i < 5; i++) { int r; - + if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { pa_log("connect(): %s", strerror(errno)); goto fail; } - + if (r >= 0) break; @@ -94,7 +94,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { FD_SET(fd, &ifds); FD_ZERO(&ofds); - + for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { pa_log("select(): %s", strerror(errno)); @@ -104,19 +104,19 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (FD_ISSET(0, &ifds)) { ssize_t r; assert(!ibuf_length); - + if ((r = read(0, ibuf, sizeof(ibuf))) <= 0) { if (r == 0) break; - + pa_log("read(): %s", strerror(errno)); goto fail; } - + ibuf_length = (size_t) r; ibuf_index = 0; } - + if (FD_ISSET(fd, &ifds)) { ssize_t r; assert(!obuf_length); @@ -124,7 +124,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if ((r = read(fd, obuf, sizeof(obuf))) <= 0) { if (r == 0) break; - + pa_log("read(): %s", strerror(errno)); goto fail; } @@ -136,12 +136,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (FD_ISSET(1, &ofds)) { ssize_t r; assert(obuf_length); - + if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { pa_log("write(): %s", strerror(errno)); goto fail; } - + obuf_length -= (size_t) r; obuf_index += obuf_index; @@ -150,12 +150,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (FD_ISSET(fd, &ofds)) { ssize_t r; assert(ibuf_length); - + if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { pa_log("write(): %s", strerror(errno)); goto fail; } - + ibuf_length -= (size_t) r; ibuf_index += obuf_index; @@ -163,24 +163,24 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { FD_ZERO(&ifds); FD_ZERO(&ofds); - + if (obuf_length <= 0) FD_SET(fd, &ifds); else FD_SET(1, &ofds); - + if (ibuf_length <= 0) FD_SET(0, &ifds); else FD_SET(fd, &ofds); } - + ret = 0; - + fail: if (fd >= 0) close(fd); - + return ret; } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 110585f7..0c418c4f 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -112,13 +112,13 @@ static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) pa_bytes_snprint(s, sizeof(s), i->scache_size); printf("Sample cache size: %s\n", s); - + complete_action(); } static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; - + if (!i) { fprintf(stderr, "Failed to get server information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -149,7 +149,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - + if (is_last < 0) { fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -160,7 +160,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ complete_action(); return; } - + assert(i); if (nl) @@ -207,7 +207,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int complete_action(); return; } - + assert(i); if (nl) @@ -215,7 +215,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int nl = 1; snprintf(t, sizeof(t), "%u", i->monitor_of_sink); - + printf("*** Source #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -256,7 +256,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int complete_action(); return; } - + assert(i); if (nl) @@ -264,7 +264,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int nl = 1; snprintf(t, sizeof(t), "%u", i->n_used); - + printf("*** Module #%u ***\n" "Name: %s\n" "Argument: %s\n" @@ -290,7 +290,7 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int complete_action(); return; } - + assert(i); if (nl) @@ -298,7 +298,7 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int nl = 1; snprintf(t, sizeof(t), "%u", i->owner_module); - + printf("*** Client #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -322,7 +322,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info complete_action(); return; } - + assert(i); if (nl) @@ -331,7 +331,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); - + printf("*** Sink Input #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -372,17 +372,17 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu complete_action(); return; } - + assert(i); if (nl) printf("\n"); nl = 1; - + snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); - + printf("*** Source Output #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -420,16 +420,16 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int complete_action(); return; } - + assert(i); if (nl) printf("\n"); nl = 1; - + pa_bytes_snprint(t, sizeof(t), i->bytes); - + printf("*** Sample #%u ***\n" "Name: %s\n" "Volume: %s\n" @@ -461,7 +461,7 @@ static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i, complete_action(); return; } - + assert(i); if (nl) @@ -497,11 +497,11 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_CREATING: case PA_STREAM_READY: break; - + case PA_STREAM_TERMINATED: drain(); break; - + case PA_STREAM_FAILED: default: fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); @@ -524,7 +524,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { fprintf(stderr, "Premature end of file\n"); quit(1); } - + pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE); sample_length -= length; @@ -551,7 +551,7 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL)); break; - case PLAY_SAMPLE: + case PLAY_SAMPLE: pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL)); break; @@ -562,12 +562,12 @@ static void context_state_callback(pa_context *c, void *userdata) { case UPLOAD_SAMPLE: sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL); assert(sample_stream); - + pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); pa_stream_connect_upload(sample_stream, sample_length); break; - + case EXIT: pa_operation_unref(pa_context_exit_daemon(c, NULL, NULL)); drain(); @@ -578,7 +578,7 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL)); pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL)); pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL)); - pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL)); + pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL)); pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL)); pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL)); pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL)); @@ -591,7 +591,7 @@ static void context_state_callback(pa_context *c, void *userdata) { case MOVE_SOURCE_OUTPUT: pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL)); break; - + default: assert(0); } @@ -650,14 +650,14 @@ int main(int argc, char *argv[]) { bn = argv[0]; else bn++; - + while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) { switch (c) { case 'h' : help(bn); ret = 0; goto quit; - + case ARG_VERSION: printf("pactl "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; @@ -680,7 +680,7 @@ int main(int argc, char *argv[]) { if (!client_name) client_name = pa_xstrdup(bn); - + if (optind < argc) { if (!strcmp(argv[optind], "stat")) action = STAT; @@ -712,13 +712,13 @@ int main(int argc, char *argv[]) { tmp[n] = 0; sample_name = pa_xstrdup(tmp); } - + memset(&sfinfo, 0, sizeof(sfinfo)); if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfinfo))) { fprintf(stderr, "Failed to open sound file.\n"); goto quit; } - + sample_spec.format = PA_SAMPLE_FLOAT32; sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; @@ -735,7 +735,7 @@ int main(int argc, char *argv[]) { if (optind+2 < argc) device = pa_xstrdup(argv[optind+2]); - + } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; if (optind+1 >= argc) { @@ -783,7 +783,7 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); goto quit; @@ -808,7 +808,7 @@ quit: pa_signal_done(); pa_mainloop_free(m); } - + if (sndfile) sf_close(sndfile); diff --git a/src/utils/padsp.c b/src/utils/padsp.c index a8ac8667..679a5d01 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ struct fd_info { pthread_mutex_t mutex; int ref; int unusable; - + fd_info_type_t type; int app_fd, thread_fd; @@ -95,7 +95,7 @@ struct fd_info { int volume_modify_count; int optr_n_blocks; - + PA_LLIST_FIELDS(fd_info); }; @@ -248,7 +248,7 @@ static int padsp_disabled(void) { * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value * of 7 disables padsp entirely. */ - + pthread_mutex_lock(&func_mutex); if (!sym_resolved) { sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__"); @@ -259,14 +259,14 @@ static int padsp_disabled(void) { if (!sym) return 0; - + return *sym; } static int dsp_cloak_enable(void) { if (padsp_disabled() & 1) return 0; - + if (getenv("PADSP_NO_DSP")) return 0; @@ -302,7 +302,7 @@ static int function_enter(void) { /* Avoid recursive calls */ static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT; pthread_once(&recursion_key_once, recursion_key_alloc); - + if (pthread_getspecific(recursion_key)) return 0; @@ -320,10 +320,10 @@ static void fd_info_free(fd_info *i) { debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd); dsp_drain(i); - + if (i->mainloop) pa_threaded_mainloop_stop(i->mainloop); - + if (i->play_stream) { pa_stream_disconnect(i->play_stream); pa_stream_unref(i->play_stream); @@ -338,7 +338,7 @@ static void fd_info_free(fd_info *i) { pa_context_disconnect(i->context); pa_context_unref(i->context); } - + if (i->mainloop) pa_threaded_mainloop_free(i->mainloop); @@ -360,7 +360,7 @@ static void fd_info_free(fd_info *i) { static fd_info *fd_info_ref(fd_info *i) { assert(i); - + pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); i->ref++; @@ -404,7 +404,7 @@ static void context_state_cb(pa_context *c, void *userdata) { static void reset_params(fd_info *i) { assert(i); - + i->sample_spec.format = PA_SAMPLE_U8; i->sample_spec.channels = 1; i->sample_spec.rate = 8000; @@ -418,7 +418,7 @@ static const char *client_name(char *buf, size_t n) { if ((e = getenv("PADSP_CLIENT_NAME"))) return e; - + if (pa_get_binary_name(p, sizeof(p))) snprintf(buf, n, "OSS Emulation[%s]", p); else @@ -440,7 +440,7 @@ static void atfork_prepare(void) { fd_info *i; debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n"); - + function_enter(); pthread_mutex_lock(&fd_infos_mutex); @@ -452,13 +452,13 @@ static void atfork_prepare(void) { pthread_mutex_lock(&func_mutex); - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n"); } static void atfork_parent(void) { fd_info *i; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n"); pthread_mutex_unlock(&func_mutex); @@ -471,19 +471,19 @@ static void atfork_parent(void) { pthread_mutex_unlock(&fd_infos_mutex); function_exit(); - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n"); } static void atfork_child(void) { fd_info *i; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n"); /* We do only the bare minimum to get all fds closed */ pthread_mutex_init(&func_mutex, NULL); pthread_mutex_init(&fd_infos_mutex, NULL); - + for (i = fd_infos; i; i = i->next) { pthread_mutex_init(&i->mutex, NULL); @@ -556,7 +556,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ pthread_once(&install_atfork_once, install_atfork); - + if (!(i = malloc(sizeof(fd_info)))) { *_errno = ENOMEM; goto fail; @@ -638,12 +638,12 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { unlock_and_fail: pa_threaded_mainloop_unlock(i->mainloop); - + fail: if (i) fd_info_unref(i); - + return NULL; } @@ -671,7 +671,7 @@ static fd_info* fd_info_find(int fd) { fd_info *i; pthread_mutex_lock(&fd_infos_mutex); - + for (i = fd_infos; i; i = i->next) if (i->app_fd == fd && !i->unusable) { fd_info_ref(i); @@ -679,7 +679,7 @@ static fd_info* fd_info_find(int fd) { } pthread_mutex_unlock(&fd_infos_mutex); - + return i; } @@ -907,7 +907,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { case PA_STREAM_READY: debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n"); break; - + case PA_STREAM_FAILED: debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); fd_info_shutdown(i); @@ -923,7 +923,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { static int create_playback_stream(fd_info *i) { pa_buffer_attr attr; int n; - + assert(i); fix_metrics(i); @@ -942,7 +942,7 @@ static int create_playback_stream(fd_info *i) { attr.tlength = i->fragment_size * i->n_fragments; attr.prebuf = i->fragment_size; attr.minreq = i->fragment_size; - + if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -952,7 +952,7 @@ static int create_playback_stream(fd_info *i) { setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); n = i->fragment_size; setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); - + return 0; fail: @@ -962,7 +962,7 @@ fail: static int create_record_stream(fd_info *i) { pa_buffer_attr attr; int n; - + assert(i); fix_metrics(i); @@ -979,7 +979,7 @@ static int create_record_stream(fd_info *i) { memset(&attr, 0, sizeof(attr)); attr.maxlength = i->fragment_size * (i->n_fragments+1); attr.fragsize = i->fragment_size; - + if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -989,7 +989,7 @@ static int create_record_stream(fd_info *i) { setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); n = i->fragment_size; setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); - + return 0; fail: @@ -1025,7 +1025,7 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even fd_info *i = userdata; pa_threaded_mainloop_signal(i->mainloop, 0); - + if (flags & PA_IO_EVENT_INPUT) { if (!i->play_stream) { @@ -1035,7 +1035,7 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even if (fd_info_copy_data(i, 0) < 0) goto fail; } - + } else if (flags & PA_IO_EVENT_OUTPUT) { if (!i->rec_stream) { @@ -1050,7 +1050,7 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even goto fail; return; - + fail: /* We can't do anything better than removing the event source */ fd_info_shutdown(i); @@ -1100,7 +1100,7 @@ static int dsp_open(int flags, int *_errno) { if (!(i->io_event = api->io_new(api, i->thread_fd, i->io_flags, io_event_cb, i))) goto fail; - + pa_threaded_mainloop_unlock(i->mainloop); debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); @@ -1108,7 +1108,7 @@ static int dsp_open(int flags, int *_errno) { fd_info_add_to_list(i); ret = i->app_fd; fd_info_unref(i); - + return ret; fail: @@ -1116,7 +1116,7 @@ fail: if (i) fd_info_unref(i); - + *_errno = EIO; debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n"); @@ -1138,7 +1138,7 @@ static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, v if (!pa_cvolume_equal(&i->sink_volume, &si->volume)) i->volume_modify_count++; - + i->sink_volume = si->volume; i->sink_index = si->index; @@ -1160,7 +1160,7 @@ static void source_info_cb(pa_context *context, const pa_source_info *si, int eo if (!pa_cvolume_equal(&i->source_volume, &si->volume)) i->volume_modify_count++; - + i->source_volume = si->volume; i->source_index = si->index; @@ -1193,13 +1193,13 @@ static int mixer_open(int flags, int *_errno) { debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n"); - if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) + if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) return -1; - + pa_threaded_mainloop_lock(i->mainloop); pa_context_set_subscribe_callback(i->context, subscribe_cb, i); - + if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; @@ -1274,7 +1274,7 @@ static int mixer_open(int flags, int *_errno) { fd_info_add_to_list(i); ret = i->app_fd; fd_info_unref(i); - + return ret; fail: @@ -1285,7 +1285,7 @@ fail: if (i) fd_info_unref(i); - + *_errno = EIO; debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n"); @@ -1323,7 +1323,7 @@ static int sndstat_open(int flags, int *_errno) { int e; debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n"); - + if (flags != O_RDONLY #ifdef O_LARGEFILE && flags != (O_RDONLY|O_LARGEFILE) @@ -1401,16 +1401,16 @@ int open(const char *filename, int flags, ...) { } function_exit(); - + if (_errno) errno = _errno; - + return r; } static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; - + switch (request) { case SOUND_MIXER_READ_DEVMASK : debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n"); @@ -1423,7 +1423,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno *(int*) argp = SOUND_MASK_IGAIN; break; - + case SOUND_MIXER_READ_STEREODEVS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n"); @@ -1434,7 +1434,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno if (i->source_volume.channels > 1) *(int*) argp |= SOUND_MASK_IGAIN; pa_threaded_mainloop_unlock(i->mainloop); - + break; case SOUND_MIXER_READ_RECSRC: @@ -1452,7 +1452,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno *(int*) argp = 0; break; - + case SOUND_MIXER_READ_PCM: case SOUND_MIXER_READ_IGAIN: { pa_cvolume *v; @@ -1515,23 +1515,23 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CONTEXT_CHECK_DEAD_GOTO(i, exit_loop); - + pa_threaded_mainloop_wait(i->mainloop); } exit_loop: - + if (!i->operation_success) debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); pa_operation_unref(o); } - + /* We don't wait for completion here */ i->volume_modify_count++; } - + pa_threaded_mainloop_unlock(i->mainloop); - + break; } @@ -1548,7 +1548,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_threaded_mainloop_unlock(i->mainloop); break; } - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); @@ -1557,44 +1557,44 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno } ret = 0; - + fail: - + return ret; } static int map_format(int *fmt, pa_sample_spec *ss) { - + switch (*fmt) { case AFMT_MU_LAW: ss->format = PA_SAMPLE_ULAW; break; - + case AFMT_A_LAW: ss->format = PA_SAMPLE_ALAW; break; - + case AFMT_S8: *fmt = AFMT_U8; /* fall through */ case AFMT_U8: ss->format = PA_SAMPLE_U8; break; - + case AFMT_U16_BE: *fmt = AFMT_S16_BE; /* fall through */ case AFMT_S16_BE: ss->format = PA_SAMPLE_S16BE; break; - + case AFMT_U16_LE: *fmt = AFMT_S16_LE; /* fall through */ case AFMT_S16_LE: ss->format = PA_SAMPLE_S16LE; break; - + default: ss->format = PA_SAMPLE_S16NE; *fmt = AFMT_S16_NE; @@ -1666,14 +1666,14 @@ static int dsp_flush_socket(fd_info *i) { static int dsp_empty_socket(fd_info *i) { #ifdef SIOCINQ int ret = -1; - + /* Empty the socket */ for (;;) { int l; - + if (i->thread_fd < 0) break; - + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); break; @@ -1683,7 +1683,7 @@ static int dsp_empty_socket(fd_info *i) { ret = 0; break; } - + pa_threaded_mainloop_wait(i->mainloop); } @@ -1700,19 +1700,19 @@ static int dsp_drain(fd_info *i) { if (!i->mainloop) return 0; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n"); pa_threaded_mainloop_lock(i->mainloop); if (dsp_empty_socket(i) < 0) goto fail; - + if (!i->play_stream) goto fail; debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n"); - + if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -1721,7 +1721,7 @@ static int dsp_drain(fd_info *i) { i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); - + pa_threaded_mainloop_wait(i->mainloop); } @@ -1731,9 +1731,9 @@ static int dsp_drain(fd_info *i) { } r = 0; - + fail: - + if (o) pa_operation_unref(o); @@ -1755,7 +1755,7 @@ static int dsp_trigger(fd_info *i) { goto fail; debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n"); - + if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -1764,7 +1764,7 @@ static int dsp_trigger(fd_info *i) { i->operation_success = 0; while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); - + pa_threaded_mainloop_wait(i->mainloop); } @@ -1774,9 +1774,9 @@ static int dsp_trigger(fd_info *i) { } r = 0; - + fail: - + if (o) pa_operation_unref(o); @@ -1787,11 +1787,11 @@ fail: static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; - + switch (request) { case SNDCTL_DSP_SETFMT: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); if (*(int*) argp == AFMT_QUERY) @@ -1804,12 +1804,12 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_unlock(i->mainloop); break; } - + case SNDCTL_DSP_SPEED: { pa_sample_spec ss; int valid; char t[256]; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1821,7 +1821,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->sample_spec = ss; free_streams(i); } - + debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); pa_threaded_mainloop_unlock(i->mainloop); @@ -1833,24 +1833,24 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } - + case SNDCTL_DSP_STEREO: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); - + i->sample_spec.channels = *(int*) argp ? 2 : 1; free_streams(i); - + pa_threaded_mainloop_unlock(i->mainloop); return 0; case SNDCTL_DSP_CHANNELS: { pa_sample_spec ss; int valid; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); ss = i->sample_spec; @@ -1860,7 +1860,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->sample_spec = ss; free_streams(i); } - + pa_threaded_mainloop_unlock(i->mainloop); if (!valid) { @@ -1878,16 +1878,16 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) fix_metrics(i); *(int*) argp = i->fragment_size; - + pa_threaded_mainloop_unlock(i->mainloop); - + break; case SNDCTL_DSP_SETFRAGMENT: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); - + i->fragment_size = 1 << ((*(int*) argp) & 31); i->n_fragments = (*(int*) argp) >> 16; @@ -1896,14 +1896,14 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->n_fragments = 12; free_streams(i); - + pa_threaded_mainloop_unlock(i->mainloop); - + break; - + case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - + *(int*) argp = DSP_CAP_DUPLEX #ifdef DSP_CAP_MULTI | DSP_CAP_MULTI @@ -1913,13 +1913,13 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETODELAY: { int l; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = 0; - + for (;;) { pa_usec_t usec; @@ -1937,10 +1937,10 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_wait(i->mainloop); } - + exit_loop: -#ifdef SIOCINQ +#ifdef SIOCINQ if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); else @@ -1955,39 +1955,39 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } - + case SNDCTL_DSP_RESET: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n"); - + pa_threaded_mainloop_lock(i->mainloop); free_streams(i); dsp_flush_socket(i); i->optr_n_blocks = 0; - + pa_threaded_mainloop_unlock(i->mainloop); break; } - + case SNDCTL_DSP_GETFMTS: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n"); - + *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE; break; } case SNDCTL_DSP_POST: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n"); - - if (dsp_trigger(i) < 0) + + if (dsp_trigger(i) < 0) *_errno = EIO; break; - case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_SYNC: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n"); - - if (dsp_drain(i) < 0) + + if (dsp_drain(i) < 0) *_errno = EIO; break; @@ -2055,36 +2055,36 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SOUND_PCM_READ_RATE: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_RATE\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = i->sample_spec.rate; pa_threaded_mainloop_unlock(i->mainloop); - break; + break; case SOUND_PCM_READ_CHANNELS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_CHANNELS\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = i->sample_spec.channels; pa_threaded_mainloop_unlock(i->mainloop); - break; + break; case SOUND_PCM_READ_BITS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_BITS\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = pa_sample_size(&i->sample_spec)*8; pa_threaded_mainloop_unlock(i->mainloop); - break; - + break; + case SNDCTL_DSP_GETOPTR: { count_info *info; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOPTR\n"); info = (count_info*) argp; memset(info, 0, sizeof(*info)); - + pa_threaded_mainloop_lock(i->mainloop); for (;;) { @@ -2095,7 +2095,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if (pa_stream_get_time(i->play_stream, &usec) >= 0) { size_t k = pa_usec_to_bytes(usec, &i->sample_spec); int m; - + info->bytes = (int) k; m = k / i->fragment_size; info->blocks = m - i->optr_n_blocks; @@ -2111,7 +2111,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_wait(i->mainloop); } - + pa_threaded_mainloop_unlock(i->mainloop); debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr); @@ -2122,7 +2122,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETIPTR: debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); goto inval; - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); @@ -2132,9 +2132,9 @@ inval: } ret = 0; - + fail: - + return ret; } @@ -2165,14 +2165,14 @@ int ioctl(int fd, unsigned long request, ...) { r = mixer_ioctl(i, request, argp, &_errno); else r = dsp_ioctl(i, request, argp, &_errno); - + fd_info_unref(i); if (_errno) errno = _errno; function_exit(); - + return r; } @@ -2194,7 +2194,7 @@ int close(int fd) { fd_info_remove_from_list(i); fd_info_unref(i); - + function_exit(); return 0; @@ -2207,7 +2207,7 @@ int access(const char *pathname, int mode) { errno = EFAULT; return -1; } - + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); if (strcmp(pathname, "/dev/dsp") != 0 && @@ -2236,7 +2236,7 @@ int open64(const char *filename, int flags, ...) { mode_t mode = 0; debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); - + va_start(args, flags); if (flags & O_CREAT) mode = va_arg(args, mode_t); @@ -2259,7 +2259,7 @@ FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; mode_t m; - + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename); if (strcmp(filename, "/dev/dsp") != 0 && @@ -2293,7 +2293,7 @@ FILE* fopen(const char *filename, const char *mode) { close(fd); return NULL; } - + return f; } @@ -2337,9 +2337,9 @@ int fclose(FILE *f) { /* Dirty trick to avoid that the fd is not freed twice, once by us * and once by the real fclose() */ i->app_fd = -1; - + fd_info_unref(i); - + function_exit(); LOAD_FCLOSE_FUNC(); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 0386c9df..1617b27d 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -77,14 +77,14 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); quit(1); } - - if (verbose) + + if (verbose) fprintf(stderr, "Playback stream drained.\n"); pa_stream_disconnect(stream); pa_stream_unref(stream); stream = NULL; - + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else { @@ -111,7 +111,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { if ((bytes = readf_function(sndfile, data, length/k)) > 0) bytes *= k; - + } else bytes = sf_read_raw(sndfile, data, length); @@ -140,7 +140,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { if (verbose) fprintf(stderr, "Stream successfully created\n"); break; - + case PA_STREAM_FAILED: default: fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); @@ -157,10 +157,10 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; - + case PA_CONTEXT_READY: { pa_cvolume cv; - + assert(c && !stream); if (verbose) @@ -172,10 +172,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL); - + break; } - + case PA_CONTEXT_TERMINATED: quit(0); break; @@ -192,7 +192,7 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, if (verbose) fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); - + } static void help(const char *argv0) { @@ -251,7 +251,7 @@ int main(int argc, char *argv[]) { help(bn); ret = 0; goto quit; - + case ARG_VERSION: printf("paplay "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; @@ -302,7 +302,7 @@ int main(int argc, char *argv[]) { } filename = optind < argc ? argv[optind] : "STDIN"; - + memset(&sfinfo, 0, sizeof(sfinfo)); if (optind < argc) @@ -317,9 +317,9 @@ int main(int argc, char *argv[]) { sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; - + readf_function = NULL; - + switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: @@ -327,11 +327,11 @@ int main(int argc, char *argv[]) { sample_spec.format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; - + case SF_FORMAT_ULAW: sample_spec.format = PA_SAMPLE_ULAW; break; - + case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_ALAW; break; @@ -369,13 +369,13 @@ int main(int argc, char *argv[]) { if (!stream_name) stream_name = pa_utf8_filter(n); } - + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); fprintf(stderr, "Using sample spec '%s'\n", t); } - + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); @@ -390,7 +390,7 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + /* Create a new connection context */ if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); @@ -407,7 +407,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "pa_mainloop_run() failed.\n"); goto quit; } - + quit: if (stream) pa_stream_unref(stream); @@ -427,6 +427,6 @@ quit: if (sndfile) sf_close(sndfile); - + return ret; } diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 6a3c6dbc..00332f65 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio 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 Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) { switch (mode) { case DUMP: { char t[1024]; - if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) printf("Server: %s\n", t); if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) printf("Source: %s\n", t); @@ -110,10 +110,10 @@ int main(int argc, char *argv[]) { break; } - + case IMPORT: { char t[1024]; - if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) printf("PULSE_SERVER='%s'\nexport PULSE_SERVER\n", t); if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) printf("PULSE_SOURCE='%s'\nexport PULSE_SOURCE\n", t); @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) { pa_x11_del_prop(d, "PULSE_SOURCE"); pa_x11_del_prop(d, "PULSE_ID"); pa_x11_del_prop(d, "PULSE_COOKIE"); - + if (server) pa_x11_set_prop(d, "PULSE_SERVER", server); else if (conf->default_server) @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Failed to get FQDN.\n"); goto finish; } - + pa_x11_set_prop(d, "PULSE_SERVER", hn); } @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) { pa_x11_set_prop(d, "PULSE_SOURCE", conf->default_source); pa_client_conf_free(conf); - + if (pa_authkey_load_auto(cookie_file, cookie, sizeof(cookie)) < 0) { fprintf(stderr, "Failed to load cookie data\n"); goto finish; @@ -201,20 +201,20 @@ int main(int argc, char *argv[]) { pa_x11_del_prop(d, "PULSE_ID"); pa_x11_del_prop(d, "PULSE_COOKIE"); break; - + default: fprintf(stderr, "No yet implemented.\n"); goto finish; } ret = 0; - + finish: if (d) { XSync(d, False); XCloseDisplay(d); } - + return ret; } -- cgit From 19bd9148c5d16a8363065ca128e06037780337ab Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 14:06:24 +0000 Subject: Fix error messages for failure connecting streams. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1419 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 679a5d01..c6025417 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -909,7 +909,15 @@ static void stream_state_cb(pa_stream *s, void * userdata) { break; case PA_STREAM_FAILED: - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + if (s == i->play_stream) { + debug(DEBUG_LEVEL_NORMAL, + __FILE__": pa_stream_connect_playback() failed: %s\n", + pa_strerror(pa_context_errno(i->context))); + } else if (s == i->rec_stream) { + debug(DEBUG_LEVEL_NORMAL, + __FILE__": pa_stream_connect_record() failed: %s\n", + pa_strerror(pa_context_errno(i->context))); + } fd_info_shutdown(i); break; @@ -981,7 +989,7 @@ static int create_record_stream(fd_info *i) { attr.fragsize = i->fragment_size; if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } -- cgit From c992ed9c47854338106b38a1d093c4c1bf65e96d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 14:17:57 +0000 Subject: Free stream objects when they've been invalidated. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1420 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c6025417..aa0ec9dd 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -913,10 +913,14 @@ static void stream_state_cb(pa_stream *s, void * userdata) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + pa_stream_unref(i->play_stream); + i->play_stream = NULL; } else if (s == i->rec_stream) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + pa_stream_unref(i->rec_stream); + i->rec_stream = NULL; } fd_info_shutdown(i); break; -- cgit From 4c0a481f79715c0e783000c75e800d2401c11019 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 14:20:53 +0000 Subject: Report IO error on ioctl() when we're in a fatal error state. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1421 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index aa0ec9dd..b4c5bb0b 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1800,6 +1800,16 @@ fail: static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; + if (i->thread_fd == -1) { + /* + * We've encountered some fatal error and are just waiting + * for a close. + */ + debug(DEBUG_LEVEL_NORMAL, __FILE__": got ioctl 0x%08lx in fatal error state\n", request); + *_errno = EIO; + return -1; + } + switch (request) { case SNDCTL_DSP_SETFMT: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); -- cgit From 4171f2504a4e0de5c46c3237da009f5355cf57ec Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 19 Jan 2007 08:00:31 +0000 Subject: Make sure we report success for SNDCTL_DSP_SETDUPLEX. (Patch by ZlatkO) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1422 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b4c5bb0b..2b314a9c 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2145,6 +2145,11 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); goto inval; + case SNDCTL_DSP_SETDUPLEX: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n"); + /* this is a no-op */ + break; + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); -- cgit From 06211b7c8fd329137ae9003818543912a87d9898 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Feb 2007 15:35:19 +0000 Subject: Add copyright notices to all relevant files. (based on svn log) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 2 ++ src/utils/pacat.c | 3 +++ src/utils/pacmd.c | 2 ++ src/utils/pactl.c | 2 ++ src/utils/padsp | 3 +++ src/utils/padsp.c | 3 +++ src/utils/paplay.c | 3 +++ src/utils/pax11publish.c | 2 ++ 8 files changed, 20 insertions(+) (limited to 'src/utils') diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index f756ac01..d88001ef 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pacat.c b/src/utils/pacat.c index cb103c99..96b6adb7 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index d25b26c3..16e5822f 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 0c418c4f..b95cbfee 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/padsp b/src/utils/padsp index bae5a728..c70c3af7 100755 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -4,6 +4,9 @@ # # This file is part of PulseAudio. # +# Copyright 2006 Lennart Poettering +# Copyright 2006 Pierre Ossman for Cendio AB +# # PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 2b314a9c..444e1b4d 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 1617b27d..2c779a7a 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 00332f65..9a50f8ef 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, -- cgit From 9ee398107e524ca71a0cfd23e003daa300d1e227 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 7 Mar 2007 09:27:30 +0000 Subject: Add support for SNDCTL_DSP_SETTRIGGER. (closes #56) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1437 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 9 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 444e1b4d..fddd8fb4 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -4,7 +4,7 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -84,6 +84,8 @@ struct fd_info { pa_context *context; pa_stream *play_stream; pa_stream *rec_stream; + int play_precork; + int rec_precork; pa_io_event *io_event; pa_io_event_flags_t io_flags; @@ -197,7 +199,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ -} while(0); +} while(0) #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ @@ -205,7 +207,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ -} while(0); +} while(0) #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ @@ -213,7 +215,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ -} while(0); +} while(0) static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); @@ -572,6 +574,8 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->context = NULL; i->play_stream = NULL; i->rec_stream = NULL; + i->play_precork = 0; + i->rec_precork = 0; i->io_event = NULL; i->io_flags = 0; pthread_mutex_init(&i->mutex, NULL); @@ -937,7 +941,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { static int create_playback_stream(fd_info *i) { pa_buffer_attr attr; - int n; + int n, flags; assert(i); @@ -958,7 +962,12 @@ static int create_playback_stream(fd_info *i) { attr.prebuf = i->fragment_size; attr.minreq = i->fragment_size; - if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { + flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE; + if (i->play_precork) { + flags |= PA_STREAM_START_CORKED; + debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n"); + } + if (pa_stream_connect_playback(i->play_stream, NULL, &attr, flags, NULL, NULL) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -976,7 +985,7 @@ fail: static int create_record_stream(fd_info *i) { pa_buffer_attr attr; - int n; + int n, flags; assert(i); @@ -995,7 +1004,12 @@ static int create_record_stream(fd_info *i) { attr.maxlength = i->fragment_size * (i->n_fragments+1); attr.fragsize = i->fragment_size; - if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { + flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE; + if (i->rec_precork) { + flags |= PA_STREAM_START_CORKED; + debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n"); + } + if (pa_stream_connect_record(i->rec_stream, NULL, &attr, flags) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1800,6 +1814,44 @@ fail: return 0; } +static int dsp_cork(fd_info *i, pa_stream *s, int b) { + pa_operation *o = NULL; + int r = -1; + + pa_threaded_mainloop_lock(i->mainloop); + + if (!(o = pa_stream_cork(s, b, stream_success_cb, i))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + i->operation_success = 0; + while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (s == i->play_stream) + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); + else if (s == i->rec_stream) + RECORD_STREAM_CHECK_DEAD_GOTO(i, fail); + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (!i->operation_success) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + r = 0; + +fail: + + if (o) + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(i->mainloop); + + return 0; +} + static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; @@ -1929,7 +1981,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - *(int*) argp = DSP_CAP_DUPLEX + *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER #ifdef DSP_CAP_MULTI | DSP_CAP_MULTI #endif @@ -2009,6 +2061,32 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *_errno = EIO; break; + case SNDCTL_DSP_SETTRIGGER: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp); + + if (!i->io_event) { + *_errno = EIO; + break; + } + + i->play_precork = !((*(int*) argp) & PCM_ENABLE_OUTPUT); + + if (i->play_stream) { + if (dsp_cork(i, i->play_stream, !((*(int*) argp) & PCM_ENABLE_OUTPUT)) < 0) + *_errno = EIO; + if (dsp_trigger(i) < 0) + *_errno = EIO; + } + + i->rec_precork = !((*(int*) argp) & PCM_ENABLE_INPUT); + + if (i->rec_stream) { + if (dsp_cork(i, i->rec_stream, !((*(int*) argp) & PCM_ENABLE_INPUT)) < 0) + *_errno = EIO; + } + + break; + case SNDCTL_DSP_SYNC: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n"); -- cgit From 8e738ede9b2050a29400d4218b96b68863290857 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 15:30:34 +0000 Subject: fix a few obvious copynpaste errors when handling volumes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1444 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index fddd8fb4..0ac48254 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1511,14 +1511,14 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_WRITE_IGAIN: { pa_cvolume v, *pv; - if (request == SOUND_MIXER_READ_PCM) + if (request == SOUND_MIXER_WRITE_PCM) debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); else debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_IGAIN\n"); pa_threaded_mainloop_lock(i->mainloop); - if (request == SOUND_MIXER_READ_PCM) { + if (request == SOUND_MIXER_WRITE_PCM) { v = i->sink_volume; pv = &i->sink_volume; } else { @@ -1532,7 +1532,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno if (!pa_cvolume_equal(pv, &v)) { pa_operation *o; - if (request == SOUND_MIXER_READ_PCM) + if (request == SOUND_MIXER_WRITE_PCM) o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, context_success_cb, i); else o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, context_success_cb, i); -- cgit From 1e12e0ee8dfdda1632b9c082aba6fc1956813a5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 May 2007 17:24:48 +0000 Subject: Kill spaces on EOL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1465 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 0ac48254..955bd2f1 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2230,7 +2230,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n"); /* this is a no-op */ break; - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); -- cgit From 13a4c5290a5a80025c72e9f40c28c2e6437c82e8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 4 Jun 2007 09:52:03 +0000 Subject: Add support for the poorly documented SNDCTL_DSP_GETTRIGGER. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1466 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 955bd2f1..b9c26f09 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2061,6 +2061,17 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *_errno = EIO; break; + case SNDCTL_DSP_GETTRIGGER: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETTRIGGER\n"); + + *(int*) argp = 0; + if (!i->play_precork) + *(int*) argp |= PCM_ENABLE_OUTPUT; + if (!i->rec_precork) + *(int*) argp |= PCM_ENABLE_INPUT; + + break; + case SNDCTL_DSP_SETTRIGGER: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp); -- cgit From 14cbbe1096ef10091a0073009a3c65eb13d2da27 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 11 Jun 2007 11:22:30 +0000 Subject: Support stat() and friends as some programs (audacity) likes to check if the device node is there first. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1467 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b9c26f09..9a2bad44 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -116,9 +116,17 @@ static int (*_ioctl)(int, int, void*) = NULL; static int (*_close)(int) = NULL; static int (*_open)(const char *, int, mode_t) = NULL; static FILE* (*_fopen)(const char *path, const char *mode) = NULL; +static int (*_stat)(const char *, struct stat *) = NULL; +#ifdef _STAT_VER +static int (*___xstat)(int, const char *, struct stat *) = NULL; +#endif #ifdef HAVE_OPEN64 static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; +static int (*_stat64)(const char *, struct stat64 *) = NULL; +#ifdef _STAT_VER +static int (*___xstat64)(int, const char *, struct stat64 *) = NULL; +#endif #endif static int (*_fclose)(FILE *f) = NULL; static int (*_access)(const char *, int) = NULL; @@ -170,6 +178,38 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define LOAD_STAT_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_stat) \ + _stat = (int (*)(const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "stat"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_STAT64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_stat64) \ + _stat64 = (int (*)(const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "stat64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_XSTAT_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!___xstat) \ + ___xstat = (int (*)(int, const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "__xstat"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_XSTAT64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!___xstat64) \ + ___xstat64 = (int (*)(int, const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "__xstat64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + #define LOAD_FOPEN_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ @@ -2348,7 +2388,107 @@ int access(const char *pathname, int mode) { return 0; } +int stat(const char *pathname, struct stat *buf) { #ifdef HAVE_OPEN64 + struct stat64 parent; +#else + struct stat parent; +#endif + int ret; + + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname); + LOAD_STAT_FUNC(); + return _stat(pathname, buf); + } + + debug(DEBUG_LEVEL_NORMAL, __FILE__": stat(%s)\n", pathname); + +#ifdef _STAT_VER +#ifdef HAVE_OPEN64 + ret = __xstat64(_STAT_VER, "/dev", &parent); +#else + ret = __xstat(_STAT_VER, "/dev", &parent); +#endif +#else +#ifdef HAVE_OPEN64 + ret = stat64("/dev", &parent); +#else + ret = stat("/dev", &parent); +#endif +#endif + + if (ret) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": unable to stat \"/dev\"\n"); + return -1; + } + + buf->st_dev = parent.st_dev; + buf->st_ino = 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */ + buf->st_mode = S_IFCHR | S_IRUSR | S_IWUSR; + buf->st_nlink = 1; + buf->st_uid = getuid(); + buf->st_gid = getgid(); + buf->st_rdev = 0x0E03; /* FIXME: Linux specific */ + buf->st_size = 0; + buf->st_atime = 1181557705; + buf->st_mtime = 1181557705; + buf->st_ctime = 1181557705; + buf->st_blksize = 1; + buf->st_blocks = 0; + + return 0; +} + +#ifdef HAVE_OPEN64 + +int stat64(const char *pathname, struct stat64 *buf) { + struct stat oldbuf; + int ret; + + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_STAT64_FUNC(); + return _stat64(pathname, buf); + } + + ret = stat(pathname, &oldbuf); + if (ret) + return ret; + + buf->st_dev = oldbuf.st_dev; + buf->st_ino = oldbuf.st_ino; + buf->st_mode = oldbuf.st_mode; + buf->st_nlink = oldbuf.st_nlink; + buf->st_uid = oldbuf.st_uid; + buf->st_gid = oldbuf.st_gid; + buf->st_rdev = oldbuf.st_rdev; + buf->st_size = oldbuf.st_size; + buf->st_atime = oldbuf.st_atime; + buf->st_mtime = oldbuf.st_mtime; + buf->st_ctime = oldbuf.st_ctime; + buf->st_blksize = oldbuf.st_blksize; + buf->st_blocks = oldbuf.st_blocks; + + return 0; +} int open64(const char *filename, int flags, ...) { va_list args; @@ -2374,6 +2514,62 @@ int open64(const char *filename, int flags, ...) { #endif +#ifdef _STAT_VER + +int __xstat(int ver, const char *pathname, struct stat *buf) { + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_XSTAT_FUNC(); + return ___xstat(ver, pathname, buf); + } + + if (ver != _STAT_VER) { + errno = EINVAL; + return -1; + } + + return stat(pathname, buf); +} + +#ifdef HAVE_OPEN64 + +int __xstat64(int ver, const char *pathname, struct stat64 *buf) { + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_XSTAT64_FUNC(); + return ___xstat64(ver, pathname, buf); + } + + if (ver != _STAT_VER) { + errno = EINVAL; + return -1; + } + + return stat64(pathname, buf); +} + +#endif + +#endif + FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; -- cgit From 0694d2ae3549ed4e7cb8fca3558fb90ed844fca1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 13 Jun 2007 07:21:57 +0000 Subject: Make sure mixer ioctls work on /dev/dsp aswell. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1473 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 9a2bad44..95fc9ed3 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2279,11 +2279,12 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_SETDUPLEX: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n"); - /* this is a no-op */ - break; + /* this is a no-op */ + break; default: - debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); + /* Mixer ioctls are valid on /dev/dsp aswell */ + return mixer_ioctl(i, request, argp, _errno); inval: *_errno = EINVAL; -- cgit From a67c21f093202f142438689d3f7cfbdf4ea82eea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:13:50 +0000 Subject: merge 'lennart' branch back into trunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 123 +++++++++++++++++-- src/utils/padsp.c | 71 ++++++----- src/utils/paplay.c | 2 +- src/utils/pasuspender.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 473 insertions(+), 39 deletions(-) create mode 100644 src/utils/pasuspender.c (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index b95cbfee..c963987f 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -48,8 +48,10 @@ static pa_context *context = NULL; static pa_mainloop_api *mainloop_api = NULL; -static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL; +static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL; static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX; +static uint32_t module_index; +static int suspend; static SNDFILE *sndfile = NULL; static pa_stream *sample_stream = NULL; @@ -69,7 +71,11 @@ static enum { REMOVE_SAMPLE, LIST, MOVE_SINK_INPUT, - MOVE_SOURCE_OUTPUT + MOVE_SOURCE_OUTPUT, + LOAD_MODULE, + UNLOAD_MODULE, + SUSPEND_SINK, + SUSPEND_SOURCE, } action = NONE; static void quit(int ret) { @@ -354,7 +360,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info i->sink, pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), - pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), (double) i->buffer_usec, (double) i->sink_usec, i->resample_method ? i->resample_method : "n/a"); @@ -492,6 +498,18 @@ static void simple_callback(pa_context *c, int success, void *userdata) { complete_action(); } +static void index_callback(pa_context *c, uint32_t idx, void *userdata) { + if (idx == PA_INVALID_INDEX) { + fprintf(stderr, "Failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + printf("%u\n", idx); + + complete_action(); +} + static void stream_state_callback(pa_stream *s, void *userdata) { assert(s); @@ -594,6 +612,28 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL)); break; + case LOAD_MODULE: + pa_operation_unref(pa_context_load_module(c, module_name, module_args, index_callback, NULL)); + break; + + case UNLOAD_MODULE: + pa_operation_unref(pa_context_unload_module(c, module_index, simple_callback, NULL)); + break; + + case SUSPEND_SINK: + if (sink_name) + pa_operation_unref(pa_context_suspend_sink_by_name(c, sink_name, suspend, simple_callback, NULL)); + else + pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL)); + break; + + case SUSPEND_SOURCE: + if (source_name) + pa_operation_unref(pa_context_suspend_source_by_name(c, source_name, suspend, simple_callback, NULL)); + else + pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL)); + break; + default: assert(0); } @@ -624,12 +664,16 @@ static void help(const char *argv0) { "%s [options] play-sample NAME [SINK]\n" "%s [options] move-sink-input ID SINK\n" "%s [options] move-source-output ID SOURCE\n" - "%s [options] remove-sample NAME\n\n" + "%s [options] remove-sample NAME\n" + "%s [options] load-module NAME [ARGS ...]\n" + "%s [options] unload-module ID\n" + "%s [options] suspend-sink [SINK] 1|0\n" + "%s [options] suspend-source [SOURCE] 1|0\n\n" " -h, --help Show this help\n" " --version Show version\n\n" " -s, --server=SERVER The name of the server to connect to\n" " -n, --client-name=NAME How to call this client on the server\n", - argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); + argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); } enum { ARG_VERSION = 256 }; @@ -728,7 +772,7 @@ int main(int argc, char *argv[]) { sample_length = sfinfo.frames*pa_frame_size(&sample_spec); } else if (!strcmp(argv[optind], "play-sample")) { action = PLAY_SAMPLE; - if (optind+1 >= argc) { + if (argc != optind+2 && argc != optind+3) { fprintf(stderr, "You have to specify a sample name to play\n"); goto quit; } @@ -740,7 +784,7 @@ int main(int argc, char *argv[]) { } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; - if (optind+1 >= argc) { + if (argc != optind+2) { fprintf(stderr, "You have to specify a sample name to remove\n"); goto quit; } @@ -748,7 +792,7 @@ int main(int argc, char *argv[]) { sample_name = pa_xstrdup(argv[optind+1]); } else if (!strcmp(argv[optind], "move-sink-input")) { action = MOVE_SINK_INPUT; - if (optind+2 >= argc) { + if (argc != optind+3) { fprintf(stderr, "You have to specify a sink input index and a sink\n"); goto quit; } @@ -757,13 +801,72 @@ int main(int argc, char *argv[]) { sink_name = pa_xstrdup(argv[optind+2]); } else if (!strcmp(argv[optind], "move-source-output")) { action = MOVE_SOURCE_OUTPUT; - if (optind+2 >= argc) { + if (argc != optind+3) { fprintf(stderr, "You have to specify a source output index and a source\n"); goto quit; } source_output_idx = atoi(argv[optind+1]); source_name = pa_xstrdup(argv[optind+2]); + } else if (!strcmp(argv[optind], "load-module")) { + int i; + size_t n = 0; + char *p; + + action = LOAD_MODULE; + + if (argc <= optind+1) { + fprintf(stderr, "You have to specify a module name and arguments.\n"); + goto quit; + } + + module_name = argv[optind+1]; + + for (i = optind+2; i < argc; i++) + n += strlen(argv[i])+1; + + if (n > 0) { + p = module_args = pa_xnew0(char, n); + + for (i = optind+2; i < argc; i++) + p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]); + } + + } else if (!strcmp(argv[optind], "unload-module")) { + action = UNLOAD_MODULE; + + if (argc != optind+2) { + fprintf(stderr, "You have to specify a module index\n"); + goto quit; + } + + module_index = atoi(argv[optind+1]); + + } else if (!strcmp(argv[optind], "suspend-sink")) { + action = SUSPEND_SINK; + + if (argc > optind+3 || optind+1 >= argc) { + fprintf(stderr, "You may not specify more than one sink. You have to specify at least one boolean value.\n"); + goto quit; + } + + suspend = !!atoi(argv[argc-1]); + + if (argc > optind+2) + sink_name = pa_xstrdup(argv[optind+1]); + + } else if (!strcmp(argv[optind], "suspend-source")) { + action = SUSPEND_SOURCE; + + if (argc > optind+3 || optind+1 >= argc) { + fprintf(stderr, "You may not specify more than one source. You have to specify at least one boolean value.\n"); + goto quit; + } + + suspend = !!atoi(argv[argc-1]); + + if (argc > optind+2) + source_name = pa_xstrdup(argv[optind+1]); } } @@ -819,6 +922,8 @@ quit: pa_xfree(sample_name); pa_xfree(sink_name); pa_xfree(source_name); + pa_xfree(module_args); + pa_xfree(client_name); return ret; } diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 95fc9ed3..b48af93c 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -61,6 +61,10 @@ # define SIOCINQ FIONREAD #endif +/* make sure gcc doesn't redefine open and friends as macros */ +#undef open +#undef open64 + typedef enum { FD_INFO_MIXER, FD_INFO_STREAM, @@ -259,9 +263,9 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -#define DEBUG_LEVEL_ALWAYS 0 -#define DEBUG_LEVEL_NORMAL 1 -#define DEBUG_LEVEL_VERBOSE 2 +#define DEBUG_LEVEL_ALWAYS 0 +#define DEBUG_LEVEL_NORMAL 1 +#define DEBUG_LEVEL_VERBOSE 2 static void debug(int level, const char *format, ...) { va_list ap; @@ -421,7 +425,7 @@ static void fd_info_unref(fd_info *i) { pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); r = --i->ref; - debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); if (r <= 0) @@ -1395,7 +1399,7 @@ static int sndstat_open(int flags, int *_errno) { if (flags != O_RDONLY #ifdef O_LARGEFILE - && flags != (O_RDONLY|O_LARGEFILE) + && flags != (O_RDONLY|O_LARGEFILE) #endif ) { *_errno = EACCES; @@ -1436,34 +1440,23 @@ fail: return -1; } -int open(const char *filename, int flags, ...) { - va_list args; - mode_t mode = 0; +static int real_open(const char *filename, int flags, mode_t mode) { int r, _errno = 0; debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); - va_start(args, flags); - if (flags & O_CREAT) { - if (sizeof(mode_t) < sizeof(int)) - mode = va_arg(args, int); - else - mode = va_arg(args, mode_t); - } - va_end(args); - if (!function_enter()) { LOAD_OPEN_FUNC(); return _open(filename, flags, mode); } - if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) { + if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) r = dsp_open(flags, &_errno); - } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) { + else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) r = mixer_open(flags, &_errno); - } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) { + else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) r = sndstat_open(flags, &_errno); - } else { + else { function_exit(); LOAD_OPEN_FUNC(); return _open(filename, flags, mode); @@ -1477,6 +1470,22 @@ int open(const char *filename, int flags, ...) { return r; } +int open(const char *filename, int flags, ...) { + va_list args; + mode_t mode = 0; + + if (flags & O_CREAT) { + va_start(args, flags); + if (sizeof(mode_t) < sizeof(int)) + mode = va_arg(args, int); + else + mode = va_arg(args, mode_t); + va_end(args); + } + + return real_open(filename, flags, mode); +} + static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; @@ -2023,9 +2032,9 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER #ifdef DSP_CAP_MULTI - | DSP_CAP_MULTI + | DSP_CAP_MULTI #endif - ; + ; break; case SNDCTL_DSP_GETODELAY: { @@ -2497,10 +2506,14 @@ int open64(const char *filename, int flags, ...) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); - va_start(args, flags); - if (flags & O_CREAT) - mode = va_arg(args, mode_t); - va_end(args); + if (flags & O_CREAT) { + va_start(args, flags); + if (sizeof(mode_t) < sizeof(int)) + mode = va_arg(args, int); + else + mode = va_arg(args, mode_t); + va_end(args); + } if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && @@ -2510,7 +2523,7 @@ int open64(const char *filename, int flags, ...) { return _open64(filename, flags, mode); } - return open(filename, flags, mode); + return real_open(filename, flags, mode); } #endif @@ -2602,7 +2615,7 @@ FILE* fopen(const char *filename, const char *mode) { if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+')) m = O_RDWR; - if ((fd = open(filename, m)) < 0) + if ((fd = real_open(filename, m, 0)) < 0) return NULL; if (!(f = fdopen(fd, mode))) { diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 2c779a7a..e7076d2d 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -123,7 +123,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { else pa_xfree(data); - if (bytes < length) { + if (bytes < (sf_count_t) length) { sf_close(sndfile); sndfile = NULL; pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c new file mode 100644 index 00000000..ae59086b --- /dev/null +++ b/src/utils/pasuspender.c @@ -0,0 +1,316 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio 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 Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __linux__ +#include +#endif + +#include +#include + +#if PA_API_VERSION < 10 +#error Invalid PulseAudio API version +#endif + +#define BUFSIZE 1024 + +static pa_context *context = NULL; +static pa_mainloop_api *mainloop_api = NULL; +static char **child_argv = NULL; +static int child_argc = 0; +static pid_t child_pid = (pid_t) -1; +static int child_ret = 0; +static int dead = 1; + +static void quit(int ret) { + pa_assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + + +static void context_drain_complete(pa_context *c, void *userdata) { + pa_context_disconnect(c); +} + +static void drain(void) { + pa_operation *o; + + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else + pa_operation_unref(o); +} + +static void start_child(void) { + + if ((child_pid = fork()) < 0) { + + fprintf(stderr, "fork(): %s\n", strerror(errno)); + quit(1); + + } else if (child_pid == 0) { + /* Child */ + +#ifdef __linux__ + prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); +#endif + + if (execvp(child_argv[0], child_argv) < 0) + fprintf(stderr, "execvp(): %s\n", strerror(errno)); + + _exit(1); + + } else { + + /* parent */ + dead = 0; + } +} + +static void suspend_complete(pa_context *c, int success, void *userdata) { + static int n = 0; + + n++; + + if (!success) { + fprintf(stderr, "Failure to suspend: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (n >= 2) + start_child(); +} + +static void resume_complete(pa_context *c, int success, void *userdata) { + static int n = 0; + + n++; + + if (!success) { + fprintf(stderr, "Failure to resume: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (n >= 2) + drain(); /* drain and quit */ +} + +static void context_state_callback(pa_context *c, void *userdata) { + pa_assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + if (pa_context_is_local(c)) { + pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); + pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); + } else + start_child(); + + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + + pa_context_unref(context); + context = NULL; + + if (child_pid == (pid_t) -1) + /* not started yet, then we do it now */ + start_child(); + else if (dead) + /* already started, and dead, so let's quit */ + quit(1); + + break; + } +} + +static void sigint_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); +} + +static void sigchld_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { + int status = 0; + pid_t p; + + p = waitpid(-1, &status, WNOHANG); + + if (p != child_pid) + return; + + dead = 1; + + if (WIFEXITED(status)) + child_ret = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) { + fprintf(stderr, "WARNING: Child process terminated by signal %u\n", WTERMSIG(status)); + child_ret = 1; + } + + if (context) { + if (pa_context_is_local(context)) { + /* A context is around, so let's resume */ + pa_operation_unref(pa_context_suspend_sink_by_index(context, PA_INVALID_INDEX, 0, resume_complete, NULL)); + pa_operation_unref(pa_context_suspend_source_by_index(context, PA_INVALID_INDEX, 0, resume_complete, NULL)); + } else + drain(); + } else + /* Hmm, no context here, so let's terminate right away */ + quit(0); +} + +static void help(const char *argv0) { + + printf("%s [options] ... \n\n" + " -h, --help Show this help\n" + " --version Show version\n" + " -s, --server=SERVER The name of the server to connect to\n\n", + argv0); +} + +enum { + ARG_VERSION = 256 +}; + +int main(int argc, char *argv[]) { + pa_mainloop* m = NULL; + int c, ret = 1; + char *server = NULL, *bn; + + static const struct option long_options[] = { + {"server", 1, NULL, 's'}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + while ((c = getopt_long(argc, argv, "s:h", long_options, NULL)) != -1) { + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("pasuspender "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 's': + pa_xfree(server); + server = pa_xstrdup(optarg); + break; + + default: + goto quit; + } + } + + child_argv = argv + optind; + child_argc = argc - optind; + + if (child_argc <= 0) { + help(bn); + ret = 0; + goto quit; + } + + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + pa_assert_se(mainloop_api = pa_mainloop_get_api(m)); + pa_assert_se(pa_signal_init(mainloop_api) == 0); + pa_signal_new(SIGINT, sigint_callback, NULL); + pa_signal_new(SIGCHLD, sigchld_callback, NULL); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + if (!(context = pa_context_new(mainloop_api, bn))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + pa_context_set_state_callback(context, context_state_callback, NULL); + pa_context_connect(context, server, PA_CONTEXT_NOAUTOSPAWN, NULL); + + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (context) + pa_context_unref(context); + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + pa_xfree(server); + + if (!dead) + kill(child_pid, SIGTERM); + + return ret == 0 ? child_ret : ret; +} -- cgit From 0eb011bda093438044338946d575ff7845e6aa3c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 5 Nov 2007 23:56:30 +0000 Subject: minor cleanups of --help texts git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2025 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- src/utils/paplay.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index c963987f..eddbebc9 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -662,9 +662,9 @@ static void help(const char *argv0) { "%s [options] exit\n" "%s [options] upload-sample FILENAME [NAME]\n" "%s [options] play-sample NAME [SINK]\n" + "%s [options] remove-sample NAME\n" "%s [options] move-sink-input ID SINK\n" "%s [options] move-source-output ID SOURCE\n" - "%s [options] remove-sample NAME\n" "%s [options] load-module NAME [ARGS ...]\n" "%s [options] unload-module ID\n" "%s [options] suspend-sink [SINK] 1|0\n" diff --git a/src/utils/paplay.c b/src/utils/paplay.c index e7076d2d..fddbb18c 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -203,9 +203,9 @@ static void help(const char *argv0) { printf("%s [options] [FILE]\n\n" " -h, --help Show this help\n" " --version Show version\n\n" - " -v, --verbose Enable verbose operations\n\n" + " -v, --verbose Enable verbose operation\n\n" " -s, --server=SERVER The name of the server to connect to\n" - " -d, --device=DEVICE The name of the sink/source to connect to\n" + " -d, --device=DEVICE The name of the sink to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" -- cgit From 1ef4bafc9a6ea0661e5b1a26948f8ab5b5b8afa2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Nov 2007 13:52:07 +0000 Subject: warn if the sound server is not local git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2028 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pasuspender.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c index ae59086b..05d96a68 100644 --- a/src/utils/pasuspender.c +++ b/src/utils/pasuspender.c @@ -149,8 +149,10 @@ static void context_state_callback(pa_context *c, void *userdata) { if (pa_context_is_local(c)) { pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); - } else + } else { + fprintf(stderr, "WARNING: Sound server is not local, not suspending.\n"); start_child(); + } break; -- cgit From 14b974a6d870432554afc20710ad9f93f4833e88 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Nov 2007 22:42:33 +0000 Subject: parse the pasuspend argument like any other boolean in PulseAudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2031 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index eddbebc9..5425b131 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -850,7 +850,7 @@ int main(int argc, char *argv[]) { goto quit; } - suspend = !!atoi(argv[argc-1]); + suspend = pa_parse_boolean(argv[argc-1]); if (argc > optind+2) sink_name = pa_xstrdup(argv[optind+1]); @@ -863,7 +863,7 @@ int main(int argc, char *argv[]) { goto quit; } - suspend = !!atoi(argv[argc-1]); + suspend = pa_parse_boolean(argv[argc-1]); if (argc > optind+2) source_name = pa_xstrdup(argv[optind+1]); -- cgit From ecf349dc6cdb6737f3854c5c4678d336dcf10938 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 01:30:46 +0000 Subject: add missing #include git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2035 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 5425b131..4519b13b 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -38,6 +38,7 @@ #include #include +#include #if PA_API_VERSION < 10 #error Invalid PulseAudio API version -- cgit From 7b321eda3af7dbdd689152da9b3ca315d383b5b4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 19:21:15 +0000 Subject: increase the pacmd timeout a bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2051 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 16e5822f..9583385b 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -80,7 +80,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { goto fail; } - pa_msleep(50); + pa_msleep(300); } if (i >= 5) { -- cgit From 14a9b80afbb0bddc216462b72156f14e032e1b5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:30:40 +0000 Subject: - Check process name when dealing with PID files - Add new PA_STREAM_FIX_CHANNELS, FIX_RATE, FIX_FORMAT, DONT_MOVE, VARIABLE_RATES to pa_sream_flags_t adn implement it - Expose those flags in pacat - Add notifications about device suspend/resume to the protocol and expose them in libpulse - Allow changing of buffer_attr during playback - allow disabling for remixing globally - hookup polkit support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2067 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/utils/pacmd.c | 4 +-- 2 files changed, 92 insertions(+), 13 deletions(-) (limited to 'src/utils') diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 96b6adb7..68e308d8 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -40,7 +40,7 @@ #define TIME_EVENT_USEC 50000 -#if PA_API_VERSION < 9 +#if PA_API_VERSION < 10 #error Invalid PulseAudio API version #endif @@ -69,6 +69,8 @@ static pa_sample_spec sample_spec = { static pa_channel_map channel_map; static int channel_map_set = 0; +static pa_stream_flags_t flags = 0; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -105,7 +107,8 @@ static void do_stream_write(size_t length) { /* This is called whenever new data may be written to the stream */ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { - assert(s && length); + assert(s); + assert(length > 0); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); @@ -119,7 +122,8 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { /* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { const void *data; - assert(s && length); + assert(s); + assert(length > 0); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); @@ -130,7 +134,8 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { return; } - assert(data && length); + assert(data); + assert(length > 0); if (buffer) { fprintf(stderr, "Buffer overrun, dropping incoming data\n"); @@ -159,6 +164,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; + char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; fprintf(stderr, "Stream successfully created.\n"); @@ -172,9 +178,16 @@ static void stream_state_callback(pa_stream *s, void *userdata) { assert(mode == RECORD); fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } - } + fprintf(stderr, "Using sample spec '%s', channel map '%s'.\n", + pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), + pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); + + fprintf(stderr, "Connected to device %s (%u, %ssuspended).\n", + pa_stream_get_device_name(s), + pa_stream_get_device_index(s), + pa_stream_is_suspended(s) ? "" : "not "); } break; @@ -186,6 +199,24 @@ static void stream_state_callback(pa_stream *s, void *userdata) { } } +static void stream_suspended_callback(pa_stream *s, void *userdata) { + assert(s); + + if (verbose) { + if (pa_stream_is_suspended(s)) + fprintf(stderr, "Stream device suspended.\n"); + else + fprintf(stderr, "Stream device resumed.\n"); + } +} + +static void stream_moved_callback(pa_stream *s, void *userdata) { + assert(s); + + if (verbose) + fprintf(stderr, "Stream moved to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); +} + /* This is called whenever the context status changes */ static void context_state_callback(pa_context *c, void *userdata) { assert(c); @@ -199,7 +230,8 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_READY: { int r; - assert(c && !stream); + assert(c); + assert(!stream); if (verbose) fprintf(stderr, "Connection established.\n"); @@ -212,16 +244,18 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); pa_stream_set_read_callback(stream, stream_read_callback, NULL); + pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL); + pa_stream_set_moved_callback(stream, stream_moved_callback, NULL); if (mode == PLAYBACK) { pa_cvolume cv; - if ((r = pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { + if ((r = pa_stream_connect_playback(stream, device, NULL, flags, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } } else { - if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) { + if ((r = pa_stream_connect_record(stream, device, NULL, flags)) < 0) { fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } @@ -280,7 +314,10 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && e && stdio_event == e); + + assert(a == mainloop_api); + assert(e); + assert(stdio_event == e); if (buffer) { mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); @@ -330,7 +367,10 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even /* Some data may be written to STDOUT */ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { ssize_t r; - assert(a == mainloop_api && e && stdio_event == e); + + assert(a == mainloop_api); + assert(e); + assert(stdio_event == e); if (!buffer) { mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); @@ -429,7 +469,16 @@ static void help(const char *argv0) { " float32be, ulaw, alaw (defaults to s16ne)\n" " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" " (defaults to 2)\n" - " --channel-map=CHANNELMAP Channel map to use instead of the default\n", + " --channel-map=CHANNELMAP Channel map to use instead of the default\n" + " --fix-format Take the sample format from the sink the stream is\n" + " being connected to.\n" + " --fix-rate Take the sampling rate from the sink the stream is\n" + " being connected to.\n" + " --fix-channels Take the number of channels and the channel map\n" + " from the sink the stream is being connected to.\n" + " --no-remix Don't upmix or downmix channels.\n" + " --no-remap Map channels by index instead of name.\n" + , argv0); } @@ -441,6 +490,11 @@ enum { ARG_SAMPLEFORMAT, ARG_CHANNELS, ARG_CHANNELMAP, + ARG_FIX_FORMAT, + ARG_FIX_RATE, + ARG_FIX_CHANNELS, + ARG_NO_REMAP, + ARG_NO_REMIX }; int main(int argc, char *argv[]) { @@ -464,6 +518,11 @@ int main(int argc, char *argv[]) { {"format", 1, NULL, ARG_SAMPLEFORMAT}, {"channels", 1, NULL, ARG_CHANNELS}, {"channel-map", 1, NULL, ARG_CHANNELMAP}, + {"fix-format", 0, NULL, ARG_FIX_FORMAT}, + {"fix-rate", 0, NULL, ARG_FIX_RATE}, + {"fix-channels",0, NULL, ARG_FIX_CHANNELS}, + {"no-remap", 0, NULL, ARG_NO_REMAP}, + {"no-remix", 0, NULL, ARG_NO_REMIX}, {NULL, 0, NULL, 0} }; @@ -549,6 +608,26 @@ int main(int argc, char *argv[]) { channel_map_set = 1; break; + case ARG_FIX_CHANNELS: + flags |= PA_STREAM_FIX_CHANNELS; + break; + + case ARG_FIX_RATE: + flags |= PA_STREAM_FIX_RATE; + break; + + case ARG_FIX_FORMAT: + flags |= PA_STREAM_FIX_FORMAT; + break; + + case ARG_NO_REMIX: + flags |= PA_STREAM_NO_REMIX_CHANNELS; + break; + + case ARG_NO_REMAP: + flags |= PA_STREAM_NO_REMAP_CHANNELS; + break; + default: goto quit; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 9583385b..daa6a96e 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -50,7 +50,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { size_t ibuf_index, ibuf_length, obuf_index, obuf_length; fd_set ifds, ofds; - if (pa_pid_file_check_running(&pid) < 0) { + if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) { pa_log("no PulseAudio daemon running"); goto fail; } @@ -75,7 +75,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r >= 0) break; - if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { + if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) { pa_log("failed to kill PulseAudio daemon."); goto fail; } -- cgit From 75e1ebdf772b07949636662d0b9e52189d8a78e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 15 Feb 2008 11:50:48 +0000 Subject: Improve compatibility with applications which like to pass invalid strings to the libc functions we overwrite, by handing directly to the original function. Patch by Colin Guthrie and Gustavo De Nardin, Closes #227 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2106 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 132 +++++++++++++++++++++++++----------------------------- 1 file changed, 60 insertions(+), 72 deletions(-) (limited to 'src/utils') diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b48af93c..cb57ff8a 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1443,18 +1443,18 @@ fail: static int real_open(const char *filename, int flags, mode_t mode) { int r, _errno = 0; - debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename?filename:"NULL"); if (!function_enter()) { LOAD_OPEN_FUNC(); return _open(filename, flags, mode); } - if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) + if (filename && dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) r = dsp_open(flags, &_errno); - else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) + else if (filename && mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) r = mixer_open(flags, &_errno); - else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) + else if (filename && sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) r = sndstat_open(flags, &_errno); else { function_exit(); @@ -2371,18 +2371,13 @@ int close(int fd) { int access(const char *pathname, int mode) { - if (!pathname) { - /* Firefox needs this. See #27 */ - errno = EFAULT; - return -1; - } - - debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname?pathname:"NULL"); - if (strcmp(pathname, "/dev/dsp") != 0 && - strcmp(pathname, "/dev/adsp") != 0 && - strcmp(pathname, "/dev/sndstat") != 0 && - strcmp(pathname, "/dev/mixer") != 0) { + if (!pathname || + ( strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0 )) { LOAD_ACCESS_FUNC(); return _access(pathname, mode); } @@ -2406,16 +2401,13 @@ int stat(const char *pathname, struct stat *buf) { #endif int ret; - if (!pathname || !buf) { - errno = EFAULT; - return -1; - } - - if (strcmp(pathname, "/dev/dsp") != 0 && - strcmp(pathname, "/dev/adsp") != 0 && - strcmp(pathname, "/dev/sndstat") != 0 && - strcmp(pathname, "/dev/mixer") != 0) { - debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname); + if (!pathname || + !buf || + ( strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0 )) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname?pathname:"NULL"); LOAD_STAT_FUNC(); return _stat(pathname, buf); } @@ -2464,17 +2456,14 @@ int stat64(const char *pathname, struct stat64 *buf) { struct stat oldbuf; int ret; - if (!pathname || !buf) { - errno = EFAULT; - return -1; - } - - debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname?pathname:"NULL"); - if (strcmp(pathname, "/dev/dsp") != 0 && - strcmp(pathname, "/dev/adsp") != 0 && - strcmp(pathname, "/dev/sndstat") != 0 && - strcmp(pathname, "/dev/mixer") != 0) { + if (!pathname || + !buf || + ( strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0 )) { LOAD_STAT64_FUNC(); return _stat64(pathname, buf); } @@ -2504,7 +2493,7 @@ int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; - debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename?filename:"NULL"); if (flags & O_CREAT) { va_start(args, flags); @@ -2515,10 +2504,11 @@ int open64(const char *filename, int flags, ...) { va_end(args); } - if (strcmp(filename, "/dev/dsp") != 0 && - strcmp(filename, "/dev/adsp") != 0 && - strcmp(filename, "/dev/sndstat") != 0 && - strcmp(filename, "/dev/mixer") != 0) { + if (!filename || + ( strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && + strcmp(filename, "/dev/mixer") != 0 )) { LOAD_OPEN64_FUNC(); return _open64(filename, flags, mode); } @@ -2531,17 +2521,14 @@ int open64(const char *filename, int flags, ...) { #ifdef _STAT_VER int __xstat(int ver, const char *pathname, struct stat *buf) { - if (!pathname || !buf) { - errno = EFAULT; - return -1; - } - - debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname); - - if (strcmp(pathname, "/dev/dsp") != 0 && - strcmp(pathname, "/dev/adsp") != 0 && - strcmp(pathname, "/dev/sndstat") != 0 && - strcmp(pathname, "/dev/mixer") != 0) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname?pathname:"NULL"); + + if (!pathname || + !buf || + ( strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0 )) { LOAD_XSTAT_FUNC(); return ___xstat(ver, pathname, buf); } @@ -2557,17 +2544,14 @@ int __xstat(int ver, const char *pathname, struct stat *buf) { #ifdef HAVE_OPEN64 int __xstat64(int ver, const char *pathname, struct stat64 *buf) { - if (!pathname || !buf) { - errno = EFAULT; - return -1; - } - - debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname); - - if (strcmp(pathname, "/dev/dsp") != 0 && - strcmp(pathname, "/dev/adsp") != 0 && - strcmp(pathname, "/dev/sndstat") != 0 && - strcmp(pathname, "/dev/mixer") != 0) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname?pathname:"NULL"); + + if (!pathname || + !buf || + ( strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0 )) { LOAD_XSTAT64_FUNC(); return ___xstat64(ver, pathname, buf); } @@ -2589,12 +2573,14 @@ FILE* fopen(const char *filename, const char *mode) { int fd; mode_t m; - debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename?filename:"NULL"); - if (strcmp(filename, "/dev/dsp") != 0 && - strcmp(filename, "/dev/adsp") != 0 && - strcmp(filename, "/dev/sndstat") != 0 && - strcmp(filename, "/dev/mixer") != 0) { + if (!filename || + !mode || + ( strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && + strcmp(filename, "/dev/mixer") != 0 )) { LOAD_FOPEN_FUNC(); return _fopen(filename, mode); } @@ -2630,12 +2616,14 @@ FILE* fopen(const char *filename, const char *mode) { FILE *fopen64(const char *filename, const char *mode) { - debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename?filename:"NULL"); - if (strcmp(filename, "/dev/dsp") != 0 && - strcmp(filename, "/dev/adsp") != 0 && - strcmp(filename, "/dev/sndstat") != 0 && - strcmp(filename, "/dev/mixer") != 0) { + if (!filename || + !mode || + ( strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && + strcmp(filename, "/dev/mixer") != 0 )) { LOAD_FOPEN64_FUNC(); return _fopen64(filename, mode); } -- cgit From 6ad7621b61d40dba9b877379ef5f15f73a2ed268 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Mar 2008 13:32:33 +0000 Subject: work around solaris printf %s and NULL string brain damage git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2117 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/utils') diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 4519b13b..4381d9d2 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -281,7 +281,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int "Auto unload: %s\n", i->index, i->name, - i->argument, + i->argument ? i->argument : "", i->n_used != PA_INVALID_INDEX ? t : "n/a", i->auto_unload ? "yes" : "no"); } -- cgit