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/modules/module-solaris.c | 488 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 488 insertions(+) create mode 100644 src/modules/module-solaris.c (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c new file mode 100644 index 00000000..e0745fc0 --- /dev/null +++ b/src/modules/module-solaris.c @@ -0,0 +1,488 @@ +/* $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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-solaris-symdef.h" + +PA_MODULE_AUTHOR("Pierre Ossman") +PA_MODULE_DESCRIPTION("Solaris Sink/Source") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= buffer_size=") + +struct userdata { + pa_sink *sink; + pa_source *source; + pa_iochannel *io; + pa_core *core; + pa_signal_event *sig; + + pa_memchunk memchunk, silence; + + uint32_t sample_size; + uint32_t buffer_size; + unsigned int written_bytes, read_bytes; + + int fd; + pa_module *module; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "source_name", + "device", + "record", + "playback", + "buffer_size", + "format", + "rate", + "channels", + NULL +}; + +#define DEFAULT_SINK_NAME "solaris_output" +#define DEFAULT_SOURCE_NAME "solaris_input" +#define DEFAULT_DEVICE "/dev/audio" + +#define CHUNK_SIZE 2048 + +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_size(u->source->outputs) : 0)); +} + +static void do_write(struct userdata *u) { + audio_info_t info; + int err; + pa_memchunk *memchunk; + size_t len; + ssize_t r; + + assert(u); + + if (!u->sink || !pa_iochannel_is_writable(u->io)) + return; + + update_usage(u); + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + /* + * Since we cannot modify the size of the output buffer we fake it + * by not filling it more than u->buffer_size. + */ + len = u->buffer_size; + len -= u->written_bytes - (info.play.samples * u->sample_size); + + /* + * Do not fill more than half the buffer in one chunk since we only + * get notifications upon completion of entire chunks. + */ + if (len > (u->buffer_size / 2)) + len = u->buffer_size / 2; + + if (len < u->sample_size) + return; + + memchunk = &u->memchunk; + + if (!memchunk->length) + if (pa_sink_render(u->sink, len, memchunk) < 0) + memchunk = &u->silence; + + assert(memchunk->memblock); + assert(memchunk->memblock->data); + assert(memchunk->length); + + if (memchunk->length < len) + len = memchunk->length; + + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + return; + } + + if (memchunk == &u->silence) + assert(r % u->sample_size == 0); + else { + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + } + } + + u->written_bytes += r; + + /* + * Write 0 bytes which will generate a SIGPOLL when "played". + */ + if (write(u->fd, NULL, 0) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + return; + } +} + +static void do_read(struct userdata *u) { + pa_memchunk memchunk; + int err, l; + ssize_t r; + assert(u); + + if (!u->source || !pa_iochannel_is_readable(u->io)) + return; + + update_usage(u); + + err = ioctl(u->fd, I_NREAD, &l); + assert(err >= 0); + + memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat); + assert(memchunk.memblock); + if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { + pa_memblock_unref(memchunk.memblock); + if (errno != EAGAIN) + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + return; + } + + assert(r <= (ssize_t) memchunk.memblock->length); + memchunk.length = memchunk.memblock->length = r; + memchunk.index = 0; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); + + u->read_bytes += r; +} + +static void io_callback(pa_iochannel *io, void*userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); + do_read(u); +} + +void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); +} + +static pa_usec_t sink_get_latency_cb(pa_sink *s) { + pa_usec_t r = 0; + audio_info_t info; + int err; + struct userdata *u = s->userdata; + assert(s && u && u->sink); + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec); + r -= pa_bytes_to_usec(info.play.samples * u->sample_size, &s->sample_spec); + + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + + return r; +} + +static pa_usec_t source_get_latency_cb(pa_source *s) { + pa_usec_t r = 0; + struct userdata *u = s->userdata; + audio_info_t info; + int err; + assert(s && u && u->source); + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + r += pa_bytes_to_usec(info.record.samples * u->sample_size, &s->sample_spec); + r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec); + + return r; +} + +static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { + audio_info_t info; + + AUDIO_INITINFO(&info); + + if (mode != O_RDONLY) { + info.play.sample_rate = ss->rate; + info.play.channels = ss->channels; + switch (ss->format) { + case PA_SAMPLE_U8: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + case PA_SAMPLE_ALAW: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ALAW; + break; + case PA_SAMPLE_ULAW: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ULAW; + break; + case PA_SAMPLE_S16NE: + info.play.precision = 16; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + default: + return -1; + } + } + + if (mode != O_WRONLY) { + info.record.sample_rate = ss->rate; + info.record.channels = ss->channels; + switch (ss->format) { + case PA_SAMPLE_U8: + info.record.precision = 8; + info.record.encoding = AUDIO_ENCODING_LINEAR; + break; + case PA_SAMPLE_ALAW: + info.record.precision = 8; + info.record.encoding = AUDIO_ENCODING_ALAW; + break; + case PA_SAMPLE_ULAW: + info.record.precision = 8; + info.record.encoding = AUDIO_ENCODING_ULAW; + break; + case PA_SAMPLE_S16NE: + info.record.precision = 16; + info.record.encoding = AUDIO_ENCODING_LINEAR; + break; + default: + return -1; + } + } + + if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format.\n"); + else + pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +static int pa_solaris_set_buffer(int fd, int buffer_size) { + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.record.buffer_size = buffer_size; + + if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size.\n"); + else + pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u = NULL; + const char *p; + int fd = -1; + int buffer_size; + int mode; + int record = 1, playback = 1; + pa_sample_spec ss; + pa_modargs *ma = NULL; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments.\n"); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { + pa_log(__FILE__": record= and playback= expect numeric argument.\n"); + goto fail; + } + + if (!playback && !record) { + pa_log(__FILE__": neither playback nor record enabled for device.\n"); + goto fail; + } + + mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + + buffer_size = 16384; + if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { + pa_log(__FILE__": failed to parse buffer size argument\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": failed to parse sample specification\n"); + goto fail; + } + + if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) + goto fail; + + pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + + if (pa_solaris_auto_format(fd, mode, &ss) < 0) + goto fail; + + if ((mode != O_WRONLY) && (buffer_size >= 1)) + if (pa_solaris_set_buffer(fd, buffer_size) < 0) + goto fail; + + u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + + if (mode != O_WRONLY) { + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); + assert(u->source); + u->source->userdata = u; + u->source->get_latency = source_get_latency_cb; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + } else + u->source = NULL; + + if (mode != O_RDONLY) { + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); + assert(u->sink); + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + } else + u->sink = NULL; + + assert(u->source || u->sink); + + u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); + assert(u->io); + pa_iochannel_set_callback(u->io, io_callback, u); + u->fd = fd; + + u->memchunk.memblock = NULL; + u->memchunk.length = 0; + u->sample_size = pa_frame_size(&ss); + u->buffer_size = buffer_size; + + u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); + assert(u->silence.memblock); + pa_silence_memblock(u->silence.memblock, &ss); + u->silence.index = 0; + + u->written_bytes = 0; + u->read_bytes = 0; + + u->module = m; + m->userdata = u; + + u->sig = pa_signal_new(SIGPOLL, sig_callback, u); + assert(u->sig); + ioctl(u->fd, I_SETSIG, S_MSG); + + pa_modargs_free(ma); + + return 0; + +fail: + if (fd >= 0) + close(fd); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + ioctl(u->fd, I_SETSIG, 0); + pa_signal_free(u->sig); + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + if (u->silence.memblock) + pa_memblock_unref(u->silence.memblock); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } + + pa_iochannel_free(u->io); + pa_xfree(u); +} -- cgit From 502d3f551bb8a168b6686b6d0c833a5f6e40c98c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 16:13:10 +0000 Subject: Hardware volume support for Solaris. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@524 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index e0745fc0..7356cb7b 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -258,6 +258,40 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { return r; } +static int sink_get_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + int err; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, + info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + + return 0; +} + +static int sink_set_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.play.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.play.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume.\n"); + else + pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { audio_info_t info; @@ -411,6 +445,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; + u->sink->get_hw_volume = sink_get_hw_volume_cb; + u->sink->set_hw_volume = sink_set_hw_volume_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); -- 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/modules/module-solaris.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 7356cb7b..1de21aed 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -150,7 +150,7 @@ static void do_write(struct userdata *u) { len = memchunk->length; if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } @@ -172,7 +172,7 @@ static void do_write(struct userdata *u) { * Write 0 bytes which will generate a SIGPOLL when "played". */ if (write(u->fd, NULL, 0) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } } @@ -196,7 +196,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); return; } @@ -283,9 +283,9 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume.\n"); + pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); return -1; } @@ -349,9 +349,9 @@ static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format.\n"); + pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format."); else - pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); return -1; } @@ -367,9 +367,9 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size.\n"); + pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size."); else - pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); return -1; } @@ -388,17 +388,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric argument.\n"); + pa_log(__FILE__": record= and playback= expect numeric argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device."); goto fail; } @@ -406,20 +406,20 @@ int pa__init(pa_core *c, pa_module*m) { buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { - pa_log(__FILE__": failed to parse buffer size argument\n"); + pa_log(__FILE__": failed to parse buffer size argument"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; - pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_solaris_auto_format(fd, mode, &ss) < 0) goto fail; -- cgit From 12e35c546c97e3b36d8c0656c571b6b3f2c7d46a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:07:49 +0000 Subject: Make sure hardware volume gets a correct initial value. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@579 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 1de21aed..76f50935 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -482,6 +482,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); + /* Read mixer settings */ + if (u->sink) + sink_get_hw_volume(u->sink); + return 0; fail: -- cgit From f8aca21379e6caf09ebcd1129ee90195c7e24714 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:08:06 +0000 Subject: Wrong function name. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@580 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 76f50935..eb909e4f 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -484,7 +484,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Read mixer settings */ if (u->sink) - sink_get_hw_volume(u->sink); + sink_get_hw_volume_cb(u->sink); return 0; -- cgit From 79e800904500fd3adcb14a19d7a8ec0436f9d5bf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:44:50 +0000 Subject: Hardware source volume support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@584 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index eb909e4f..a74a70c2 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -292,6 +292,40 @@ static int sink_set_hw_volume_cb(pa_sink *s) { return 0; } +static int source_get_hw_volume_cb(pa_source *s) { + struct userdata *u = s->userdata; + audio_info_t info; + int err; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, + info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + + return 0; +} + +static int source_set_hw_volume_cb(pa_source *s) { + struct userdata *u = s->userdata; + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.record.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.record.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); + else + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + return -1; + } + + return 0; +} + static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { audio_info_t info; @@ -436,6 +470,8 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; + u->source->get_hw_volume = source_get_hw_volume_cb; + u->source->set_hw_volume = source_set_hw_volume_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); } else @@ -483,6 +519,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); /* Read mixer settings */ + if (u->source) + sink_get_hw_volume_cb(u->source); if (u->sink) sink_get_hw_volume_cb(u->sink); -- cgit From 9366ab9dc9acd687dc41e492d07413d36ba2f3ed Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 10:17:41 +0000 Subject: Hardware sink mute support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@593 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a74a70c2..9015cfd2 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -292,6 +292,35 @@ static int sink_set_hw_volume_cb(pa_sink *s) { return 0; } +static int sink_get_hw_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + int err; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + s->hw_muted = !!info.output_muted; + + return 0; +} + +static int sink_set_hw_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.output_muted = !!s->hw_muted; + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + return -1; + } + + return 0; +} + static int source_get_hw_volume_cb(pa_source *s) { struct userdata *u = s->userdata; audio_info_t info; @@ -483,6 +512,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = sink_get_latency_cb; u->sink->get_hw_volume = sink_get_hw_volume_cb; u->sink->set_hw_volume = sink_set_hw_volume_cb; + u->sink->get_hw_mute = sink_get_hw_mute_cb; + u->sink->set_hw_mute = sink_set_hw_mute_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); @@ -521,8 +552,10 @@ int pa__init(pa_core *c, pa_module*m) { /* Read mixer settings */ if (u->source) sink_get_hw_volume_cb(u->source); - if (u->sink) + if (u->sink) { sink_get_hw_volume_cb(u->sink); + sink_get_hw_mute_cb(u->sink); + } return 0; -- cgit From c205ea6ebe1b373fe6b84ee189528809e9fefc90 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 10:18:24 +0000 Subject: Make local function static. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@594 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 9015cfd2..55ef1cd1 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -217,7 +217,7 @@ static void io_callback(pa_iochannel *io, void*userdata) { do_read(u); } -void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { +static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; assert(u); do_write(u); -- cgit From a1f5573313e888d39dbe4015bdd993ad9eccb92f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 10:18:53 +0000 Subject: Call correct function. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@595 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 55ef1cd1..94fa6d8c 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -551,7 +551,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Read mixer settings */ if (u->source) - sink_get_hw_volume_cb(u->source); + source_get_hw_volume_cb(u->source); if (u->sink) { sink_get_hw_volume_cb(u->sink); sink_get_hw_mute_cb(u->sink); -- cgit From e8b3819ac87e96e6ad3442ca29eaecb1c57efcc4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:18:18 +0000 Subject: Catch volume update events. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@612 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 94fa6d8c..12d6719e 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -219,8 +219,20 @@ static void io_callback(pa_iochannel *io, void*userdata) { static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; - assert(u); + pa_cvolume old_vol; + + assert(u && u->sink && u->sink->get_hw_volume); + do_write(u); + + memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); + if (u->sink->get_hw_volume(u->sink) < 0) + return; + if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { + pa_subscription_post(u->sink->core, + PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, + u->sink->index); + } } static pa_usec_t sink_get_latency_cb(pa_sink *s) { -- cgit From 4756d186ab461322470a57b0f1e8ca5fdd4eb6fb Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:20:25 +0000 Subject: We have both sink and source in this module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@613 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 12d6719e..9f93f9d8 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -221,17 +221,32 @@ static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void struct userdata *u = userdata; pa_cvolume old_vol; - assert(u && u->sink && u->sink->get_hw_volume); + assert(u); do_write(u); - memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); - if (u->sink->get_hw_volume(u->sink) < 0) - return; - if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { - pa_subscription_post(u->sink->core, - PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, - u->sink->index); + if (u->sink) { + assert(u->sink->get_hw_volume); + memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); + if (u->sink->get_hw_volume(u->sink) < 0) + return; + if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { + pa_subscription_post(u->sink->core, + PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, + u->sink->index); + } + } + + if (u->source) { + assert(u->source->get_hw_volume); + memcpy(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)); + if (u->source->get_hw_volume(u->source) < 0) + return; + if (memcmp(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)) != 0) { + pa_subscription_post(u->source->core, + PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, + u->source->index); + } } } -- cgit From 989fa585b267fbd7b7e40f4dd6e4caf34708910c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 14:30:42 +0000 Subject: Sun's documentation about SIGPOLL on EOF:s is wrong, so use a timer based solution instead. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@761 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 48 ++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 9f93f9d8..a2034f3e 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -64,6 +64,8 @@ struct userdata { pa_source *source; pa_iochannel *io; pa_core *core; + pa_time_event *timer; + pa_usec_t poll_timeout; pa_signal_event *sig; pa_memchunk memchunk, silence; @@ -111,7 +113,8 @@ static void do_write(struct userdata *u) { assert(u); - if (!u->sink || !pa_iochannel_is_writable(u->io)) + /* We cannot check pa_iochannel_is_writable() because of our buffer hack */ + if (!u->sink) return; update_usage(u); @@ -126,12 +129,8 @@ static void do_write(struct userdata *u) { len = u->buffer_size; len -= u->written_bytes - (info.play.samples * u->sample_size); - /* - * Do not fill more than half the buffer in one chunk since we only - * get notifications upon completion of entire chunks. - */ - if (len > (u->buffer_size / 2)) - len = u->buffer_size / 2; + if (len == u->buffer_size) + pa_log_debug(__FILE__": Solaris buffer underflow!"); if (len < u->sample_size) return; @@ -167,14 +166,6 @@ static void do_write(struct userdata *u) { } u->written_bytes += r; - - /* - * Write 0 bytes which will generate a SIGPOLL when "played". - */ - if (write(u->fd, NULL, 0) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); - return; - } } static void do_read(struct userdata *u) { @@ -217,14 +208,26 @@ static void io_callback(pa_iochannel *io, void*userdata) { do_read(u); } +static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval ntv; + + assert(u); + + do_write(u); + + pa_gettimeofday(&ntv); + pa_timeval_add(&ntv, u->poll_timeout); + + a->time_restart(e, &ntv); +} + static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; pa_cvolume old_vol; assert(u); - do_write(u); - if (u->sink) { assert(u->sink->get_hw_volume); memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); @@ -475,6 +478,7 @@ int pa__init(pa_core *c, pa_module*m) { int record = 1, playback = 1; pa_sample_spec ss; pa_modargs *ma = NULL; + struct timeval tv; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -570,6 +574,14 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; m->userdata = u; + u->poll_timeout = pa_bytes_to_usec(u->buffer_size / 10, &ss); + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, u->poll_timeout); + + u->timer = c->mainloop->time_new(c->mainloop, &tv, timer_cb, u); + assert(u->timer); + u->sig = pa_signal_new(SIGPOLL, sig_callback, u); assert(u->sig); ioctl(u->fd, I_SETSIG, S_MSG); @@ -603,6 +615,8 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; + if (u->timer) + c->mainloop->time_free(u->timer); ioctl(u->fd, I_SETSIG, 0); pa_signal_free(u->sig); -- cgit From e4b53b2badbd3679df6154e6d6687fcc2aa57885 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 15:37:52 +0000 Subject: Tweaks for the solaris module. The sound system requires complete frames to be written. Also, the sample counter can magically go backwards sometimes, causing havoc with our buffer handling. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@762 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a2034f3e..e1a03272 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -70,7 +70,7 @@ struct userdata { pa_memchunk memchunk, silence; - uint32_t sample_size; + uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; @@ -127,12 +127,18 @@ static void do_write(struct userdata *u) { * by not filling it more than u->buffer_size. */ len = u->buffer_size; - len -= u->written_bytes - (info.play.samples * u->sample_size); + len -= u->written_bytes - (info.play.samples * u->frame_size); + + /* The sample counter can sometimes go backwards :( */ + if (len > u->buffer_size) + len = 0; if (len == u->buffer_size) pa_log_debug(__FILE__": Solaris buffer underflow!"); - if (len < u->sample_size) + len -= len % u->frame_size; + + if (len == 0) return; memchunk = &u->memchunk; @@ -145,17 +151,20 @@ static void do_write(struct userdata *u) { assert(memchunk->memblock->data); assert(memchunk->length); - if (memchunk->length < len) + if (memchunk->length < len) { len = memchunk->length; - + len -= len % u->frame_size; + assert(len); + } + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } + + assert(r % u->frame_size == 0); - if (memchunk == &u->silence) - assert(r % u->sample_size == 0); - else { + if (memchunk != &u->silence) { u->memchunk.index += r; u->memchunk.length -= r; @@ -264,7 +273,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(err >= 0); r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec); - r -= pa_bytes_to_usec(info.play.samples * u->sample_size, &s->sample_spec); + r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &s->sample_spec); if (u->memchunk.memblock) r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); @@ -282,7 +291,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { err = ioctl(u->fd, AUDIO_GETINFO, &info); assert(err >= 0); - r += pa_bytes_to_usec(info.record.samples * u->sample_size, &s->sample_spec); + r += pa_bytes_to_usec(info.record.samples * u->frame_size, &s->sample_spec); r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec); return r; @@ -560,7 +569,7 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->sample_size = pa_frame_size(&ss); + u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); -- cgit From 99612dd88dfee3abd072c3138231549594381ee7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 27 Apr 2006 05:41:18 +0000 Subject: Channel map argument support for solaris. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@815 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index e1a03272..eaac9e6e 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -57,7 +57,16 @@ PA_MODULE_AUTHOR("Pierre Ossman") PA_MODULE_DESCRIPTION("Solaris Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= buffer_size=") +PA_MODULE_USAGE( + "sink_name= " + "source_name= " + "device= record= " + "playback= " + "format= " + "channels= " + "rate= " + "buffer_size= " + "channel_map=") struct userdata { pa_sink *sink; @@ -88,6 +97,7 @@ static const char* const valid_modargs[] = { "format", "rate", "channels", + "channel_map", NULL }; @@ -486,6 +496,7 @@ int pa__init(pa_core *c, pa_module*m) { int mode; int record = 1, playback = 1; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; struct timeval tv; assert(c && m); @@ -514,7 +525,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -535,7 +546,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (mode != O_WRONLY) { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; @@ -547,7 +558,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->get_hw_volume = sink_get_hw_volume_cb; -- cgit From 05c14685203b5ced74bfec0e6a3b3aa3f8721c51 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 06:31:18 +0000 Subject: Use default channel map for Solaris module. There doesn't seem to be a standard for > 2 channels, so we'll have to rely on the user. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@889 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index eaac9e6e..3e7c2fb4 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -525,7 +525,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } -- cgit From d9cc2cfcb97c1b0449bcbfb6ab0301a58d77bd55 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 16:34:18 +0000 Subject: Move xmalloc to the public side (libpolyp). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@908 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 3e7c2fb4..d82e3362 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -49,7 +50,6 @@ #include #include #include -#include #include #include "module-solaris-symdef.h" -- 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/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index d82e3362..77eb4e49 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -48,7 +48,7 @@ #include #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/modules/module-solaris.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 77eb4e49..8670bb35 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -168,7 +169,7 @@ static void do_write(struct userdata *u) { } if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); return; } @@ -206,7 +207,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); return; } @@ -334,7 +335,7 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -363,7 +364,7 @@ static int sink_set_hw_mute_cb(pa_sink *s) { info.output_muted = !!s->hw_muted; if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -397,7 +398,7 @@ static int source_set_hw_volume_cb(pa_source *s) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -463,7 +464,7 @@ static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -481,7 +482,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } -- 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/modules/module-solaris.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 8670bb35..12c4a3ff 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.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. ***/ @@ -40,18 +40,18 @@ #include #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include #include "module-solaris-symdef.h" -- cgit From b91dd2381bffeb0a4b5450ef4ce1f0031909f79a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:28:41 +0000 Subject: set is_hardware flag for a few hw plugins git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1092 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 12c4a3ff..02ef4bc4 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -555,6 +555,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source->set_hw_volume = source_set_hw_volume_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + u->source->is_hardware = 1; } else u->source = NULL; @@ -569,6 +570,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + u->sink->is_hardware = 1; } else u->sink = NULL; -- cgit From bfa6604b1ddc5e2c0f1aaa15330363724856359b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 23:58:55 +0000 Subject: don't set the sink/source descriptions manually, use the new functions pa_{sink,source}_set_description() instead git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1205 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 02ef4bc4..21a72b38 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -500,6 +500,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map map; pa_modargs *ma = NULL; struct timeval tv; + char *t; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -554,7 +555,8 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_volume = source_get_hw_volume_cb; u->source->set_hw_volume = source_set_hw_volume_cb; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); u->source->is_hardware = 1; } else u->source = NULL; @@ -569,7 +571,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_mute = sink_set_hw_mute_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); u->sink->is_hardware = 1; } else u->sink = NULL; -- cgit From dbe6bdd2bcd035b0b07d70811593be719c5cc7c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 17:06:05 +0000 Subject: make use of pa_sink_used_by()/pa_source_used_by() wherever applicable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1227 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 21a72b38..53c73af7 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -110,9 +110,8 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_size(u->source->outputs) : 0)); + (u->sink ? pa_sink_used_by(u->sink) : 0) + + (u->source ? pa_source_used_by(u->source) : 0)); } static void do_write(struct userdata *u) { -- 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/modules/module-solaris.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 53c73af7..e13254e9 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -144,7 +144,7 @@ static void do_write(struct userdata *u) { len = 0; if (len == u->buffer_size) - pa_log_debug(__FILE__": Solaris buffer underflow!"); + pa_log_debug("Solaris buffer underflow!"); len -= len % u->frame_size; @@ -168,7 +168,7 @@ static void do_write(struct userdata *u) { } if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { - pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); + pa_log("write() failed: %s", pa_cstrerror(errno)); return; } @@ -206,7 +206,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); + pa_log("read() failed: %s", pa_cstrerror(errno)); return; } @@ -332,9 +332,9 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); + pa_log("AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -363,7 +363,7 @@ static int sink_set_hw_mute_cb(pa_sink *s) { info.output_muted = !!s->hw_muted; if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -395,9 +395,9 @@ static int source_set_hw_volume_cb(pa_source *s) { if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); + pa_log("AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -461,9 +461,9 @@ static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format."); + pa_log("AUDIO_SETINFO: Unsupported sample format."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -479,9 +479,9 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size."); + pa_log("AUDIO_SETINFO: Unsupported buffer size."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -503,17 +503,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric argument."); + pa_log("record= and playback= expect numeric argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device."); + pa_log("neither playback nor record enabled for device."); goto fail; } @@ -521,20 +521,20 @@ int pa__init(pa_core *c, pa_module*m) { buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { - pa_log(__FILE__": failed to parse buffer size argument"); + pa_log("failed to parse buffer size argument"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + pa_log("failed to parse sample specification"); goto fail; } if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; - pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_solaris_auto_format(fd, mode, &ss) < 0) goto fail; -- cgit From 6e3d8af52078db439f9cacece690dfe96d353c42 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:21:41 +0000 Subject: Add header for pa_cstrerror(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1309 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index e13254e9..06de7d36 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "module-solaris-symdef.h" -- cgit From 1c320fe0b76995c50cfc4b54bfe90e859accdfc4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:23:47 +0000 Subject: Fix calls to pa_memblock_new(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1310 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 06de7d36..d198ee61 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -202,7 +202,7 @@ static void do_read(struct userdata *u) { err = ioctl(u->fd, I_NREAD, &l); assert(err >= 0); - memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat); + memchunk.memblock = pa_memblock_new(u->core->mempool, l); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); @@ -589,7 +589,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; - u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); + u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = CHUNK_SIZE); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; -- cgit From 7bc71103fb51609edfb0d7893344871a00f1221d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:25:45 +0000 Subject: Fix missing header for timeval helpers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1311 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index d198ee61..8eaf6758 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include -- cgit From b27ffbec8c815d0efa936063482b9bf0bc312103 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 16:25:47 +0000 Subject: Remove silence generation in solaris module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1326 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 55 +++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 29 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 8eaf6758..90cf010b 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -80,11 +80,12 @@ struct userdata { pa_usec_t poll_timeout; pa_signal_event *sig; - pa_memchunk memchunk, silence; + pa_memchunk memchunk; uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; + int sink_underflow; int fd; pa_module *module; @@ -119,7 +120,6 @@ static void update_usage(struct userdata *u) { static void do_write(struct userdata *u) { audio_info_t info; int err; - pa_memchunk *memchunk; size_t len; ssize_t r; @@ -145,7 +145,7 @@ static void do_write(struct userdata *u) { if (len > u->buffer_size) len = 0; - if (len == u->buffer_size) + if (!u->sink_underflow && (len == u->buffer_size)) pa_log_debug("Solaris buffer underflow!"); len -= len % u->frame_size; @@ -153,37 +153,39 @@ static void do_write(struct userdata *u) { if (len == 0) return; - memchunk = &u->memchunk; - - if (!memchunk->length) - if (pa_sink_render(u->sink, len, memchunk) < 0) - memchunk = &u->silence; + if (!u->memchunk.length) { + if (pa_sink_render(u->sink, len, &u->memchunk) < 0) { + u->sink_underflow = 1; + return; + } + } + + u->sink_underflow = 0; - assert(memchunk->memblock); - assert(memchunk->memblock->data); - assert(memchunk->length); + assert(u->memchunk.memblock); + assert(u->memchunk.memblock->data); + assert(u->memchunk.length); - if (memchunk->length < len) { - len = memchunk->length; + if (u->memchunk.length < len) { + len = u->memchunk.length; len -= len % u->frame_size; assert(len); } - if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { + if ((r = pa_iochannel_write(u->io, + (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, len)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); return; } assert(r % u->frame_size == 0); - if (memchunk != &u->silence) { - u->memchunk.index += r; - u->memchunk.length -= r; - - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - } + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; } u->written_bytes += r; @@ -590,14 +592,11 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; - u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = CHUNK_SIZE); - assert(u->silence.memblock); - pa_silence_memblock(u->silence.memblock, &ss); - u->silence.index = 0; - u->written_bytes = 0; u->read_bytes = 0; + u->sink_underflow = 1; + u->module = m; m->userdata = u; @@ -649,8 +648,6 @@ void pa__done(pa_core *c, pa_module*m) { if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - if (u->silence.memblock) - pa_memblock_unref(u->silence.memblock); if (u->sink) { pa_sink_disconnect(u->sink); -- cgit From 79c4a6842c7e67a9e39d951d8ac2beab98100ae4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 23 Aug 2006 07:57:43 +0000 Subject: Make the recording a bit more chunky so that we can fit in the pool and have efficient blocks. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1327 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 90cf010b..66968cb1 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -82,6 +82,8 @@ struct userdata { pa_memchunk memchunk; + unsigned int page_size; + uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; @@ -193,7 +195,8 @@ static void do_write(struct userdata *u) { static void do_read(struct userdata *u) { pa_memchunk memchunk; - int err, l; + int err; + size_t l; ssize_t r; assert(u); @@ -205,6 +208,11 @@ static void do_read(struct userdata *u) { err = ioctl(u->fd, I_NREAD, &l); assert(err >= 0); + /* This is to make sure it fits in the memory pool. Also, a page + should be the most efficient transfer size. */ + if (l > u->page_size) + l = u->page_size; + memchunk.memblock = pa_memblock_new(u->core->mempool, l); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { @@ -589,6 +597,10 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; + + /* We use this to get a reasonable chunk size */ + u->page_size = sysconf(_SC_PAGESIZE); + u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; -- 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/modules/module-solaris.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 66968cb1..1454d639 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.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 @@ -124,7 +124,7 @@ static void do_write(struct userdata *u) { int err; size_t len; ssize_t r; - + assert(u); /* We cannot check pa_iochannel_is_writable() because of our buffer hack */ @@ -163,7 +163,7 @@ static void do_write(struct userdata *u) { } u->sink_underflow = 0; - + assert(u->memchunk.memblock); assert(u->memchunk.memblock->data); assert(u->memchunk.length); @@ -181,10 +181,10 @@ static void do_write(struct userdata *u) { } assert(r % u->frame_size == 0); - + u->memchunk.index += r; u->memchunk.length -= r; - + if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; @@ -199,7 +199,7 @@ static void do_read(struct userdata *u) { size_t l; ssize_t r; assert(u); - + if (!u->source || !pa_iochannel_is_readable(u->io)) return; @@ -221,11 +221,11 @@ static void do_read(struct userdata *u) { pa_log("read() failed: %s", pa_cstrerror(errno)); return; } - + assert(r <= (ssize_t) memchunk.memblock->length); memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; - + pa_source_post(u->source, &memchunk); pa_memblock_unref(memchunk.memblock); @@ -256,7 +256,7 @@ static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval * static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; pa_cvolume old_vol; - + assert(u); if (u->sink) { @@ -518,7 +518,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse module arguments."); goto fail; } - + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { pa_log("record= and playback= expect numeric argument."); goto fail; @@ -531,7 +531,7 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - buffer_size = 16384; + buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { pa_log("failed to parse buffer size argument"); goto fail; @@ -542,7 +542,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse sample specification"); goto fail; } - + if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; @@ -642,7 +642,7 @@ fail: if (ma) pa_modargs_free(ma); - + return -1; } @@ -657,7 +657,7 @@ void pa__done(pa_core *c, pa_module*m) { c->mainloop->time_free(u->timer); ioctl(u->fd, I_SETSIG, 0); pa_signal_free(u->sig); - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); @@ -665,12 +665,12 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); } - + if (u->source) { pa_source_disconnect(u->source); pa_source_unref(u->source); } - + pa_iochannel_free(u->io); pa_xfree(u); } -- 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/modules/module-solaris.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 1454d639..a50f1ecf 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.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, -- 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/modules/module-solaris.c | 690 ++++++++++++++++++++++++------------------- 1 file changed, 389 insertions(+), 301 deletions(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a50f1ecf..a8a94712 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.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 @@ -57,6 +57,9 @@ #include #include #include +#include +#include +#include #include "module-solaris-symdef.h" @@ -75,12 +78,14 @@ PA_MODULE_USAGE( "channel_map=") struct userdata { + pa_core *core; pa_sink *sink; pa_source *source; - pa_iochannel *io; - pa_core *core; - pa_time_event *timer; - pa_usec_t poll_timeout; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_signal_event *sig; pa_memchunk memchunk; @@ -90,9 +95,9 @@ struct userdata { uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; - int sink_underflow; int fd; + pa_rtpoll_item *rtpoll_item; pa_module *module; }; @@ -114,309 +119,357 @@ static const char* const valid_modargs[] = { #define DEFAULT_SOURCE_NAME "solaris_input" #define DEFAULT_DEVICE "/dev/audio" -#define CHUNK_SIZE 2048 - -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_sink_used_by(u->sink) : 0) + - (u->source ? pa_source_used_by(u->source) : 0)); -} - -static void do_write(struct userdata *u) { - audio_info_t info; +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; int err; - size_t len; - ssize_t r; + audio_info_t info; - assert(u); + switch (code) { + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; - /* We cannot check pa_iochannel_is_writable() because of our buffer hack */ - if (!u->sink) - return; + if (u->fd >= 0) { - update_usage(u); + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + r += pa_bytes_to_usec(u->written_bytes, &PA_SINK(o)->sample_spec); + r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &PA_SINK(o)->sample_spec); - /* - * Since we cannot modify the size of the output buffer we fake it - * by not filling it more than u->buffer_size. - */ - len = u->buffer_size; - len -= u->written_bytes - (info.play.samples * u->frame_size); + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec); + } - /* The sample counter can sometimes go backwards :( */ - if (len > u->buffer_size) - len = 0; + *((pa_usec_t*) data) = r; - if (!u->sink_underflow && (len == u->buffer_size)) - pa_log_debug("Solaris buffer underflow!"); + return 0; + } - len -= len % u->frame_size; + case PA_SINK_MESSAGE_SET_VOLUME: + if (u->fd >= 0) { + AUDIO_INITINFO(&info); + + info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.play.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log("AUDIO_SETINFO: Unsupported volume."); + else + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); + } else { + return 0; + } + } + break; - if (len == 0) - return; + case PA_SINK_MESSAGE_GET_VOLUME: + if (u->fd >= 0) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); - if (!u->memchunk.length) { - if (pa_sink_render(u->sink, len, &u->memchunk) < 0) { - u->sink_underflow = 1; - return; - } - } + pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels, + info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); - u->sink_underflow = 0; + return 0; + } + break; - assert(u->memchunk.memblock); - assert(u->memchunk.memblock->data); - assert(u->memchunk.length); + case PA_SINK_MESSAGE_SET_MUTE: + if (u->fd >= 0) { + AUDIO_INITINFO(&info); - if (u->memchunk.length < len) { - len = u->memchunk.length; - len -= len % u->frame_size; - assert(len); - } + info.output_muted = !!PA_PTR_TO_UINT(data); - if ((r = pa_iochannel_write(u->io, - (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, len)) < 0) { - pa_log("write() failed: %s", pa_cstrerror(errno)); - return; - } + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); + else + return 0; + } + break; - assert(r % u->frame_size == 0); + case PA_SINK_MESSAGE_GET_MUTE: + if (u->fd >= 0) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - u->memchunk.index += r; - u->memchunk.length -= r; + *(int*)data = !!info.output_muted; - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; + return 0; + } + break; } - u->written_bytes += r; + return pa_sink_process_msg(o, code, data, offset, chunk); } -static void do_read(struct userdata *u) { - pa_memchunk memchunk; +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SOURCE(o)->userdata; int err; - size_t l; - ssize_t r; - assert(u); + audio_info_t info; - if (!u->source || !pa_iochannel_is_readable(u->io)) - return; + switch (code) { + case PA_SOURCE_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; - update_usage(u); + if (u->fd) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - err = ioctl(u->fd, I_NREAD, &l); - assert(err >= 0); + r += pa_bytes_to_usec(info.record.samples * u->frame_size, &PA_SOURCE(o)->sample_spec); + r -= pa_bytes_to_usec(u->read_bytes, &PA_SOURCE(o)->sample_spec); + } - /* This is to make sure it fits in the memory pool. Also, a page - should be the most efficient transfer size. */ - if (l > u->page_size) - l = u->page_size; + *((pa_usec_t*) data) = r; - memchunk.memblock = pa_memblock_new(u->core->mempool, l); - assert(memchunk.memblock); - if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { - pa_memblock_unref(memchunk.memblock); - if (errno != EAGAIN) - pa_log("read() failed: %s", pa_cstrerror(errno)); - return; - } + return 0; + } - assert(r <= (ssize_t) memchunk.memblock->length); - memchunk.length = memchunk.memblock->length = r; - memchunk.index = 0; + case PA_SOURCE_MESSAGE_SET_VOLUME: + if (u->fd >= 0) { + AUDIO_INITINFO(&info); + + info.record.gain = pa_cvolume_avg((pa_cvolume*) data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.record.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log("AUDIO_SETINFO: Unsupported volume."); + else + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); + } else { + return 0; + } + } + break; - pa_source_post(u->source, &memchunk); - pa_memblock_unref(memchunk.memblock); + case PA_SOURCE_MESSAGE_GET_VOLUME: + if (u->fd >= 0) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - u->read_bytes += r; -} + pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels, + info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); -static void io_callback(pa_iochannel *io, void*userdata) { - struct userdata *u = userdata; - assert(u); - do_write(u); - do_read(u); -} + return 0; + } + break; + } -static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { - struct userdata *u = userdata; - struct timeval ntv; + return pa_source_process_msg(o, code, data, offset, chunk); +} - assert(u); +static void clear_underflow(struct userdata *u) +{ + audio_info_t info; - do_write(u); + AUDIO_INITINFO(&info); - pa_gettimeofday(&ntv); - pa_timeval_add(&ntv, u->poll_timeout); + info.play.error = 0; - a->time_restart(e, &ntv); + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); } -static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { - struct userdata *u = userdata; - pa_cvolume old_vol; +static void clear_overflow(struct userdata *u) +{ + audio_info_t info; - assert(u); + AUDIO_INITINFO(&info); - if (u->sink) { - assert(u->sink->get_hw_volume); - memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); - if (u->sink->get_hw_volume(u->sink) < 0) - return; - if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { - pa_subscription_post(u->sink->core, - PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, - u->sink->index); - } - } + info.record.error = 0; - if (u->source) { - assert(u->source->get_hw_volume); - memcpy(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)); - if (u->source->get_hw_volume(u->source) < 0) - return; - if (memcmp(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)) != 0) { - pa_subscription_post(u->source->core, - PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, - u->source->index); - } - } + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); } -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - pa_usec_t r = 0; - audio_info_t info; - int err; - struct userdata *u = s->userdata; - assert(s && u && u->sink); +static void thread_func(void *userdata) { + struct userdata *u = userdata; + unsigned short revents = 0; + int ret; - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + pa_assert(u); - r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec); - r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &s->sample_spec); + pa_log_debug("Thread starting up"); - if (u->memchunk.memblock) - r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + if (u->core->high_priority) + pa_make_realtime(); - return r; -} + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); -static pa_usec_t source_get_latency_cb(pa_source *s) { - pa_usec_t r = 0; - struct userdata *u = s->userdata; - audio_info_t info; - int err; - assert(s && u && u->source); + for (;;) { + /* Render some data and write it to the dsp */ - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) { + audio_info_t info; + int err; + size_t len; - r += pa_bytes_to_usec(info.record.samples * u->frame_size, &s->sample_spec); - r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec); + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - return r; -} + /* + * Since we cannot modify the size of the output buffer we fake it + * by not filling it more than u->buffer_size. + */ + len = u->buffer_size; + len -= u->written_bytes - (info.play.samples * u->frame_size); -static int sink_get_hw_volume_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; - int err; + /* The sample counter can sometimes go backwards :( */ + if (len > u->buffer_size) + len = 0; - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + if (info.play.error) { + pa_log_debug("Solaris buffer underflow!"); + clear_underflow(u); + } - pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, - info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + len -= len % u->frame_size; - return 0; -} + while (len) { + void *p; + ssize_t r; -static int sink_set_hw_volume_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; + if (!u->memchunk.length) + pa_sink_render(u->sink, len, &u->memchunk); - AUDIO_INITINFO(&info); + pa_assert(u->memchunk.length); - info.play.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; - assert(info.play.gain <= AUDIO_MAX_GAIN); + p = pa_memblock_acquire(u->memchunk.memblock); + r = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, NULL); + pa_memblock_release(u->memchunk.memblock); - if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - if (errno == EINVAL) - pa_log("AUDIO_SETINFO: Unsupported volume."); - else - pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); - return -1; - } + if (r < 0) { + if (errno == EINTR) + continue; + else if (errno != EAGAIN) { + pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno)); + goto fail; + } + } else { + pa_assert(r % u->frame_size == 0); - return 0; -} + u->memchunk.index += r; + u->memchunk.length -= r; -static int sink_get_hw_mute_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; - int err; + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + } - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + len -= r; + u->written_bytes += r; + } + } + } - s->hw_muted = !!info.output_muted; + /* Try to read some data and pass it on to the source driver */ + + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN))) { + pa_memchunk memchunk; + int err; + size_t l; + void *p; + ssize_t r; + audio_info_t info; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); + + if (info.record.error) { + pa_log_debug("Solaris buffer overflow!"); + clear_overflow(u); + } + + err = ioctl(u->fd, I_NREAD, &l); + pa_assert(err >= 0); + + if (l > 0) { + /* This is to make sure it fits in the memory pool. Also, a page + should be the most efficient transfer size. */ + if (l > u->page_size) + l = u->page_size; + + memchunk.memblock = pa_memblock_new(u->core->mempool, l); + pa_assert(memchunk.memblock); + + p = pa_memblock_acquire(memchunk.memblock); + r = pa_read(u->fd, p, l, NULL); + pa_memblock_release(memchunk.memblock); + + if (r < 0) { + pa_memblock_unref(memchunk.memblock); + if (errno != EAGAIN) { + pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno)); + goto fail; + } + } else { + memchunk.index = 0; + memchunk.length = r; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); + + u->read_bytes += r; + + revents &= ~POLLIN; + } + } + } - return 0; -} + if (u->fd >= 0) { + struct pollfd *pollfd; -static int sink_set_hw_mute_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->events = + ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0); + } - AUDIO_INITINFO(&info); + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + goto fail; - info.output_muted = !!s->hw_muted; + if (ret == 0) + goto finish; - if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); - return -1; - } + if (u->fd >= 0) { + struct pollfd *pollfd; - return 0; -} + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); -static int source_get_hw_volume_cb(pa_source *s) { - struct userdata *u = s->userdata; - audio_info_t info; - int err; + if (pollfd->revents & ~(POLLOUT|POLLIN)) { + pa_log("DSP shutdown."); + goto fail; + } - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + revents = pollfd->revents; + } else + revents = 0; + } - pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, - info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); +fail: + /* We have to continue processing messages until we receive the + * SHUTDOWN message */ + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); + pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); - return 0; +finish: + pa_log_debug("Thread shutting down"); } -static int source_set_hw_volume_cb(pa_source *s) { - struct userdata *u = s->userdata; - audio_info_t info; - - AUDIO_INITINFO(&info); +static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { + struct userdata *u = userdata; - info.record.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; - assert(info.record.gain <= AUDIO_MAX_GAIN); + assert(u); - if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - if (errno == EINVAL) - pa_log("AUDIO_SETINFO: Unsupported volume."); - else - pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); - return -1; + if (u->sink) { + pa_sink_get_volume(u->sink); + pa_sink_get_mute(u->sink); } - return 0; + if (u->source) + pa_source_get_volume(u->source); } static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { @@ -490,6 +543,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { AUDIO_INITINFO(&info); + info.play.buffer_size = buffer_size; info.record.buffer_size = buffer_size; if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { @@ -503,7 +557,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { return 0; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module *m) { struct userdata *u = NULL; const char *p; int fd = -1; @@ -513,9 +567,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; - struct timeval tv; char *t; - assert(c && m); + struct pollfd *pollfd; + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); @@ -540,7 +595,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("failed to parse sample specification"); goto fail; @@ -554,55 +609,18 @@ int pa__init(pa_core *c, pa_module*m) { if (pa_solaris_auto_format(fd, mode, &ss) < 0) goto fail; - if ((mode != O_WRONLY) && (buffer_size >= 1)) - if (pa_solaris_set_buffer(fd, buffer_size) < 0) - goto fail; + if (pa_solaris_set_buffer(fd, buffer_size) < 0) + goto fail; u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; + u->core = m->core; - if (mode != O_WRONLY) { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); - assert(u->source); - u->source->userdata = u; - u->source->get_latency = source_get_latency_cb; - u->source->get_hw_volume = source_get_hw_volume_cb; - u->source->set_hw_volume = source_set_hw_volume_cb; - pa_source_set_owner(u->source, m); - pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); - pa_xfree(t); - u->source->is_hardware = 1; - } else - u->source = NULL; - - if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); - assert(u->sink); - u->sink->get_latency = sink_get_latency_cb; - u->sink->get_hw_volume = sink_get_hw_volume_cb; - u->sink->set_hw_volume = sink_set_hw_volume_cb; - u->sink->get_hw_mute = sink_get_hw_mute_cb; - u->sink->set_hw_mute = sink_set_hw_mute_cb; - u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); - pa_xfree(t); - u->sink->is_hardware = 1; - } else - u->sink = NULL; - - assert(u->source || u->sink); - - u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); - assert(u->io); - pa_iochannel_set_callback(u->io, io_callback, u); u->fd = fd; - u->memchunk.memblock = NULL; - u->memchunk.length = 0; + pa_memchunk_reset(&u->memchunk); /* We use this to get a reasonable chunk size */ - u->page_size = sysconf(_SC_PAGESIZE); + u->page_size = PA_PAGE_SIZE; u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; @@ -610,37 +628,91 @@ int pa__init(pa_core *c, pa_module*m) { u->written_bytes = 0; u->read_bytes = 0; - u->sink_underflow = 1; - u->module = m; m->userdata = u; - u->poll_timeout = pa_bytes_to_usec(u->buffer_size / 10, &ss); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); + + pa_rtpoll_set_timer_periodic(u->rtpoll, pa_bytes_to_usec(u->buffer_size / 10, &ss)); - pa_gettimeofday(&tv); - pa_timeval_add(&tv, u->poll_timeout); + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = fd; + pollfd->events = 0; + pollfd->revents = 0; - u->timer = c->mainloop->time_new(c->mainloop, &tv, timer_cb, u); - assert(u->timer); + if (mode != O_WRONLY) { + u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); + pa_assert(u->source); + + u->source->userdata = u; + u->source->parent.process_msg = source_process_msg; + + pa_source_set_module(u->source, m); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); + + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL; + u->source->refresh_volume = 1; + } else + u->source = NULL; + + if (mode != O_RDONLY) { + u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); + pa_assert(u->sink); + + u->sink->userdata = u; + u->sink->parent.process_msg = sink_process_msg; + + pa_sink_set_module(u->sink, m); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL; + u->sink->refresh_volume = 1; + u->sink->refresh_mute = 1; + } else + u->sink = NULL; + + pa_assert(u->source || u->sink); u->sig = pa_signal_new(SIGPOLL, sig_callback, u); - assert(u->sig); + pa_assert(u->sig); ioctl(u->fd, I_SETSIG, S_MSG); - pa_modargs_free(ma); + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } /* Read mixer settings */ if (u->source) - source_get_hw_volume_cb(u->source); + pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL); if (u->sink) { - sink_get_hw_volume_cb(u->sink); - sink_get_hw_mute_cb(u->sink); + pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL); + pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_MUTE, &u->sink->muted, 0, NULL); } + if (u->sink) + pa_sink_put(u->sink); + if (u->source) + pa_source_put(u->source); + + pa_modargs_free(ma); + return 0; fail: - if (fd >= 0) + if (u) + pa__done(m); + else if (fd >= 0) close(fd); if (ma) @@ -649,31 +721,47 @@ fail: return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module *m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - if (u->timer) - c->mainloop->time_free(u->timer); ioctl(u->fd, I_SETSIG, 0); pa_signal_free(u->sig); - if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); + if (u->sink) + pa_sink_unlink(u->sink); - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); + if (u->source) + pa_source_unlink(u->source); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); } - if (u->source) { - pa_source_disconnect(u->source); + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->source) pa_source_unref(u->source); - } - pa_iochannel_free(u->io); + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->fd >= 0) + close(u->fd); + pa_xfree(u); } -- cgit From 1dae2e644f1e7c9810befb95315ec22fec7c100c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:32:53 +0000 Subject: we don't want to include assert.h anymore git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1986 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/modules/module-solaris.c') diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a8a94712..4a5c88e4 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include -- cgit