#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
+
+
+Verbose Error Messages
+======================
+
+Since version 1.0.8, assert() for some non-fatal errors are removed
+and error messages are no longer shown to stderr as default. Instead,
+the error messages appear only when the environment variable
+LIBASOUND_DEBUG is set. When LIBASOUND_DEBUG=assert is set, the
+default error message handler calls assert() to catch with a
+debugger.
+
+This feature is disabled when --with-debug=no is passed to configure,
+i.e. no strict checking is done in alsa-lib.
int snd_send_fd(int sock, void *data, size_t len, int fd);
int snd_receive_fd(int sock, void *data, size_t len, int *fd);
+/*
+ * error messages
+ */
+#ifndef NDEBUG
+#define CHECK_SANITY(x) x
+extern snd_lib_error_handler_t snd_err_msg;
+#define SNDMSG(args...) snd_err_msg(__FILE__, __LINE__, __FUNCTION__, 0, ##args)
+#define SYSMSG(args...) snd_err_msg(__FILE__, __LINE__, __FUNCTION__, errno, ##args)
+#else
+#define CHECK_SANITY(x) 0 /* not evaluated */
+#define SNDMSG(args...) /* nop */
+#define SYSMSG(args...) /* nop */
+#endif
+
+/*
+ */
#define HAVE_GNU_LD
#define HAVE_ELF
#define HAVE_ASM_PREVIOUS_DIRECTIVE
int snd_lib_error_set_handler(snd_lib_error_handler_t handler)
{
snd_lib_error = handler == NULL ? snd_lib_error_default : handler;
+#ifndef NDEBUG
+ if (snd_lib_error != snd_lib_error_default)
+ snd_err_msg = snd_lib_error;
+#endif
return 0;
}
{
return SND_LIB_VERSION_STR;
}
+
+#ifndef NDEBUG
+/*
+ * internal error handling
+ */
+static void snd_err_msg_default(const char *file, int line, const char *function, int err, const char *fmt, ...)
+{
+ va_list arg;
+ const char *verbose;
+
+ verbose = getenv("LIBASOUND_DEBUG");
+ if (! verbose || ! *verbose)
+ return;
+ va_start(arg, fmt);
+ fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function);
+ vfprintf(stderr, fmt, arg);
+ if (err)
+ fprintf(stderr, ": %s", snd_strerror(err));
+ putc('\n', stderr);
+ va_end(arg);
+ if (! strcmp(verbose, "assert"))
+ assert(0);
+}
+
+snd_lib_error_handler_t snd_err_msg = snd_err_msg_default;
+
+#endif
int snd_pcm_hw_free(snd_pcm_t *pcm)
{
int err;
- assert(pcm->setup);
+ if (! pcm->setup)
+ return 0;
if (pcm->mmap_channels) {
err = snd_pcm_munmap(pcm);
if (err < 0)
int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
{
int err;
- assert(pcm->setup); /* the hw_params must be set at first!!! */
+ /* the hw_params must be set at first!!! */
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
if (! params->avail_min || ! params->xfer_align)
return -EINVAL;
if (params->start_threshold <= pcm->buffer_size &&
params->start_threshold > (pcm->buffer_size / params->avail_min) * params->avail_min) {
- SNDERR("snd_pcm_sw_params: params->avail_min problem for start_threshold");
+ SNDMSG("params->avail_min problem for start_threshold");
return -EINVAL;
}
if (params->start_threshold <= pcm->buffer_size &&
params->start_threshold > (pcm->buffer_size / params->xfer_align) * params->xfer_align) {
- SNDERR("snd_pcm_sw_params: params->xfer_align problem for start_threshold");
+ SNDMSG("params->xfer_align problem for start_threshold");
return -EINVAL;
}
err = pcm->ops->sw_params(pcm->op_arg, params);
int snd_pcm_hwsync(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->hwsync(pcm->fast_op_arg);
}
int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->delay(pcm->fast_op_arg, delayp);
}
int snd_pcm_resume(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->resume(pcm->fast_op_arg);
}
int snd_pcm_prepare(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->prepare(pcm->fast_op_arg);
}
int snd_pcm_reset(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->reset(pcm->fast_op_arg);
}
int snd_pcm_start(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->start(pcm->fast_op_arg);
}
int snd_pcm_drop(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->drop(pcm->fast_op_arg);
}
int snd_pcm_drain(snd_pcm_t *pcm)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->drain(pcm->fast_op_arg);
}
int snd_pcm_pause(snd_pcm_t *pcm, int enable)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return pcm->fast_ops->pause(pcm->fast_op_arg, enable);
}
snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
assert(pcm);
- assert(pcm->setup);
- assert(frames > 0);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (frames == 0)
+ return 0;
return pcm->fast_ops->rewind(pcm->fast_op_arg, frames);
}
#endif
{
assert(pcm);
- assert(pcm->setup);
- assert(frames > 0);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (frames == 0)
+ return 0;
return pcm->fast_ops->forward(pcm->fast_op_arg, frames);
}
use_default_symbol_version(__snd_pcm_forward, snd_pcm_forward, ALSA_0.9.0rc8);
{
assert(pcm);
assert(size == 0 || buffer);
- assert(pcm->setup);
- assert(pcm->access == SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED) {
+ SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
+ return -EINVAL;
+ }
return _snd_pcm_writei(pcm, buffer, size);
}
{
assert(pcm);
assert(size == 0 || bufs);
- assert(pcm->setup);
- assert(pcm->access == SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
+ SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
+ return -EINVAL;
+ }
return _snd_pcm_writen(pcm, bufs, size);
}
{
assert(pcm);
assert(size == 0 || buffer);
- assert(pcm->setup);
- assert(pcm->access == SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED) {
+ SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
+ return -EINVAL;
+ }
return _snd_pcm_readi(pcm, buffer, size);
}
{
assert(pcm);
assert(size == 0 || bufs);
- assert(pcm->setup);
- assert(pcm->access == SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
+ SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
+ return -EINVAL;
+ }
return _snd_pcm_readn(pcm, bufs, size);
}
if (fd1 < 0 || fd2 < 0)
return -ENOSYS;
if (ioctl(fd1, SNDRV_PCM_IOCTL_LINK, fd2) < 0) {
- SYSERR("SNDRV_PCM_IOCTL_LINK failed");
+ SYSMSG("SNDRV_PCM_IOCTL_LINK failed");
return -errno;
}
return 0;
int fd;
fd = _snd_pcm_link_descriptor(pcm);
if (ioctl(fd, SNDRV_PCM_IOCTL_UNLINK) < 0) {
- SYSERR("SNDRV_PCM_IOCTL_UNLINK failed");
+ SYSMSG("SNDRV_PCM_IOCTL_UNLINK failed");
return -errno;
}
return 0;
if (err < 0)
return err;
}
- assert(pcm->poll_fd >= 0);
+ if (! pcm->poll_fd < 0) {
+ SNDMSG("poll_fd < 0");
+ return -EIO;
+ }
if (space >= 1 && pfds) {
pfds->fd = pcm->poll_fd;
pfds->events = pcm->poll_events | POLLERR | POLLNVAL;
*/
const char *snd_pcm_stream_name(snd_pcm_stream_t stream)
{
- assert(stream <= SND_PCM_STREAM_LAST);
+ if (stream > SND_PCM_STREAM_LAST)
+ return NULL;
return snd_pcm_stream_names[stream];
}
*/
const char *snd_pcm_start_mode_name(snd_pcm_start_t mode)
{
- assert(mode <= SND_PCM_START_LAST);
+ if (mode > SND_PCM_START_LAST)
+ return NULL;
return snd_pcm_start_mode_names[mode];
}
*/
const char *snd_pcm_xrun_mode_name(snd_pcm_xrun_t mode)
{
- assert(mode <= SND_PCM_XRUN_LAST);
+ if (mode > SND_PCM_XRUN_LAST)
+ return NULL;
return snd_pcm_xrun_mode_names[mode];
}
{
assert(pcm);
assert(out);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
snd_output_printf(out, "stream : %s\n", snd_pcm_stream_name(pcm->stream));
snd_output_printf(out, "access : %s\n", snd_pcm_access_name(pcm->access));
snd_output_printf(out, "format : %s\n", snd_pcm_format_name(pcm->format));
{
assert(pcm);
assert(out);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
snd_output_printf(out, "tstamp_mode : %s\n", snd_pcm_tstamp_mode_name(pcm->tstamp_mode));
snd_output_printf(out, "period_step : %d\n", pcm->period_step);
snd_output_printf(out, "sleep_min : %d\n", pcm->sleep_min);
snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return bytes * 8 / pcm->frame_bits;
}
ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, snd_pcm_sframes_t frames)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return frames * pcm->frame_bits / 8;
}
long snd_pcm_bytes_to_samples(snd_pcm_t *pcm, ssize_t bytes)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return bytes * 8 / pcm->sample_bits;
}
ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, long samples)
{
assert(pcm);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
return samples * pcm->sample_bits / 8;
}
*/
snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler)
{
- assert(handler->type == SND_ASYNC_HANDLER_PCM);
+ if (handler->type == SND_ASYNC_HANDLER_PCM) {
+ SNDMSG("invalid handler type %d", handler->type);
+ return NULL;
+ }
return handler->u.pcm;
}
err = snd_pcm_poll_descriptors(pcm, &pfd, 1);
if (err < 0)
return err;
- assert(err == 1);
+ if (err != 1) {
+ SNDMSG("invalid poll descriptors %d\n", err);
+ return -EIO;
+ }
__retry:
err_poll = poll(&pfd, 1, timeout);
if (err_poll < 0)
break;
}
default:
- assert(0);
+ SNDMSG("invalid format width %d", width);
+ return -EINVAL;
}
return 0;
}
break;
}
default:
- assert(0);
+ SNDMSG("invalid format width %d", width);
+ return -EINVAL;
}
return 0;
}
int width = snd_pcm_format_physical_width(format);
assert(dst_areas);
assert(src_areas);
- assert(channels > 0);
- assert(frames > 0);
+ if (! channels) {
+ SNDMSG("invalid channels %d", channels);
+ return -EINVAL;
+ }
+ if (! frames) {
+ SNDMSG("invalid frames %ld", frames);
+ return -EINVAL;
+ }
while (channels > 0) {
unsigned int step = src_areas->step;
void *src_addr = src_areas->addr;
*/
int snd_pcm_hw_params_can_mmap_sample_resolution(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_MMAP_VALID);
}
*/
int snd_pcm_hw_params_is_double(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_DOUBLE);
}
*/
int snd_pcm_hw_params_is_batch(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_BATCH);
}
*/
int snd_pcm_hw_params_is_block_transfer(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_BLOCK_TRANSFER);
}
*/
int snd_pcm_hw_params_can_overrange(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_OVERRANGE);
}
*/
int snd_pcm_hw_params_can_pause(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_PAUSE);
}
*/
int snd_pcm_hw_params_can_resume(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_RESUME);
}
*/
int snd_pcm_hw_params_is_half_duplex(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_HALF_DUPLEX);
}
*/
int snd_pcm_hw_params_is_joint_duplex(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_JOINT_DUPLEX);
}
*/
int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return 0; /* FIXME: should be a negative error? */
+ }
return !!(params->info & SNDRV_PCM_INFO_SYNC_START);
}
int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
unsigned int *rate_num, unsigned int *rate_den)
{
- assert(params && params->rate_den != 0);
+ assert(params);
+ if (CHECK_SANITY(params->rate_den == 0)) {
+ SNDMSG("invalid rate_den value");
+ return -EINVAL;
+ }
*rate_num = params->rate_num;
*rate_den = params->rate_den;
return 0;
*/
int snd_pcm_hw_params_get_sbits(const snd_pcm_hw_params_t *params)
{
- assert(params && params->msbits != 0);
+ assert(params);
+ if (CHECK_SANITY(params->msbits == 0)) {
+ SNDMSG("invalid msbits value");
+ return -EINVAL;
+ }
return params->msbits;
}
*/
int snd_pcm_hw_params_get_fifo_size(const snd_pcm_hw_params_t *params)
{
- assert(params && params->info != ~0U);
+ assert(params);
+ if (CHECK_SANITY(params->info == ~0U)) {
+ SNDMSG("invalid PCM info field");
+ return -EINVAL;
+ }
return params->fifo_size;
}
int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
{
assert(pcm && params);
- assert(pcm->setup);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
params->tstamp_mode = pcm->tstamp_mode;
params->period_step = pcm->period_step;
params->sleep_min = pcm->sleep_min;
params->start_threshold = pcm->boundary;
break;
default:
- assert(0);
- break;
+ SNDMSG("invalid start mode value %d\n", val);
+ return -EINVAL;
}
return 0;
}
params->stop_threshold = pcm->boundary;
break;
default:
- assert(0);
- break;
+ SNDMSG("invalid xrun mode value %d\n", val);
+ return -EINVAL;
}
return 0;
}
#endif
{
assert(pcm && params);
- assert(val <= SND_PCM_TSTAMP_LAST);
+ if (CHECK_SANITY(val > SND_PCM_TSTAMP_LAST)) {
+ SNDMSG("invalid tstamp_mode value %d", val);
+ return -EINVAL;
+ }
params->tstamp_mode = val;
return 0;
}
#endif
{
assert(pcm && params);
- assert(val % pcm->min_align == 0);
+ if (CHECK_SANITY(val % pcm->min_align)) {
+ SNDMSG("xfer_align (%ld) is not aligned to min_align (%ld)", val, pcm->min_align);
+ return -EINVAL;
+ }
params->xfer_align = val;
return 0;
}
#endif
{
assert(pcm && params);
- assert(val < pcm->buffer_size);
+ if (CHECK_SANITY(val >= pcm->buffer_size)) {
+ SNDMSG("invalid silent_threshold value %ld (buffer_size = %ld)",
+ val, pcm->buffer_size);
+ return -EINVAL;
+ }
params->silence_threshold = val;
return 0;
}
#endif
{
assert(pcm && params);
- assert(val >= pcm->boundary || val <= pcm->buffer_size);
+ if (CHECK_SANITY(val < pcm->boundary && val > pcm->buffer_size)) {
+ SNDMSG("invalid silence_size %ld (boundary %ld, buffer_size %ld)",
+ val, pcm->boundary, pcm->buffer_size);
+ return -EINVAL;
+ }
params->silence_size = val;
return 0;
}
snd_pcm_uframes_t frames)
{
assert(pcm);
- assert(offset == *pcm->appl.ptr % pcm->buffer_size);
- assert(frames <= snd_pcm_mmap_avail(pcm));
+ if (CHECK_SANITY(offset != *pcm->appl.ptr % pcm->buffer_size)) {
+ SNDMSG("commit offset (%ld) doesn't match with appl_ptr (%ld) %% buf_size (%ld)",
+ offset, *pcm->appl.ptr, pcm->buffer_size);
+ return -EPIPE;
+ }
+ if (CHECK_SANITY(frames > snd_pcm_mmap_avail(pcm))) {
+ SNDMSG("commit frames (%ld) overflow (avail = %ld)", frames,
+ snd_pcm_mmap_avail(pcm));
+ return -EPIPE;
+ }
return pcm->fast_ops->mmap_commit(pcm->fast_op_arg, offset, frames);
}
frames = size;
if (frames > (snd_pcm_uframes_t) avail)
frames = avail;
- assert(frames != 0);
+ if (! frames)
+ break;
err = func(pcm, areas, offset, frames);
if (err < 0)
break;
frames = size;
if (frames > (snd_pcm_uframes_t) avail)
frames = avail;
- assert(frames != 0);
+ if (! frames)
+ break;
err = func(pcm, areas, offset, frames);
if (err < 0)
break;
((hw)->mmap_status->tstamp)
#endif /* DOC_HIDDEN */
-static inline int check_std_error(int error)
-{
- switch (error) {
- case -EAGAIN:
- case -EPIPE:
- case -ESTRPIPE:
- case -ENXIO:
- case -ENOSYS:
- return 0;
- }
- return 1;
-}
-
struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm)
{
struct timespec res;
err = ioctl((hw)->fd, SNDRV_PCM_IOCTL_SYNC_PTR, (hw)->sync_ptr);
if (err < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_SYNC_PTR failed");
+ SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed");
return err;
}
return 0;
if ((flags = fcntl(fd, F_GETFL)) < 0) {
err = -errno;
- SYSERR("F_GETFL failed");
+ SYSMSG("F_GETFL failed");
return err;
}
if (nonblock)
flags &= ~O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0) {
err = -errno;
- SYSERR("F_SETFL for O_NONBLOCK failed");
+ SYSMSG("F_SETFL for O_NONBLOCK failed");
return err;
}
return 0;
if ((flags = fcntl(fd, F_GETFL)) < 0) {
err = -errno;
- SYSERR("F_GETFL failed");
+ SYSMSG("F_GETFL failed");
return err;
}
if (sig >= 0)
flags &= ~O_ASYNC;
if (fcntl(fd, F_SETFL, flags) < 0) {
err = -errno;
- SYSERR("F_SETFL for O_ASYNC failed");
+ SYSMSG("F_SETFL for O_ASYNC failed");
return err;
}
if (sig < 0)
return 0;
if (fcntl(fd, F_SETSIG, (long)sig) < 0) {
err = -errno;
- SYSERR("F_SETSIG failed");
+ SYSMSG("F_SETSIG failed");
return err;
}
if (fcntl(fd, F_SETOWN, (long)pid) < 0) {
err = -errno;
- SYSERR("F_SETOWN failed");
+ SYSMSG("F_SETOWN failed");
return err;
}
return 0;
int fd = hw->fd, err;
if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, info) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_INFO failed");
+ SYSMSG("SNDRV_PCM_IOCTL_INFO failed");
return err;
}
return 0;
} else {
if (hw_refine_call(hw, params) < 0) {
err = -errno;
- // SYSERR("SNDRV_PCM_IOCTL_HW_REFINE failed");
+ // SYSMSG("SNDRV_PCM_IOCTL_HW_REFINE failed");
return err;
}
}
if (hw_params_call(hw, params) < 0) {
_err:
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_HW_PARAMS failed");
+ SYSMSG("SNDRV_PCM_IOCTL_HW_PARAMS failed");
return err;
}
}
int fd = hw->fd, err;
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_FREE) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_HW_FREE failed");
+ SYSMSG("SNDRV_PCM_IOCTL_HW_FREE failed");
return err;
}
return 0;
}
if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_SW_PARAMS failed");
+ SYSMSG("SNDRV_PCM_IOCTL_SW_PARAMS failed");
return err;
}
hw->mmap_control->avail_min = params->avail_min;
i.channel = info->channel;
if (ioctl(fd, SNDRV_PCM_IOCTL_CHANNEL_INFO, &i) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_CHANNEL_INFO failed");
+ SYSMSG("SNDRV_PCM_IOCTL_CHANNEL_INFO failed");
return err;
}
info->channel = i.channel;
int fd = hw->fd, err;
if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS, status) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_STATUS failed");
+ SYSMSG("SNDRV_PCM_IOCTL_STATUS failed");
return err;
}
if (SNDRV_PROTOCOL_VERSION(2, 0, 5) > hw->version) {
}
if (ioctl(fd, SNDRV_PCM_IOCTL_DELAY, delayp) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_DELAY failed");
+ SYSMSG("SNDRV_PCM_IOCTL_DELAY failed");
return err;
}
return 0;
} else {
if (ioctl(fd, SNDRV_PCM_IOCTL_HWSYNC) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_HWSYNC failed");
+ SYSMSG("SNDRV_PCM_IOCTL_HWSYNC failed");
return err;
}
}
int fd = hw->fd, err;
if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_PREPARE failed");
+ SYSMSG("SNDRV_PCM_IOCTL_PREPARE failed");
return err;
}
return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL);
int fd = hw->fd, err;
if (ioctl(fd, SNDRV_PCM_IOCTL_RESET) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_RESET failed");
+ SYSMSG("SNDRV_PCM_IOCTL_RESET failed");
return err;
}
return sync_ptr(hw, SNDRV_PCM_SYNC_PTR_APPL);
#endif
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_START failed");
+ SYSMSG("SNDRV_PCM_IOCTL_START failed");
#if 0
if (err == -EBADFD)
SNDERR("PCM state = %s", snd_pcm_state_name(snd_pcm_hw_state(pcm)));
int err;
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DROP) < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_DROP failed");
+ SYSMSG("SNDRV_PCM_IOCTL_DROP failed");
return err;
}
return 0;
int err;
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DRAIN) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_DRAIN failed");
+ SYSMSG("SNDRV_PCM_IOCTL_DRAIN failed");
return err;
}
return 0;
int err;
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_PAUSE, enable) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_PAUSE failed");
+ SYSMSG("SNDRV_PCM_IOCTL_PAUSE failed");
return err;
}
return 0;
int err;
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_REWIND, &frames) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_REWIND failed");
+ SYSMSG("SNDRV_PCM_IOCTL_REWIND failed");
return err;
}
return frames;
if (SNDRV_PROTOCOL_VERSION(2, 0, 4) <= hw->version) {
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_FORWARD, &frames) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_FORWARD failed");
+ SYSMSG("SNDRV_PCM_IOCTL_FORWARD failed");
return err;
}
return frames;
int fd = hw->fd, err;
if (ioctl(fd, SNDRV_PCM_IOCTL_RESUME) < 0) {
err = -errno;
- if (check_std_error(err))
- SYSERR("SNDRV_PCM_IOCTL_RESUME failed");
+ SYSMSG("SNDRV_PCM_IOCTL_RESUME failed");
return err;
}
return 0;
err = ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, &sync_ptr);
if (err < 0) {
err = -errno;
- SYSERR("SNDRV_PCM_IOCTL_SYNC_PTR failed");
+ SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed");
return err;
}
hw->sync_ptr = calloc(1, sizeof(struct sndrv_pcm_sync_ptr));
hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
if (ptr == MAP_FAILED || ptr == NULL) {
err = -errno;
- SYSERR("control mmap failed");
+ SYSMSG("control mmap failed");
return err;
}
hw->mmap_control = ptr;
} else {
if (munmap((void*)hw->mmap_status, page_align(sizeof(*hw->mmap_status))) < 0) {
err = -errno;
- SYSERR("status munmap failed");
+ SYSMSG("status munmap failed");
return err;
}
}
} else {
if (munmap(hw->mmap_control, page_align(sizeof(*hw->mmap_control))) < 0) {
err = -errno;
- SYSERR("control munmap failed");
+ SYSMSG("control munmap failed");
return err;
}
}
int err;
if (close(hw->fd)) {
err = -errno;
- SYSERR("close failed\n");
+ SYSMSG("close failed\n");
return err;
}
snd_pcm_hw_munmap_status(pcm);
} while (size > 0);
return result;
} else {
- snd_pcm_hw_t *hw = pcm->private_data;
assert(hw->shadow_appl_ptr);
}
}
hw->avail_update_flag = 0;
if (err < 0)
return err;
- assert((snd_pcm_uframes_t)err == avail);
+ if ((snd_pcm_uframes_t)err != avail)
+ SNDMSG("short read %ld for avail %ld", err, avail);
return err;
}
}
snd_pcm_hw_t *hw = pcm->private_data;
char *name;
int err = snd_card_get_name(hw->card, &name);
- assert(err >= 0);
+ if (err < 0) {
+ SNDERR("cannot get card name");
+ return;
+ }
snd_output_printf(out, "Hardware PCM card %d '%s' device %d subdevice %d\n",
hw->card, name, hw->device, hw->subdevice);
free(name);
memset(&info, 0, sizeof(info));
if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
ret = -errno;
- SYSERR("SNDRV_PCM_IOCTL_INFO failed");
+ SYSMSG("SNDRV_PCM_IOCTL_INFO failed");
close(fd);
return ret;
*/
if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
ret = -errno;
- SYSERR("fcntl FD_CLOEXEC failed");
+ SYSMSG("fcntl FD_CLOEXEC failed");
close(fd);
return ret;
}
if (ioctl(fd, SNDRV_PCM_IOCTL_PVERSION, &ver) < 0) {
ret = -errno;
- SYSERR("SNDRV_PCM_IOCTL_PVERSION failed");
+ SYSMSG("SNDRV_PCM_IOCTL_PVERSION failed");
close(fd);
return ret;
}
int on = 1;
if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
ret = -errno;
- SNDERR("TSTAMP failed\n");
+ SNDMSG("TSTAMP failed\n");
return ret;
}
}
filefmt = SNDRV_FILE_PCM_STREAM_CAPTURE;
break;
default:
- assert(0);
+ SNDERR("invalid stream %d", stream);
+ return -EINVAL;
}
sprintf(filename, filefmt, card, device);
fmode |= O_ASYNC;
if ((fd = open(filename, fmode)) < 0) {
ret = -errno;
- SYSERR("open %s failed", filename);
+ SYSMSG("open %s failed", filename);
goto _err;
}
if (subdevice >= 0) {
memset(&info, 0, sizeof(info));
if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
ret = -errno;
- SYSERR("SNDRV_PCM_IOCTL_INFO failed");
+ SYSMSG("SNDRV_PCM_IOCTL_INFO failed");
goto _err;
}
if (info.subdevice != (unsigned int) subdevice) {
{
snd_pcm_uframes_t xfer = 0;
- assert(snd_pcm_mmap_playback_avail(pcm) >= size);
+ if (snd_pcm_mmap_playback_avail(pcm) < size) {
+ SNDMSG("too short avail %ld to size %ld", snd_pcm_mmap_playback_avail(pcm), size);
+ return -EPIPE;
+ }
while (size > 0) {
const snd_pcm_channel_area_t *pcm_areas;
snd_pcm_uframes_t pcm_offset;
{
snd_pcm_uframes_t xfer = 0;
- assert(snd_pcm_mmap_capture_avail(pcm) >= size);
+ if (snd_pcm_mmap_capture_avail(pcm) < size) {
+ SNDMSG("too short avail %ld to size %ld", snd_pcm_mmap_capture_avail(pcm), size);
+ return -EPIPE;
+ }
while (size > 0) {
const snd_pcm_channel_area_t *pcm_areas;
snd_pcm_uframes_t pcm_offset;
info->step = pcm->sample_bits;
break;
default:
- assert(0);
- break;
+ SNDMSG("invalid access type %d", pcm->access);
+ return -EINVAL;
}
info->addr = 0;
info->type = SND_PCM_AREA_SHM;
int err;
unsigned int c;
assert(pcm);
- assert(pcm->setup);
- assert(!pcm->mmap_channels);
+ if (CHECK_SANITY(! pcm->setup)) {
+ SNDMSG("PCM not set up");
+ return -EIO;
+ }
+ if (CHECK_SANITY(pcm->mmap_channels || pcm->running_areas)) {
+ SNDMSG("Already mmapped");
+ return -EBUSY;
+ }
err = pcm->ops->mmap(pcm);
if (err < 0)
return err;
pcm->mmap_channels = calloc(pcm->channels, sizeof(pcm->mmap_channels[0]));
if (!pcm->mmap_channels)
return -ENOMEM;
- assert(!pcm->running_areas);
pcm->running_areas = calloc(pcm->channels, sizeof(pcm->running_areas[0]));
if (!pcm->running_areas) {
free(pcm->mmap_channels);
int err;
unsigned int c;
assert(pcm);
- assert(pcm->mmap_channels);
+ if (CHECK_SANITY(! pcm->mmap_channels)) {
+ SNDMSG("Not mmapped");
+ return -ENXIO;
+ }
if (pcm->mmap_shadow)
return pcm->ops->munmap(pcm);
for (c = 0; c < pcm->channels; ++c) {
{
snd_pcm_uframes_t xfer = 0;
snd_pcm_sframes_t err = 0;
- assert(size > 0);
+ if (! size)
+ return 0;
while (xfer < size) {
snd_pcm_uframes_t frames = size - xfer;
snd_pcm_uframes_t offset = snd_pcm_mmap_hw_offset(pcm);
break;
}
default:
- assert(0);
- err = -EINVAL;
- break;
+ SNDMSG("invalid access type %d", pcm->access);
+ return -EINVAL;
}
if (err < 0)
break;
{
snd_pcm_uframes_t xfer = 0;
snd_pcm_sframes_t err = 0;
- assert(size > 0);
+ if (! size)
+ return 0;
while (xfer < size) {
snd_pcm_uframes_t frames = size - xfer;
snd_pcm_uframes_t offset = snd_pcm_mmap_hw_offset(pcm);
frames = err;
}
default:
- assert(0);
- err = -EINVAL;
- break;
+ SNDMSG("invalid access type %d", pcm->access);
+ return -EINVAL;
}
if (err < 0)
break;
break;
frames = plugin->write(pcm, areas, offset, frames,
slave_areas, slave_offset, &slave_frames);
- assert(slave_frames <= snd_pcm_mmap_playback_avail(slave));
+ if (CHECK_SANITY(slave_frames > snd_pcm_mmap_playback_avail(slave))) {
+ SNDMSG("write overflow %ld > %ld", slave_frames,
+ snd_pcm_mmap_playback_avail(slave));
+ return -EPIPE;
+ }
snd_atomic_write_begin(&plugin->watom);
snd_pcm_mmap_appl_forward(pcm, frames);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
break;
frames = plugin->read(pcm, areas, offset, frames,
slave_areas, slave_offset, &slave_frames);
- assert(slave_frames <= snd_pcm_mmap_capture_avail(slave));
+ if (CHECK_SANITY(slave_frames > snd_pcm_mmap_capture_avail(slave))) {
+ SNDMSG("read overflow %ld > %ld", slave_frames,
+ snd_pcm_mmap_playback_avail(slave));
+ return -EPIPE;
+ }
snd_atomic_write_begin(&plugin->watom);
snd_pcm_mmap_appl_forward(pcm, frames);
result = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
slave_size -= frames;
xfer += frames;
}
- assert(size == 0);
+ if (CHECK_SANITY(size)) {
+ SNDMSG("short commit: %ld", size);
+ return -EPIPE;
+ }
return xfer;
}
src_frames1++;
states->u.linear.init = 2; /* get a new sample */
//printf("new_src_pos = %i\n", (src - (char *)snd_pcm_channel_area_addr(src_area, src_offset)) / src_step);
- assert(src_frames1 <= src_frames);
+ if (CHECK_SANITY(src_frames1 > src_frames)) {
+ SNDERR("src_frames overflow");
+ break;
+ }
}
}
if (dst_frames != dst_frames1) {
after_put:
dst += dst_step;
dst_frames1++;
- assert(dst_frames1 <= dst_frames);
+ if (CHECK_SANITY(dst_frames1 > dst_frames)) {
+ SNDERR("dst_frames overflow");
+ break;
+ }
}
old_sample = new_sample;
}
/* pitch is get_increment */
}
rate->pitch = (((u_int64_t)dst_rate * LINEAR_DIV) + (src_rate / 2)) / src_rate;
- assert(!rate->states);
- assert(!rate->pareas);
+ if (CHECK_SANITY(rate->states || rate->pareas)) {
+ SNDMSG("rate plugin already in use");
+ return -EBUSY;
+ }
rate->states = malloc(channels * sizeof(*rate->states));
if (rate->states == NULL)
return -ENOMEM;
}
}
} while (1);
- assert((snd_pcm_uframes_t)snd_pcm_rate_client_frames(pcm, slave->period_size ) == pcm->period_size );
+ if ((snd_pcm_uframes_t)snd_pcm_rate_client_frames(pcm, slave->period_size ) != pcm->period_size) {
+ SNDERR("invalid slave period_size %ld for pcm period_size %ld",
+ slave->period_size, pcm->period_size);
+ return -EIO;
+ }
} else {
rate->pitch = (((u_int64_t)pcm->period_size * LINEAR_DIV) + (slave->period_size/2) ) / slave->period_size;
do {
}
}
} while (1);
- assert((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size ) == slave->period_size );
+ if ((snd_pcm_uframes_t)snd_pcm_rate_slave_frames(pcm, pcm->period_size ) != slave->period_size) {
+ SNDERR("invalid pcm period_size %ld for slave period_size",
+ pcm->period_size, slave->period_size);
+ return -EIO;
+ }
}
recalc(pcm, &sparams->avail_min);
rate->orig_avail_min = sparams->avail_min;
result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames);
if (result < 0)
return result;
- assert(slave_offset == 0);
+ if (slave_offset) {
+ SNDERR("non-zero slave_offset %ld", slave_offset);
+ return -EIO;
+ }
snd_pcm_areas_copy(slave_areas, slave_offset,
rate->sareas, xfer,
pcm->channels, cont,
result = snd_pcm_mmap_begin(rate->slave, &slave_areas, &slave_offset, &slave_frames);
if (result < 0)
return result;
- assert(slave_offset == 0);
+ if (slave_offset) {
+ SNDERR("non-zero slave_offset %ld", slave_offset);
+ return -EIO;
+ }
snd_pcm_areas_copy(rate->sareas, xfer,
slave_areas, slave_offset,
pcm->channels, cont,
missing = 1;
}
err = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), frames);
- assert(err == frames);
- slave_avail -= frames;
+ if (err < 0) {
+ SYSMSG("snd_pcm_mmap_commit error");
+ return INT_MAX;
+ }
+ if (err != frames)
+ SYSMSG("commit returns %ld for size %ld", err, frames);
+ slave_avail -= err;
} else {
if (safety_missing == 0)
missing = 1;
running = 1;
break;
default:
- assert(0);
- break;
+ SNDERR("invalid shared PCM state %d", share->state);
+ return INT_MAX;
}
update_poll:
pfd[0].fd = slave->poll[0];
pfd[0].events = POLLIN;
err = snd_pcm_poll_descriptors(spcm, &pfd[1], 1);
- assert(err == 1);
+ if (err != 1) {
+ SNDERR("invalid poll descriptors %d", err);
+ return NULL;
+ }
Pthread_mutex_lock(&slave->mutex);
err = pipe(slave->poll);
- assert(err >= 0);
+ if (err < 0) {
+ SYSERR("can't create a pipe");
+ return NULL;
+ }
while (slave->open_count > 0) {
snd_pcm_uframes_t missing;
// printf("begin min_missing\n");
if ((snd_pcm_uframes_t)avail_min != spcm->avail_min) {
snd_pcm_sw_params_set_avail_min(spcm, &slave->sw_params, avail_min);
err = snd_pcm_sw_params(spcm, &slave->sw_params);
- assert(err >= 0);
+ if (err < 0) {
+ SYSERR("snd_pcm_sw_params error");
+ return NULL;
+ }
}
slave->polling = 1;
Pthread_mutex_unlock(&slave->mutex);
int err;
snd_pcm_sw_params_set_avail_min(spcm, &slave->sw_params, avail_min);
err = snd_pcm_sw_params(spcm, &slave->sw_params);
- assert(err >= 0);
+ if (err < 0) {
+ SYSERR("snd_pcm_sw_params error");
+ return;
+ }
}
}
}
if (frames > 0) {
snd_pcm_sframes_t err;
err = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), frames);
- assert(err == frames);
+ if (err < 0) {
+ SYSMSG("snd_pcm_mmap_commit error");
+ return err;
+ }
+ if (err != frames) {
+ SYSMSG("commit returns %ld for size %ld", err, frames);
+ return err;
+ }
}
_snd_pcm_share_update(pcm);
}