From e8cac7de4d3571cf0e223db001e74473487388db Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Sat, 10 Jun 2000 12:39:51 +0000 Subject: [PATCH] Changed ALSA unit from bytes to frames. Splitted mmap control structs. Better midlevel interrupt handler --- TODO | 1 - acinclude.m4 | 2 +- include/pcm.h | 37 ++-- src/pcm/pcm.c | 109 +++++++----- src/pcm/pcm_common.c | 151 ++-------------- src/pcm/pcm_hw.c | 91 ++++++---- src/pcm/pcm_local.h | 37 ++-- src/pcm/pcm_misc.c | 40 ++--- src/pcm/pcm_mmap.c | 346 ++++++++++++++++-------------------- src/pcm/pcm_plug.c | 88 ++++----- src/pcm/plugin/io.c | 25 +-- src/pcm/plugin/mmap.c | 45 ++--- src/pcm/plugin/plugin_ops.h | 4 +- 13 files changed, 405 insertions(+), 571 deletions(-) diff --git a/TODO b/TODO index c57d6051..043d4ea2 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -M convert all static checks in asserts M plug sync and pos problems M Loopback implementation? L add hsearch_r code from glibc (for compatibility with older distributions) diff --git a/acinclude.m4 b/acinclude.m4 index eda0abb3..bc6600b3 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -16,7 +16,7 @@ void main(void) #if !defined(SND_PROTOCOL_VERSION) || !defined(SND_PROTOCOL_INCOMPATIBLE) #error not found #else -#if !defined(SND_PCM_IOCTL_STREAM_BYTE_IO) +#if !defined(SND_PCM_IOCTL_STREAM_FRAME_IO) #error wrong version #endif exit(0); diff --git a/include/pcm.h b/include/pcm.h index c91d5c06..689cdfd2 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -114,12 +114,10 @@ int snd_pcm_playback_pause(snd_pcm_t *handle, int enable); int snd_pcm_stream_pause(snd_pcm_t *handle, int stream, int enable); int snd_pcm_stream_state(snd_pcm_t *handle, int stream); int snd_pcm_mmap_stream_state(snd_pcm_t *handle, int stream); -ssize_t snd_pcm_stream_byte_io(snd_pcm_t *handle, int stream, int update); -ssize_t snd_pcm_mmap_stream_byte_io(snd_pcm_t *handle, int stream); -ssize_t snd_pcm_stream_byte_data(snd_pcm_t *handle, int stream); -ssize_t snd_pcm_mmap_stream_byte_data(snd_pcm_t *handle, int stream); -ssize_t snd_pcm_stream_seek(snd_pcm_t *pcm, int stream, off_t offset); -ssize_t snd_pcm_mmap_stream_seek(snd_pcm_t *pcm, int stream, off_t offset); +ssize_t snd_pcm_stream_frame_io(snd_pcm_t *handle, int stream, int update); +ssize_t snd_pcm_mmap_stream_frame_io(snd_pcm_t *handle, int stream); +ssize_t snd_pcm_stream_frame_data(snd_pcm_t *handle, int stream, off_t offset); +ssize_t snd_pcm_mmap_stream_frame_data(snd_pcm_t *handle, int stream, off_t offset); ssize_t snd_pcm_write(snd_pcm_t *handle, const void *buffer, size_t size); ssize_t snd_pcm_read(snd_pcm_t *handle, void *buffer, size_t size); ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); @@ -129,10 +127,12 @@ const char *snd_pcm_get_format_description(int format); int snd_pcm_get_format_value(const char* name); int snd_pcm_dump_setup(snd_pcm_t *pcm, int stream, FILE *fp); -int snd_pcm_mmap(snd_pcm_t *handle, int stream, snd_pcm_mmap_control_t **control, void **buffer); +int snd_pcm_mmap(snd_pcm_t *handle, int stream, snd_pcm_mmap_status_t **status, snd_pcm_mmap_control_t **control, void **buffer); int snd_pcm_munmap(snd_pcm_t *handle, int stream); +int snd_pcm_mmap_status(snd_pcm_t *handle, int stream, snd_pcm_mmap_status_t **status); int snd_pcm_mmap_control(snd_pcm_t *handle, int stream, snd_pcm_mmap_control_t **control); int snd_pcm_mmap_data(snd_pcm_t *handle, int stream, void **buffer); +int snd_pcm_munmap_status(snd_pcm_t *handle, int stream); int snd_pcm_munmap_control(snd_pcm_t *handle, int stream); int snd_pcm_munmap_data(snd_pcm_t *handle, int stream); int snd_pcm_channels_mask(snd_pcm_t *pcm, int stream, bitset_t *client_vmask); @@ -150,8 +150,6 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels ssize_t snd_pcm_mmap_read_frames(snd_pcm_t *pcm, const void *buffer, size_t frames); int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, int stream, snd_pcm_channel_area_t *areas); -ssize_t snd_pcm_bytes_per_second(snd_pcm_t *pcm, int stream); - int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, size_t dst_offset, size_t samples, int format); int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_channels, size_t dst_offset, @@ -163,6 +161,11 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_channels, size_t src_of const snd_pcm_channel_area_t *dst_channels, size_t dst_offset, size_t vcount, size_t frames, int format); +ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, int stream, ssize_t bytes); +ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, int stream, ssize_t frames); +ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *pcm, int stream, ssize_t bytes); +ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int stream, ssize_t samples); + /* misc */ @@ -175,7 +178,6 @@ int snd_pcm_format_width(int format); /* in bits */ int snd_pcm_format_physical_width(int format); /* in bits */ int snd_pcm_build_linear_format(int width, int unsignd, int big_endian); ssize_t snd_pcm_format_size(int format, size_t samples); -ssize_t snd_pcm_format_bytes_per_second(snd_pcm_format_t *format); u_int8_t snd_pcm_format_silence(int format); u_int16_t snd_pcm_format_silence_16(int format); u_int32_t snd_pcm_format_silence_32(int format); @@ -270,19 +272,8 @@ int snd_pcm_plug_remove_first(snd_pcm_t *handle, int stream); snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_t *handle, int stream); snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_t *handle, int stream); int snd_pcm_plug_direct(snd_pcm_t *pcm, int stream); -ssize_t snd_pcm_plug_client_frames(snd_pcm_t *handle, int stream, size_t drv_frames); -ssize_t snd_pcm_plug_slave_frames(snd_pcm_t *handle, int stream, size_t clt_frames); -ssize_t snd_pcm_plug_client_size(snd_pcm_t *handle, int stream, size_t drv_size); -ssize_t snd_pcm_plug_slave_size(snd_pcm_t *handle, int stream, size_t clt_size); - -/* - * Plug-In helpers - */ - -ssize_t snd_pcm_plugin_src_frames_to_size(snd_pcm_plugin_t *plugin, size_t frames); -ssize_t snd_pcm_plugin_dst_frames_to_size(snd_pcm_plugin_t *plugin, size_t frames); -ssize_t snd_pcm_plugin_src_size_to_frames(snd_pcm_plugin_t *plugin, size_t size); -ssize_t snd_pcm_plugin_dst_size_to_frames(snd_pcm_plugin_t *plugin, size_t size); +ssize_t snd_pcm_plug_client_size(snd_pcm_t *handle, int stream, size_t drv_frames); +ssize_t snd_pcm_plug_slave_size(snd_pcm_t *handle, int stream, size_t clt_frames); /* * Plug-In constructors diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index f902a06f..a6083a13 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -68,6 +68,10 @@ int snd_pcm_stream_close(snd_pcm_t *pcm, int stream) assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; assert(str->open); + if (str->mmap_status) { + if ((err = snd_pcm_munmap_status(pcm, stream)) < 0) + ret = err; + } if (str->mmap_control) { if ((err = snd_pcm_munmap_control(pcm, stream)) < 0) ret = err; @@ -167,9 +171,8 @@ int snd_pcm_stream_setup(snd_pcm_t *pcm, snd_pcm_stream_setup_t *setup) if ((err = pcm->ops->stream_setup(pcm, setup)) < 0) return err; memcpy(&str->setup, setup, sizeof(*setup)); - str->sample_width = snd_pcm_format_physical_width(setup->format.format); - str->bits_per_frame = str->sample_width * setup->format.channels; - str->frames_per_frag = setup->frag_size * 8 / str->bits_per_frame; + str->bits_per_sample = snd_pcm_format_physical_width(setup->format.format); + str->bits_per_frame = str->bits_per_sample * setup->format.channels; str->valid_setup = 1; return 0; } @@ -209,33 +212,21 @@ int snd_pcm_stream_state(snd_pcm_t *pcm, int stream) assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; assert(str->open); - if (str->mmap_control) - return str->mmap_control->state; + if (str->mmap_status) + return str->mmap_status->state; return pcm->ops->stream_state(pcm, stream); } -int snd_pcm_stream_byte_io(snd_pcm_t *pcm, int stream, int update) +int snd_pcm_stream_frame_io(snd_pcm_t *pcm, int stream, int update) { snd_pcm_stream_t *str; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; assert(str->valid_setup); - if (str->mmap_control && !update) - return str->mmap_control->byte_io; - return pcm->ops->stream_byte_io(pcm, stream, update); -} - -int snd_pcm_stream_byte_data(snd_pcm_t *pcm, int stream) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - if (str->mmap_control) - return str->mmap_control->byte_data; - return pcm->ops->stream_seek(pcm, stream, 0); + if (str->mmap_status && !update) + return str->mmap_status->frame_io; + return pcm->ops->stream_frame_io(pcm, stream, update); } int snd_pcm_stream_prepare(snd_pcm_t *pcm, int stream) @@ -333,17 +324,20 @@ int snd_pcm_playback_pause(snd_pcm_t *pcm, int enable) return snd_pcm_stream_pause(pcm, SND_PCM_STREAM_PLAYBACK, enable); } -ssize_t snd_pcm_stream_seek(snd_pcm_t *pcm, int stream, off_t offset) +ssize_t snd_pcm_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) { snd_pcm_stream_t *str; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; assert(str->valid_setup); - if (str->mmap_control) - return snd_pcm_mmap_stream_seek(pcm, stream, offset); - else - return pcm->ops->stream_seek(pcm, stream, offset); + if (str->mmap_control) { + if (offset == 0) + return str->mmap_control->frame_data; + if (str->mmap_status) + return snd_pcm_mmap_stream_frame_data(pcm, stream, offset); + } + return pcm->ops->stream_frame_data(pcm, stream, offset); } ssize_t snd_pcm_write(snd_pcm_t *pcm, const void *buffer, size_t size) @@ -353,7 +347,7 @@ ssize_t snd_pcm_write(snd_pcm_t *pcm, const void *buffer, size_t size) str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; assert(str->valid_setup); assert(size == 0 || buffer); - assert(size % str->setup.bytes_align == 0); + assert(size % str->setup.frames_align == 0); return pcm->ops->write(pcm, buffer, size); } @@ -372,7 +366,7 @@ ssize_t snd_pcm_read(snd_pcm_t *pcm, void *buffer, size_t size) str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; assert(str->valid_setup); assert(size == 0 || buffer); - assert(size % str->setup.bytes_align == 0); + assert(size % str->setup.frames_align == 0); return pcm->ops->read(pcm, buffer, size); } @@ -400,16 +394,6 @@ int snd_pcm_channels_mask(snd_pcm_t *pcm, int stream, bitset_t *client_vmask) return pcm->ops->channels_mask(pcm, stream, client_vmask); } -ssize_t snd_pcm_bytes_per_second(snd_pcm_t *pcm, int stream) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; - assert(str->valid_setup); - return snd_pcm_format_bytes_per_second(&str->setup.format); -} - typedef struct { int value; const char* name; @@ -513,13 +497,13 @@ int snd_pcm_dump_setup(snd_pcm_t *pcm, int stream, FILE *fp) fprintf(fp, "buffer_size: %d\n", setup->buffer_size); fprintf(fp, "frag_size: %d\n", setup->frag_size); fprintf(fp, "frags: %d\n", setup->frags); - fprintf(fp, "byte_boundary: %d\n", setup->byte_boundary); + fprintf(fp, "frame_boundary: %d\n", setup->frame_boundary); fprintf(fp, "msbits_per_sample: %d\n", setup->msbits_per_sample); - fprintf(fp, "bytes_min: %d\n", setup->bytes_min); - fprintf(fp, "bytes_align: %d\n", setup->bytes_align); - fprintf(fp, "bytes_xrun_max: %d\n", setup->bytes_xrun_max); + fprintf(fp, "frames_min: %d\n", setup->frames_min); + fprintf(fp, "frames_align: %d\n", setup->frames_align); + fprintf(fp, "frames_xrun_max: %d\n", setup->frames_xrun_max); fprintf(fp, "fill_mode: %s\n", assoc(setup->fill_mode, fills)); - fprintf(fp, "bytes_fill_max: %d\n", setup->bytes_fill_max); + fprintf(fp, "frames_fill_max: %d\n", setup->frames_fill_max); return 0; } @@ -547,3 +531,42 @@ int snd_pcm_get_format_value(const char* name) return -1; } +ssize_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, int stream, int bytes) +{ + snd_pcm_stream_t *str; + assert(pcm); + assert(stream >= 0 && stream <= 1); + str = &pcm->stream[stream]; + assert(str->valid_setup); + return bytes * 8 / str->bits_per_frame; +} + +ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, int stream, int frames) +{ + snd_pcm_stream_t *str; + assert(pcm); + assert(stream >= 0 && stream <= 1); + str = &pcm->stream[stream]; + assert(str->valid_setup); + return frames * str->bits_per_frame / 8; +} + +ssize_t snd_pcm_bytes_to_samples(snd_pcm_t *pcm, int stream, int bytes) +{ + snd_pcm_stream_t *str; + assert(pcm); + assert(stream >= 0 && stream <= 1); + str = &pcm->stream[stream]; + assert(str->valid_setup); + return bytes * 8 / str->bits_per_sample; +} + +ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int stream, int samples) +{ + snd_pcm_stream_t *str; + assert(pcm); + assert(stream >= 0 && stream <= 1); + str = &pcm->stream[stream]; + assert(str->valid_setup); + return samples * str->bits_per_sample / 8; +} diff --git a/src/pcm/pcm_common.c b/src/pcm/pcm_common.c index 8c3ce79d..6885f7cd 100644 --- a/src/pcm/pcm_common.c +++ b/src/pcm/pcm_common.c @@ -80,7 +80,7 @@ static ssize_t snd_pcm_plugin_side_channels(snd_pcm_plugin_t *plugin, *channels = v; if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; - size = format->channels * frames * width; + size = frames * format->channels * width; assert(size % 8 == 0); size /= 8; ptr = (char *)snd_pcm_plug_buf_alloc(plugin->handle, plugin->stream, size); @@ -194,51 +194,7 @@ int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin) return 0; } -ssize_t snd_pcm_plugin_src_frames_to_size(snd_pcm_plugin_t *plugin, size_t frames) -{ - ssize_t result; - - assert(plugin); - result = frames * plugin->src_format.channels * plugin->src_width; - assert(result % 8 == 0); - return result / 8; -} - -ssize_t snd_pcm_plugin_dst_frames_to_size(snd_pcm_plugin_t *plugin, size_t frames) -{ - ssize_t result; - - assert(plugin); - result = frames * plugin->dst_format.channels * plugin->dst_width; - assert(result % 8 == 0); - return result / 8; -} - -ssize_t snd_pcm_plugin_src_size_to_frames(snd_pcm_plugin_t *plugin, size_t size) -{ - ssize_t result; - long tmp; - - assert(plugin); - result = size * 8; - tmp = plugin->src_format.channels * plugin->src_width; - assert(result % tmp == 0); - return result / tmp; -} - -ssize_t snd_pcm_plugin_dst_size_to_frames(snd_pcm_plugin_t *plugin, size_t size) -{ - ssize_t result; - long tmp; - - assert(plugin); - result = size * 8; - tmp = plugin->dst_format.channels * plugin->dst_width; - assert(result % tmp == 0); - return result / tmp; -} - -ssize_t snd_pcm_plug_client_frames(snd_pcm_plugin_handle_t *handle, int stream, size_t drv_frames) +ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, size_t drv_frames) { snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; @@ -266,7 +222,7 @@ ssize_t snd_pcm_plug_client_frames(snd_pcm_plugin_handle_t *handle, int stream, return drv_frames; } -ssize_t snd_pcm_plug_slave_frames(snd_pcm_plugin_handle_t *handle, int stream, size_t clt_frames) +ssize_t snd_pcm_plug_slave_size(snd_pcm_plugin_handle_t *handle, int stream, size_t clt_frames) { snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; ssize_t frames; @@ -302,81 +258,6 @@ ssize_t snd_pcm_plug_slave_frames(snd_pcm_plugin_handle_t *handle, int stream, s return frames; } -ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, size_t drv_size) -{ - snd_pcm_plugin_t *plugin; - ssize_t result = 0; - - assert(handle); - if (drv_size == 0) - return 0; - if (stream == SND_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_PLAYBACK); - if (plugin == NULL) - return drv_size; - result = snd_pcm_plugin_dst_size_to_frames(plugin, drv_size); - if (result < 0) - return result; - result = snd_pcm_plug_client_frames(handle, SND_PCM_STREAM_PLAYBACK, result); - if (result < 0) - return result; - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); - result = snd_pcm_plugin_src_frames_to_size(plugin, result); - } else if (stream == SND_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); - if (plugin == NULL) - return drv_size; - result = snd_pcm_plugin_src_size_to_frames(plugin, drv_size); - if (result < 0) - return result; - result = snd_pcm_plug_client_frames(handle, SND_PCM_STREAM_CAPTURE, result); - if (result < 0) - return result; - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); - result = snd_pcm_plugin_dst_frames_to_size(plugin, result); - } else - assert(0); - return result; -} - -ssize_t snd_pcm_plug_slave_size(snd_pcm_plugin_handle_t *handle, int stream, size_t clt_size) -{ - snd_pcm_plugin_t *plugin; - ssize_t result = 0; - - assert(handle); - if (clt_size == 0) - return 0; - if (stream == SND_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); - if (plugin == NULL) - return clt_size; - result = snd_pcm_plugin_src_size_to_frames(plugin, clt_size); - if (result < 0) - return result; - result = snd_pcm_plug_slave_frames(handle, SND_PCM_STREAM_PLAYBACK, result); - if (result < 0) - return result; - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_PLAYBACK); - result = snd_pcm_plugin_dst_frames_to_size(plugin, result); - } else if (stream == SND_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); - if (plugin == NULL) - return clt_size; - result = snd_pcm_plugin_dst_size_to_frames(plugin, clt_size); - if (result < 0) - return result; - result = snd_pcm_plug_slave_frames(handle, SND_PCM_STREAM_CAPTURE, result); - if (result < 0) - return result; - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); - result = snd_pcm_plugin_src_frames_to_size(plugin, result); - } else - assert(0); - return result; -} - - unsigned int snd_pcm_plug_formats(unsigned int formats) { int linfmts = (SND_PCM_FMT_U8 | SND_PCM_FMT_S8 | @@ -796,7 +677,6 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, *channels = v; if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; - assert(count * 8 % width == 0); nchannels = format->channels; assert(format->interleave || format->channels == 1); for (channel = 0; channel < nchannels; channel++, v++) { @@ -837,8 +717,7 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, return width; nchannels = format->channels; if (format->interleave) { - assert(count == 1 && vector->iov_base && - vector->iov_len * 8 % width == 0); + assert(count == 1 && vector->iov_base); for (channel = 0; channel < nchannels; channel++, v++) { v->enabled = 1; @@ -853,7 +732,6 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, size_t len; assert(count == nchannels); len = vector->iov_len; - assert(len * 8 % width == 0); for (channel = 0; channel < nchannels; channel++, v++, vector++) { assert(vector->iov_len == len); v->enabled = (vector->iov_base != NULL); @@ -863,7 +741,7 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, v->area.first = 0; v->area.step = width; } - return len * nchannels; + return len; } } @@ -1019,16 +897,13 @@ ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plu { snd_pcm_plugin_t *plugin, *next; snd_pcm_plugin_channel_t *dst_channels; - ssize_t frames; int err; + ssize_t frames = size; if ((err = snd_pcm_plug_playback_disable_useless_channels(handle, src_channels)) < 0) return err; plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); - frames = snd_pcm_plugin_src_size_to_frames(plugin, size); - if (frames < 0) - return frames; while (plugin && frames > 0) { if ((next = plugin->next) != NULL) { ssize_t frames1 = frames; @@ -1058,24 +933,18 @@ ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plu plugin = next; } snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr); - frames = snd_pcm_plug_client_frames(handle, SND_PCM_STREAM_PLAYBACK, frames); - if (frames < 0) - return frames; - return snd_pcm_plugin_src_frames_to_size(snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK), frames); + return snd_pcm_plug_client_size(handle, SND_PCM_STREAM_PLAYBACK, frames); } ssize_t snd_pcm_plug_read_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plugin_channel_t *dst_channels_final, size_t size) { snd_pcm_plugin_t *plugin, *next; snd_pcm_plugin_channel_t *src_channels, *dst_channels; - ssize_t frames; + ssize_t frames = size; int err; plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); - frames = snd_pcm_plugin_dst_size_to_frames(plugin, size); - if (frames < 0) - return frames; - frames = snd_pcm_plug_slave_frames(handle, SND_PCM_STREAM_CAPTURE, frames); + frames = snd_pcm_plug_slave_size(handle, SND_PCM_STREAM_CAPTURE, frames); if (frames < 0) return frames; @@ -1119,7 +988,7 @@ ssize_t snd_pcm_plug_read_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plug src_channels = dst_channels; } snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr); - return snd_pcm_plugin_dst_frames_to_size(snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE), frames); + return frames; } int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offset, diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 97c48547..335f901b 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -136,11 +136,11 @@ static ssize_t snd_pcm_hw_stream_state(snd_pcm_t *pcm, int stream) return status.state; } -static ssize_t snd_pcm_hw_stream_byte_io(snd_pcm_t *pcm, int stream, int update UNUSED) +static ssize_t snd_pcm_hw_stream_frame_io(snd_pcm_t *pcm, int stream, int update UNUSED) { snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; int fd = hw->stream[stream].fd; - ssize_t pos = ioctl(fd, SND_PCM_IOCTL_STREAM_BYTE_IO); + ssize_t pos = ioctl(fd, SND_PCM_IOCTL_STREAM_FRAME_IO); if (pos < 0) return -errno; return pos; @@ -200,11 +200,15 @@ static int snd_pcm_hw_stream_pause(snd_pcm_t *pcm, int stream, int enable) return 0; } -static ssize_t snd_pcm_hw_stream_seek(snd_pcm_t *pcm, int stream, off_t offset) +static ssize_t snd_pcm_hw_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) { + ssize_t result; snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; int fd = hw->stream[stream].fd; - return lseek(fd, offset, SEEK_CUR); + result = ioctl(fd, SND_PCM_IOCTL_STREAM_FRAME_DATA, offset); + if (result < 0) + return -errno; + return result; } static ssize_t snd_pcm_hw_write(snd_pcm_t *pcm, const void *buffer, size_t size) @@ -212,7 +216,10 @@ static ssize_t snd_pcm_hw_write(snd_pcm_t *pcm, const void *buffer, size_t size) ssize_t result; snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; int fd = hw->stream[SND_PCM_STREAM_PLAYBACK].fd; - result = write(fd, buffer, size); + snd_xfer_t xfer; + xfer.buf = (char*) buffer; + xfer.count = size; + result = ioctl(fd, SND_PCM_IOCTL_WRITE_FRAMES, &xfer); if (result < 0) return -errno; return result; @@ -223,16 +230,10 @@ static ssize_t snd_pcm_hw_writev(snd_pcm_t *pcm, const struct iovec *vector, uns ssize_t result; snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; int fd = hw->stream[SND_PCM_STREAM_PLAYBACK].fd; -#if 0 - result = writev(fd, vector, count); -#else - { - snd_v_args_t args; - args.vector = vector; - args.count = count; - result = ioctl(fd, SND_IOCTL_WRITEV, &args); - } -#endif + snd_xferv_t xferv; + xferv.vector = vector; + xferv.count = count; + result = ioctl(fd, SND_PCM_IOCTL_WRITEV_FRAMES, &xferv); if (result < 0) return -errno; return result; @@ -243,7 +244,10 @@ static ssize_t snd_pcm_hw_read(snd_pcm_t *pcm, void *buffer, size_t size) ssize_t result; snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; int fd = hw->stream[SND_PCM_STREAM_CAPTURE].fd; - result = read(fd, buffer, size); + snd_xfer_t xfer; + xfer.buf = buffer; + xfer.count = size; + result = ioctl(fd, SND_PCM_IOCTL_READ_FRAMES, &xfer); if (result < 0) return -errno; return result; @@ -254,30 +258,36 @@ ssize_t snd_pcm_hw_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned lo ssize_t result; snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; int fd = hw->stream[SND_PCM_STREAM_CAPTURE].fd; -#if 0 - result = readv(fd, vector, count); -#else - { - snd_v_args_t args; - args.vector = vector; - args.count = count; - result = ioctl(fd, SND_IOCTL_READV, &args); - } -#endif + snd_xferv_t xferv; + xferv.vector = vector; + xferv.count = count; + result = ioctl(fd, SND_PCM_IOCTL_READV_FRAMES, &xferv); if (result < 0) return -errno; return result; } -static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control, size_t csize) +static int snd_pcm_hw_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status) { - void *caddr; + void *ptr; snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; - caddr = mmap(NULL, csize, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, - hw->stream[stream].fd, SND_PCM_MMAP_OFFSET_CONTROL); - if (caddr == MAP_FAILED || caddr == NULL) + ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ, MAP_FILE|MAP_SHARED, + hw->stream[stream].fd, SND_PCM_MMAP_OFFSET_STATUS); + if (ptr == MAP_FAILED || ptr == NULL) return -errno; - *control = caddr; + *status = ptr; + return 0; +} + +static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control) +{ + void *ptr; + snd_pcm_hw_t *hw = (snd_pcm_hw_t*) &pcm->private; + ptr = mmap(NULL, sizeof(snd_pcm_mmap_control_t), PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, + hw->stream[stream].fd, SND_PCM_MMAP_OFFSET_CONTROL); + if (ptr == MAP_FAILED || ptr == NULL) + return -errno; + *control = ptr; return 0; } @@ -295,9 +305,16 @@ static int snd_pcm_hw_mmap_data(snd_pcm_t *pcm, int stream, void **buffer, size_ return 0; } -static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm UNUSED, int stream UNUSED, snd_pcm_mmap_control_t *control, size_t csize) +static int snd_pcm_hw_munmap_status(snd_pcm_t *pcm UNUSED, int stream UNUSED, snd_pcm_mmap_status_t *status) +{ + if (munmap(status, sizeof(*status)) < 0) + return -errno; + return 0; +} + +static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm UNUSED, int stream UNUSED, snd_pcm_mmap_control_t *control) { - if (munmap(control, csize) < 0) + if (munmap(control, sizeof(*control)) < 0) return -errno; return 0; } @@ -330,7 +347,7 @@ struct snd_pcm_ops snd_pcm_hw_ops = { stream_setup: snd_pcm_hw_stream_setup, channel_setup: snd_pcm_hw_channel_setup, stream_status: snd_pcm_hw_stream_status, - stream_byte_io: snd_pcm_hw_stream_byte_io, + stream_frame_io: snd_pcm_hw_stream_frame_io, stream_state: snd_pcm_hw_stream_state, stream_prepare: snd_pcm_hw_stream_prepare, stream_go: snd_pcm_hw_stream_go, @@ -338,13 +355,15 @@ struct snd_pcm_ops snd_pcm_hw_ops = { stream_drain: snd_pcm_hw_stream_drain, stream_flush: snd_pcm_hw_stream_flush, stream_pause: snd_pcm_hw_stream_pause, - stream_seek: snd_pcm_hw_stream_seek, + stream_frame_data: snd_pcm_hw_stream_frame_data, write: snd_pcm_hw_write, writev: snd_pcm_hw_writev, read: snd_pcm_hw_read, readv: snd_pcm_hw_readv, + mmap_status: snd_pcm_hw_mmap_status, mmap_control: snd_pcm_hw_mmap_control, mmap_data: snd_pcm_hw_mmap_data, + munmap_status: snd_pcm_hw_munmap_status, munmap_control: snd_pcm_hw_munmap_control, munmap_data: snd_pcm_hw_munmap_data, file_descriptor: snd_pcm_hw_file_descriptor, diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 76cda9fa..6c4e62cb 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -38,15 +38,17 @@ struct snd_pcm_ops { int (*stream_flush)(snd_pcm_t *pcm, int stream); int (*stream_pause)(snd_pcm_t *pcm, int stream, int enable); int (*stream_state)(snd_pcm_t *pcm, int stream); - ssize_t (*stream_byte_io)(snd_pcm_t *pcm, int stream, int update); - ssize_t (*stream_seek)(snd_pcm_t *pcm, int stream, off_t offset); + ssize_t (*stream_frame_io)(snd_pcm_t *pcm, int stream, int update); + ssize_t (*stream_frame_data)(snd_pcm_t *pcm, int stream, off_t offset); ssize_t (*write)(snd_pcm_t *pcm, const void *buffer, size_t size); ssize_t (*writev)(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); ssize_t (*read)(snd_pcm_t *pcm, void *buffer, size_t size); ssize_t (*readv)(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count); - int (*mmap_control)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control, size_t csize); + int (*mmap_status)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status); + int (*mmap_control)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control); int (*mmap_data)(snd_pcm_t *pcm, int stream, void **buffer, size_t bsize); - int (*munmap_control)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t *control, size_t csize); + int (*munmap_status)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t *status); + int (*munmap_control)(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t *control); int (*munmap_data)(snd_pcm_t *pcm, int stream, void *buffer, size_t bsize); int (*file_descriptor)(snd_pcm_t* pcm, int stream); int (*channels_mask)(snd_pcm_t *pcm, int stream, bitset_t *client_vmask); @@ -72,11 +74,10 @@ typedef struct { int valid_setup; snd_pcm_stream_setup_t setup; snd_pcm_channel_area_t *channels; - size_t sample_width; + size_t bits_per_sample; size_t bits_per_frame; - size_t frames_per_frag; + snd_pcm_mmap_status_t *mmap_status; snd_pcm_mmap_control_t *mmap_control; - size_t mmap_control_size; char *mmap_data; size_t mmap_data_size; enum { _INTERLEAVED, _NONINTERLEAVED, _COMPLEX } mmap_type; @@ -132,19 +133,21 @@ int conv_index(int src_format, int dst_format); #define pdprintf( args... ) { ; } #endif -static inline size_t snd_pcm_mmap_playback_bytes_avail(snd_pcm_stream_t *str) +static inline size_t snd_pcm_mmap_playback_frames_avail(snd_pcm_stream_t *str) { - ssize_t bytes_avail = str->mmap_control->byte_io + str->setup.buffer_size - str->mmap_control->byte_data; - if (bytes_avail < 0) - bytes_avail += str->setup.byte_boundary; - return bytes_avail; + ssize_t frames_avail; + frames_avail = str->mmap_status->frame_io + str->setup.buffer_size - str->mmap_control->frame_data; + if (frames_avail < 0) + frames_avail += str->setup.frame_boundary; + return frames_avail; } -static inline size_t snd_pcm_mmap_capture_bytes_avail(snd_pcm_stream_t *str) +static inline size_t snd_pcm_mmap_capture_frames_avail(snd_pcm_stream_t *str) { - ssize_t bytes_avail = str->mmap_control->byte_io - str->mmap_control->byte_data; - if (bytes_avail < 0) - bytes_avail += str->setup.byte_boundary; - return bytes_avail; + ssize_t frames_avail; + frames_avail = str->mmap_status->frame_io - str->mmap_control->frame_data; + if (frames_avail < 0) + frames_avail += str->setup.frame_boundary; + return frames_avail; } diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c index dd3cf6f3..f2043bc7 100644 --- a/src/pcm/pcm_misc.c +++ b/src/pcm/pcm_misc.c @@ -226,11 +226,6 @@ ssize_t snd_pcm_format_size(int format, size_t samples) } } -ssize_t snd_pcm_format_bytes_per_second(snd_pcm_format_t *format) -{ - return snd_pcm_format_size(format->format, format->channels * format->rate); -} - u_int64_t snd_pcm_format_silence_64(int format) { switch (format) { @@ -314,49 +309,46 @@ u_int8_t snd_pcm_format_silence(int format) return (u_int8_t)snd_pcm_format_silence_64(format); } -ssize_t snd_pcm_format_set_silence(int format, void *data, size_t count) +ssize_t snd_pcm_format_set_silence(int format, void *data, size_t samples) { - size_t count1; - - if (count == 0) + if (samples == 0) return 0; switch (snd_pcm_format_width(format)) { - case 4: + case 4: { + u_int8_t silence = snd_pcm_format_silence_64(format); + size_t samples1; + if (samples % 2 != 0) + return -EINVAL; + samples1 = samples / 2; + memset(data, silence, samples1); + break; + } case 8: { u_int8_t silence = snd_pcm_format_silence_64(format); - memset(data, silence, count); + memset(data, silence, samples); break; } case 16: { u_int16_t silence = snd_pcm_format_silence_64(format); - if (count % 2) - return -EINVAL; - count1 = count / 2; - while (count1-- > 0) + while (samples-- > 0) *((u_int16_t *)data)++ = silence; break; } case 32: { u_int32_t silence = snd_pcm_format_silence_64(format); - if (count % 4) - return -EINVAL; - count1 = count / 4; - while (count1-- > 0) + while (samples-- > 0) *((u_int32_t *)data)++ = silence; break; } case 64: { u_int64_t silence = snd_pcm_format_silence_64(format); - if (count % 8) - return -EINVAL; - count1 = count / 8; - while (count1-- > 0) + while (samples-- > 0) *((u_int64_t *)data)++ = silence; } default: return -EINVAL; } - return count; + return samples; } static int linear_formats[4*2*2] = { diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index 4749885d..aa3bf059 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -25,31 +25,17 @@ #include #include "pcm_local.h" -static ssize_t snd_pcm_mmap_playback_frames_avail(snd_pcm_t *pcm) -{ - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - ssize_t bytes = snd_pcm_mmap_playback_bytes_avail(str); - return bytes * 8 / str->bits_per_frame; -} - -static size_t snd_pcm_mmap_capture_frames_avail(snd_pcm_t *pcm) -{ - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - size_t bytes = snd_pcm_mmap_capture_bytes_avail(str); - return bytes * 8 / str->bits_per_frame; -} - int snd_pcm_frames_avail(snd_pcm_t *pcm, int stream, ssize_t *frames) { snd_pcm_stream_t *str; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - assert(str->mmap_control); + assert(str->mmap_status && str->mmap_control); if (stream == SND_PCM_STREAM_PLAYBACK) - *frames = snd_pcm_mmap_playback_frames_avail(pcm); + *frames = snd_pcm_mmap_playback_frames_avail(str); else - *frames = snd_pcm_mmap_capture_frames_avail(pcm); + *frames = snd_pcm_mmap_capture_frames_avail(str); return 0; } @@ -57,9 +43,9 @@ static int snd_pcm_mmap_playback_ready(snd_pcm_t *pcm) { snd_pcm_stream_t *str; str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - if (str->mmap_control->state == SND_PCM_STATE_XRUN) + if (str->mmap_status->state == SND_PCM_STATE_XRUN) return -EPIPE; - return snd_pcm_mmap_playback_bytes_avail(str) >= str->setup.bytes_min; + return snd_pcm_mmap_playback_frames_avail(str) >= str->setup.frames_min; } static int snd_pcm_mmap_capture_ready(snd_pcm_t *pcm) @@ -67,12 +53,12 @@ static int snd_pcm_mmap_capture_ready(snd_pcm_t *pcm) snd_pcm_stream_t *str; int ret = 0; str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - if (str->mmap_control->state == SND_PCM_STATE_XRUN) { + if (str->mmap_status->state == SND_PCM_STATE_XRUN) { ret = -EPIPE; if (str->setup.xrun_mode == SND_PCM_XRUN_DRAIN) return -EPIPE; } - if (snd_pcm_mmap_capture_bytes_avail(str) >= str->setup.bytes_min) + if (snd_pcm_mmap_capture_frames_avail(str) >= str->setup.frames_min) return 1; return ret; } @@ -80,13 +66,11 @@ static int snd_pcm_mmap_capture_ready(snd_pcm_t *pcm) int snd_pcm_mmap_ready(snd_pcm_t *pcm, int stream) { snd_pcm_stream_t *str; - snd_pcm_mmap_control_t *ctrl; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - ctrl = str->mmap_control; - assert(ctrl); - assert(ctrl->state >= SND_PCM_STATE_PREPARED); + assert(str->mmap_status && str->mmap_control); + assert(str->mmap_status->state >= SND_PCM_STATE_PREPARED); if (stream == SND_PCM_STREAM_PLAYBACK) { return snd_pcm_mmap_playback_ready(pcm); } else { @@ -94,48 +78,32 @@ int snd_pcm_mmap_ready(snd_pcm_t *pcm, int stream) } } -static size_t snd_pcm_mmap_playback_bytes_xfer(snd_pcm_t *pcm, size_t bytes) +static size_t snd_pcm_mmap_playback_frames_xfer(snd_pcm_t *pcm, size_t frames) { snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - snd_pcm_mmap_control_t *ctrl = str->mmap_control; - size_t bytes_cont; - size_t bytes_avail = snd_pcm_mmap_playback_bytes_avail(str); - if (bytes_avail < bytes) - bytes = bytes_avail; - bytes_cont = str->setup.buffer_size - ctrl->byte_data % str->setup.buffer_size; - if (bytes_cont < bytes) - bytes = bytes_cont; - return bytes; + snd_pcm_mmap_control_t *control = str->mmap_control; + size_t frames_cont; + size_t frames_avail = snd_pcm_mmap_playback_frames_avail(str); + if (frames_avail < frames) + frames = frames_avail; + frames_cont = str->setup.buffer_size - control->frame_data % str->setup.buffer_size; + if (frames_cont < frames) + frames = frames_cont; + return frames; } -static size_t snd_pcm_mmap_capture_bytes_xfer(snd_pcm_t *pcm, size_t bytes) +static size_t snd_pcm_mmap_capture_frames_xfer(snd_pcm_t *pcm, size_t frames) { snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - snd_pcm_mmap_control_t *ctrl = str->mmap_control; - size_t bytes_cont; - size_t bytes_avail = snd_pcm_mmap_capture_bytes_avail(str); - if (bytes_avail < bytes) - bytes = bytes_avail; - bytes_cont = str->setup.buffer_size - ctrl->byte_data % str->setup.buffer_size; - if (bytes_cont < bytes) - bytes = bytes_cont; - return bytes; -} - -static ssize_t snd_pcm_mmap_playback_frames_xfer(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - size_t bytes = frames * str->bits_per_frame / 8; - bytes = snd_pcm_mmap_playback_bytes_xfer(pcm, bytes); - return bytes * 8 / str->bits_per_frame; -} - -static ssize_t snd_pcm_mmap_capture_frames_xfer(snd_pcm_t *pcm, size_t frames) -{ - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - size_t bytes = frames * str->bits_per_frame / 8; - bytes = snd_pcm_mmap_capture_bytes_xfer(pcm, bytes); - return bytes * 8 / str->bits_per_frame; + snd_pcm_mmap_control_t *control = str->mmap_control; + size_t frames_cont; + size_t frames_avail = snd_pcm_mmap_capture_frames_avail(str); + if (frames_avail < frames) + frames = frames_avail; + frames_cont = str->setup.buffer_size - control->frame_data % str->setup.buffer_size; + if (frames_cont < frames) + frames = frames_cont; + return frames; } ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *pcm, int stream, size_t frames) @@ -144,7 +112,7 @@ ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *pcm, int stream, size_t frames) assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - assert(str->mmap_control); + assert(str->mmap_status && str->mmap_control); if (stream == SND_PCM_STREAM_PLAYBACK) return snd_pcm_mmap_playback_frames_xfer(pcm, frames); else @@ -154,60 +122,48 @@ ssize_t snd_pcm_mmap_frames_xfer(snd_pcm_t *pcm, int stream, size_t frames) ssize_t snd_pcm_mmap_frames_offset(snd_pcm_t *pcm, int stream) { snd_pcm_stream_t *str; - snd_pcm_mmap_control_t *ctrl; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - ctrl = str->mmap_control; - assert(ctrl); - return (ctrl->byte_data % str->setup.buffer_size) * 8 / str->bits_per_frame; -} - -int snd_pcm_mmap_stream_state(snd_pcm_t *pcm, int stream) -{ - snd_pcm_stream_t *str; - assert(pcm); - assert(stream >= 0 && stream <= 1); - str = &pcm->stream[stream]; assert(str->mmap_control); - return str->mmap_control->state; + return str->mmap_control->frame_data % str->setup.buffer_size; } -int snd_pcm_mmap_stream_byte_io(snd_pcm_t *pcm, int stream) +int snd_pcm_mmap_stream_state(snd_pcm_t *pcm, int stream) { snd_pcm_stream_t *str; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - assert(str->mmap_control); - return str->mmap_control->byte_io; + assert(str->mmap_status); + return str->mmap_status->state; } -int snd_pcm_mmap_stream_byte_data(snd_pcm_t *pcm, int stream) +int snd_pcm_mmap_stream_frame_io(snd_pcm_t *pcm, int stream) { snd_pcm_stream_t *str; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - assert(str->mmap_control); - return str->mmap_control->byte_data; + assert(str->mmap_status); + return str->mmap_status->frame_io; } -ssize_t snd_pcm_mmap_stream_seek(snd_pcm_t *pcm, int stream, off_t offset) +ssize_t snd_pcm_mmap_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) { snd_pcm_stream_t *str; - ssize_t byte_data; + ssize_t frame_data; assert(pcm); assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; - assert(str->mmap_control); - byte_data = str->mmap_control->byte_data; + assert(str->mmap_status && str->mmap_control); + frame_data = str->mmap_control->frame_data; if (offset == 0) - return byte_data; - switch (str->mmap_control->state) { + return frame_data; + switch (str->mmap_status->state) { case SND_PCM_STATE_RUNNING: if (str->setup.mode == SND_PCM_MODE_FRAME) - snd_pcm_stream_byte_io(pcm, stream, 1); + snd_pcm_stream_frame_io(pcm, stream, 1); break; case SND_PCM_STATE_PREPARED: break; @@ -218,44 +174,45 @@ ssize_t snd_pcm_mmap_stream_seek(snd_pcm_t *pcm, int stream, off_t offset) if (offset < -(ssize_t)str->setup.buffer_size) offset = -(ssize_t)str->setup.buffer_size; else - offset -= offset % str->setup.bytes_align; - byte_data += offset; - if (byte_data < 0) - byte_data += str->setup.byte_boundary; + offset -= offset % str->setup.frames_align; + frame_data += offset; + if (frame_data < 0) + frame_data += str->setup.frame_boundary; } else { - size_t bytes_avail; + size_t frames_avail; if (stream == SND_PCM_STREAM_PLAYBACK) - bytes_avail = snd_pcm_mmap_playback_bytes_avail(str); + frames_avail = snd_pcm_mmap_playback_frames_avail(str); else - bytes_avail = snd_pcm_mmap_capture_bytes_avail(str); - if ((size_t)offset > bytes_avail) - offset = bytes_avail; - offset -= offset % str->setup.bytes_align; - byte_data += offset; - if ((size_t)byte_data >= str->setup.byte_boundary) - byte_data -= str->setup.byte_boundary; + frames_avail = snd_pcm_mmap_capture_frames_avail(str); + if ((size_t)offset > frames_avail) + offset = frames_avail; + offset -= offset % str->setup.frames_align; + frame_data += offset; + if ((size_t)frame_data >= str->setup.frame_boundary) + frame_data -= str->setup.frame_boundary; } - str->mmap_control->byte_data = byte_data; - return byte_data; + str->mmap_control->frame_data = frame_data; + return frame_data; } ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels, size_t frames) { snd_pcm_stream_t *str; - snd_pcm_mmap_control_t *ctrl; + snd_pcm_mmap_status_t *status; size_t offset = 0; size_t result = 0; int err; str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - ctrl = str->mmap_control; - assert(ctrl->state >= SND_PCM_STATE_PREPARED); + assert(str->mmap_data && str->mmap_status && str->mmap_control); + status = str->mmap_status; + assert(status->state >= SND_PCM_STATE_PREPARED); if (str->setup.mode == SND_PCM_MODE_FRAGMENT) { - assert(frames % str->frames_per_frag == 0); + assert(frames % str->setup.frag_size == 0); } else { - if (ctrl->state == SND_PCM_STATE_RUNNING && + if (status->state == SND_PCM_STATE_RUNNING && str->mode & SND_PCM_NONBLOCK) - snd_pcm_stream_byte_io(pcm, SND_PCM_STREAM_PLAYBACK, 1); + snd_pcm_stream_frame_io(pcm, SND_PCM_STREAM_PLAYBACK, 1); } while (frames > 0) { ssize_t mmap_offset; @@ -265,7 +222,7 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channel return ready; if (!ready) { struct pollfd pfd; - if (ctrl->state != SND_PCM_STATE_RUNNING) + if (status->state != SND_PCM_STATE_RUNNING) return result > 0 ? result : -EPIPE; if (str->mode & SND_PCM_NONBLOCK) return result > 0 ? result : -EAGAIN; @@ -282,13 +239,13 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channel assert(frames1 > 0); mmap_offset = snd_pcm_mmap_frames_offset(pcm, SND_PCM_STREAM_PLAYBACK); snd_pcm_areas_copy(channels, offset, str->channels, mmap_offset, str->setup.format.channels, frames1, str->setup.format.format); - if (ctrl->state == SND_PCM_STATE_XRUN) + if (status->state == SND_PCM_STATE_XRUN) return result > 0 ? result : -EPIPE; - snd_pcm_stream_seek(pcm, SND_PCM_STREAM_PLAYBACK, frames1 * str->bits_per_frame / 8); + snd_pcm_stream_frame_data(pcm, SND_PCM_STREAM_PLAYBACK, frames1); frames -= frames1; offset += frames1; result += frames1; - if (ctrl->state == SND_PCM_STATE_PREPARED && + if (status->state == SND_PCM_STATE_PREPARED && (str->setup.start_mode == SND_PCM_START_DATA || (str->setup.start_mode == SND_PCM_START_FULL && !snd_pcm_mmap_playback_ready(pcm)))) { @@ -300,13 +257,13 @@ ssize_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channel return result; } -ssize_t snd_pcm_mmap_write_frames(snd_pcm_t *pcm, const void *buffer, size_t frames) +ssize_t snd_pcm_mmap_write(snd_pcm_t *pcm, const void *buffer, size_t frames) { snd_pcm_stream_t *str; unsigned int nchannels; assert(pcm); str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->mmap_data && str->mmap_control); + assert(str->mmap_data && str->mmap_status && str->mmap_control); assert(frames == 0 || buffer); nchannels = str->setup.format.channels; assert(str->setup.format.interleave || nchannels == 1); @@ -315,31 +272,13 @@ ssize_t snd_pcm_mmap_write_frames(snd_pcm_t *pcm, const void *buffer, size_t fra unsigned int channel; for (channel = 0; channel < nchannels; ++channel) { channels[channel].addr = (char*)buffer; - channels[channel].first = str->sample_width * channel; + channels[channel].first = str->bits_per_sample * channel; channels[channel].step = str->bits_per_frame; } return snd_pcm_mmap_write_areas(pcm, channels, frames); } } -ssize_t snd_pcm_mmap_write(snd_pcm_t *pcm, const void *buffer, size_t bytes) -{ - snd_pcm_stream_t *str; - unsigned int nchannels; - ssize_t frames; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->mmap_data && str->mmap_control); - assert(bytes == 0 || buffer); - nchannels = str->setup.format.channels; - assert(str->setup.format.interleave || nchannels == 1); - frames = bytes * 8 / str->bits_per_frame; - frames = snd_pcm_mmap_write_frames(pcm, buffer, frames); - if (frames <= 0) - return frames; - return frames * str->bits_per_frame / 8; -} - ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long vcount) { snd_pcm_stream_t *str; @@ -347,15 +286,15 @@ ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned unsigned int nchannels; assert(pcm); str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; - assert(str->mmap_data && str->mmap_control); + assert(str->mmap_data && str->mmap_status && str->mmap_control); assert(vcount == 0 || vector); nchannels = str->setup.format.channels; if (str->setup.format.interleave) { unsigned int b; for (b = 0; b < vcount; b++) { ssize_t ret; - size_t frames = vector[b].iov_len * 8 / str->bits_per_frame; - ret = snd_pcm_mmap_write_frames(pcm, vector[b].iov_base, frames); + size_t frames = vector[b].iov_len; + ret = snd_pcm_mmap_write(pcm, vector[b].iov_base, frames); if (ret < 0) { if (result <= 0) return ret; @@ -372,16 +311,13 @@ ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned for (b = 0; b < bcount; b++) { unsigned int v; ssize_t ret; - size_t bytes = 0; - size_t frames; - bytes = vector[0].iov_len; + size_t frames = vector[0].iov_len; for (v = 0; v < nchannels; ++v) { - assert(vector[v].iov_len == bytes); + assert(vector[v].iov_len == frames); channels[v].addr = vector[v].iov_base; channels[v].first = 0; - channels[v].step = str->sample_width; + channels[v].step = str->bits_per_sample; } - frames = bytes * 8 / str->sample_width; ret = snd_pcm_mmap_write_areas(pcm, channels, frames); if (ret < 0) { if (result <= 0) @@ -394,28 +330,29 @@ ssize_t snd_pcm_mmap_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned vector += nchannels; } } - return result * str->bits_per_frame / 8; + return result; } ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels, size_t frames) { snd_pcm_stream_t *str; - snd_pcm_mmap_control_t *ctrl; + snd_pcm_mmap_status_t *status; size_t offset = 0; size_t result = 0; int err; str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - ctrl = str->mmap_control; - assert(ctrl->state >= SND_PCM_STATE_PREPARED); + assert(str->mmap_data && str->mmap_status && str->mmap_control); + status = str->mmap_status; + assert(status->state >= SND_PCM_STATE_PREPARED); if (str->setup.mode == SND_PCM_MODE_FRAGMENT) { - assert(frames % str->frames_per_frag == 0); + assert(frames % str->setup.frag_size == 0); } else { - if (ctrl->state == SND_PCM_STATE_RUNNING && + if (status->state == SND_PCM_STATE_RUNNING && str->mode & SND_PCM_NONBLOCK) - snd_pcm_stream_byte_io(pcm, SND_PCM_STREAM_CAPTURE, 1); + snd_pcm_stream_frame_io(pcm, SND_PCM_STREAM_CAPTURE, 1); } - if (ctrl->state == SND_PCM_STATE_PREPARED && + if (status->state == SND_PCM_STATE_PREPARED && str->setup.start_mode == SND_PCM_START_DATA) { err = snd_pcm_stream_go(pcm, SND_PCM_STREAM_CAPTURE); if (err < 0) @@ -429,7 +366,7 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels return ready; if (!ready) { struct pollfd pfd; - if (ctrl->state != SND_PCM_STATE_RUNNING) + if (status->state != SND_PCM_STATE_RUNNING) return result > 0 ? result : -EPIPE; if (str->mode & SND_PCM_NONBLOCK) return result > 0 ? result : -EAGAIN; @@ -446,10 +383,10 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels assert(frames1 > 0); mmap_offset = snd_pcm_mmap_frames_offset(pcm, SND_PCM_STREAM_CAPTURE); snd_pcm_areas_copy(str->channels, mmap_offset, channels, offset, str->setup.format.channels, frames1, str->setup.format.format); - if (ctrl->state == SND_PCM_STATE_XRUN && + if (status->state == SND_PCM_STATE_XRUN && str->setup.xrun_mode == SND_PCM_XRUN_DRAIN) return result > 0 ? result : -EPIPE; - snd_pcm_stream_seek(pcm, SND_PCM_STREAM_CAPTURE, frames1 * str->bits_per_frame / 8); + snd_pcm_stream_frame_data(pcm, SND_PCM_STREAM_CAPTURE, frames1); frames -= frames1; offset += frames1; result += frames1; @@ -457,13 +394,13 @@ ssize_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, snd_pcm_channel_area_t *channels return result; } -ssize_t snd_pcm_mmap_read_frames(snd_pcm_t *pcm, const void *buffer, size_t frames) +ssize_t snd_pcm_mmap_read(snd_pcm_t *pcm, void *buffer, size_t frames) { snd_pcm_stream_t *str; unsigned int nchannels; assert(pcm); str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->mmap_data && str->mmap_control); + assert(str->mmap_data && str->mmap_status && str->mmap_control); assert(frames == 0 || buffer); nchannels = str->setup.format.channels; assert(str->setup.format.interleave || nchannels == 1); @@ -472,31 +409,13 @@ ssize_t snd_pcm_mmap_read_frames(snd_pcm_t *pcm, const void *buffer, size_t fram unsigned int channel; for (channel = 0; channel < nchannels; ++channel) { channels[channel].addr = (char*)buffer; - channels[channel].first = str->sample_width * channel; + channels[channel].first = str->bits_per_sample * channel; channels[channel].step = str->bits_per_frame; } return snd_pcm_mmap_read_areas(pcm, channels, frames); } } -ssize_t snd_pcm_mmap_read(snd_pcm_t *pcm, void *buffer, size_t bytes) -{ - snd_pcm_stream_t *str; - unsigned int nchannels; - ssize_t frames; - assert(pcm); - str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->mmap_data && str->mmap_control); - assert(bytes == 0 || buffer); - nchannels = str->setup.format.channels; - assert(str->setup.format.interleave || nchannels == 1); - frames = bytes * 8 / str->bits_per_frame; - frames = snd_pcm_mmap_read_frames(pcm, buffer, frames); - if (frames <= 0) - return frames; - return frames * str->bits_per_frame / 8; -} - ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long vcount) { snd_pcm_stream_t *str; @@ -504,15 +423,15 @@ ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned unsigned int nchannels; assert(pcm); str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; - assert(str->mmap_data && str->mmap_control); + assert(str->mmap_data && str->mmap_status && str->mmap_control); assert(vcount == 0 || vector); nchannels = str->setup.format.channels; if (str->setup.format.interleave) { unsigned int b; for (b = 0; b < vcount; b++) { ssize_t ret; - size_t frames = vector[b].iov_len * 8 / str->bits_per_frame; - ret = snd_pcm_mmap_read_frames(pcm, vector[b].iov_base, frames); + size_t frames = vector[b].iov_len; + ret = snd_pcm_mmap_read(pcm, vector[b].iov_base, frames); if (ret < 0) { if (result <= 0) return ret; @@ -529,16 +448,13 @@ ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned for (b = 0; b < bcount; b++) { unsigned int v; ssize_t ret; - size_t bytes = 0; - size_t frames; - bytes = vector[0].iov_len; + size_t frames = vector[0].iov_len; for (v = 0; v < nchannels; ++v) { - assert(vector[v].iov_len == bytes); + assert(vector[v].iov_len == frames); channels[v].addr = vector[v].iov_base; channels[v].first = 0; - channels[v].step = str->sample_width; + channels[v].step = str->bits_per_sample; } - frames = bytes * 8 / str->sample_width; ret = snd_pcm_mmap_read_areas(pcm, channels, frames); if (ret < 0) { if (result <= 0) @@ -551,13 +467,33 @@ ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned vector += nchannels; } } - return result * str->bits_per_frame / 8; + return result; +} + +int snd_pcm_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status) +{ + snd_pcm_stream_t *str; + int err; + assert(pcm); + assert(stream >= 0 && stream <= 1); + str = &pcm->stream[stream]; + assert(str->valid_setup); + if (str->mmap_status) { + if (status) + *status = str->mmap_status; + return 0; + } + + if ((err = pcm->ops->mmap_status(pcm, stream, &str->mmap_status)) < 0) + return err; + if (status) + *status = str->mmap_status; + return 0; } int snd_pcm_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control) { snd_pcm_stream_t *str; - size_t csize; int err; assert(pcm); assert(stream >= 0 && stream <= 1); @@ -568,13 +504,11 @@ int snd_pcm_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **co *control = str->mmap_control; return 0; } - csize = sizeof(snd_pcm_mmap_control_t); - if ((err = pcm->ops->mmap_control(pcm, stream, &str->mmap_control, csize)) < 0) + if ((err = pcm->ops->mmap_control(pcm, stream, &str->mmap_control)) < 0) return err; if (control) *control = str->mmap_control; - str->mmap_control_size = csize; return 0; } @@ -601,11 +535,11 @@ int snd_pcm_mmap_get_areas(snd_pcm_t *pcm, int stream, snd_pcm_channel_area_t *a if (areas) areas[channel] = s.area; *ap = s.area; - if (ap->step != str->sample_width || ap->first != 0) + if (ap->step != str->bits_per_sample || ap->first != 0) noninterleaved = 0; if (ap->addr != a[0].addr || ap->step != str->bits_per_frame || - ap->first != channel * str->sample_width) + ap->first != channel * str->bits_per_sample) interleaved = 0; } if (noninterleaved) @@ -652,20 +586,40 @@ int snd_pcm_mmap_data(snd_pcm_t *pcm, int stream, void **data) return 0; } -int snd_pcm_mmap(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control, void **data) +int snd_pcm_mmap(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status, snd_pcm_mmap_control_t **control, void **data) { int err; - err = snd_pcm_mmap_control(pcm, stream, control); + err = snd_pcm_mmap_status(pcm, stream, status); if (err < 0) return err; + err = snd_pcm_mmap_control(pcm, stream, control); + if (err < 0) { + snd_pcm_munmap_status(pcm, stream); + return err; + } err = snd_pcm_mmap_data(pcm, stream, data); if (err < 0) { + snd_pcm_munmap_status(pcm, stream); snd_pcm_munmap_control(pcm, stream); return err; } return 0; } +int snd_pcm_munmap_status(snd_pcm_t *pcm, int stream) +{ + int err; + snd_pcm_stream_t *str; + assert(pcm); + assert(stream >= 0 && stream <= 1); + str = &pcm->stream[stream]; + assert(str->mmap_status); + if ((err = pcm->ops->munmap_status(pcm, stream, str->mmap_status)) < 0) + return err; + str->mmap_status = 0; + return 0; +} + int snd_pcm_munmap_control(snd_pcm_t *pcm, int stream) { int err; @@ -674,10 +628,9 @@ int snd_pcm_munmap_control(snd_pcm_t *pcm, int stream) assert(stream >= 0 && stream <= 1); str = &pcm->stream[stream]; assert(str->mmap_control); - if ((err = pcm->ops->munmap_control(pcm, stream, str->mmap_control, str->mmap_control_size)) < 0) + if ((err = pcm->ops->munmap_control(pcm, stream, str->mmap_control)) < 0) return err; str->mmap_control = 0; - str->mmap_control_size = 0; return 0; } @@ -700,6 +653,9 @@ int snd_pcm_munmap_data(snd_pcm_t *pcm, int stream) int snd_pcm_munmap(snd_pcm_t *pcm, int stream) { int err; + err = snd_pcm_munmap_status(pcm, stream); + if (err < 0) + return err; err = snd_pcm_munmap_control(pcm, stream); if (err < 0) return err; diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index ff60f9c2..8ff03b3c 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -334,8 +334,6 @@ static int snd_pcm_plug_stream_params(snd_pcm_t *pcm, snd_pcm_stream_params_t *p snd_pcm_stream_info_t slave_info; snd_pcm_plugin_t *plugin; snd_pcm_plug_t *plug; - size_t bits; - size_t bytes_align; int err; int stream = params->stream; @@ -367,29 +365,19 @@ static int snd_pcm_plug_stream_params(snd_pcm_t *pcm, snd_pcm_stream_params_t *p return snd_pcm_stream_params(plug->slave, params); /* compute right sizes */ - bits = snd_pcm_format_physical_width(params->format.format) * params->format.channels; - while (bits % 8 != 0) - bits *= 2; - bytes_align = bits / 8; - params1.frag_size -= params1.frag_size % bytes_align; slave_params.frag_size = snd_pcm_plug_slave_size(pcm, stream, params1.frag_size); - params1.buffer_size -= params1.buffer_size % bytes_align; slave_params.buffer_size = snd_pcm_plug_slave_size(pcm, stream, params1.buffer_size); - params1.bytes_fill_max -= params1.bytes_fill_max % bytes_align; - slave_params.bytes_fill_max = snd_pcm_plug_slave_size(pcm, stream, params1.bytes_fill_max); - params1.bytes_min -= params1.bytes_min % bytes_align; - slave_params.bytes_min = snd_pcm_plug_slave_size(pcm, stream, params1.bytes_min); - params1.bytes_xrun_max -= params1.bytes_xrun_max % bytes_align; - slave_params.bytes_xrun_max = snd_pcm_plug_slave_size(pcm, stream, params1.bytes_xrun_max); - params1.bytes_align -= params1.bytes_align % bytes_align; - slave_params.bytes_align = snd_pcm_plug_slave_size(pcm, stream, params1.bytes_align); - if (slave_params.byte_boundary == 0 || slave_params.byte_boundary > INT_MAX) - slave_params.byte_boundary = INT_MAX; - slave_params.byte_boundary /= params->buffer_size; - if (slave_params.byte_boundary > INT_MAX / slave_params.buffer_size) - slave_params.byte_boundary = INT_MAX; + slave_params.frames_fill_max = snd_pcm_plug_slave_size(pcm, stream, params1.frames_fill_max); + slave_params.frames_min = snd_pcm_plug_slave_size(pcm, stream, params1.frames_min); + slave_params.frames_xrun_max = snd_pcm_plug_slave_size(pcm, stream, params1.frames_xrun_max); + slave_params.frames_align = snd_pcm_plug_slave_size(pcm, stream, params1.frames_align); + if (slave_params.frame_boundary == 0 || slave_params.frame_boundary > INT_MAX) + slave_params.frame_boundary = INT_MAX; + slave_params.frame_boundary /= params->buffer_size; + if (slave_params.frame_boundary > INT_MAX / slave_params.buffer_size) + slave_params.frame_boundary = INT_MAX; else - slave_params.byte_boundary *= slave_params.buffer_size; + slave_params.frame_boundary *= slave_params.buffer_size; /* * I/O plugins @@ -436,14 +424,14 @@ static int snd_pcm_plug_stream_setup(snd_pcm_t *pcm, snd_pcm_stream_setup_t *set return err; if (snd_pcm_plug_direct(pcm, setup->stream)) return 0; - setup->byte_boundary /= setup->frag_size; + setup->frame_boundary /= setup->frag_size; setup->frag_size = snd_pcm_plug_client_size(pcm, setup->stream, setup->frag_size); - setup->byte_boundary *= setup->frag_size; + setup->frame_boundary *= setup->frag_size; setup->buffer_size = setup->frags * setup->frag_size; - setup->bytes_min = snd_pcm_plug_client_size(pcm, setup->stream, setup->bytes_min); - setup->bytes_align = snd_pcm_plug_client_size(pcm, setup->stream, setup->bytes_align); - setup->bytes_xrun_max = snd_pcm_plug_client_size(pcm, setup->stream, setup->bytes_xrun_max); - setup->bytes_fill_max = snd_pcm_plug_client_size(pcm, setup->stream, setup->bytes_fill_max); + setup->frames_min = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_min); + setup->frames_align = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_align); + setup->frames_xrun_max = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_xrun_max); + setup->frames_fill_max = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_fill_max); plugstr = &plug->stream[setup->stream]; if (setup->stream == SND_PCM_STREAM_PLAYBACK) @@ -464,10 +452,10 @@ static int snd_pcm_plug_stream_status(snd_pcm_t *pcm, snd_pcm_stream_status_t *s if (snd_pcm_plug_direct(pcm, status->stream)) return 0; - status->byte_io = snd_pcm_plug_client_size(pcm, status->stream, status->byte_io); - status->byte_data = snd_pcm_plug_client_size(pcm, status->stream, status->byte_data); - status->bytes_avail = snd_pcm_plug_client_size(pcm, status->stream, status->bytes_avail); - status->bytes_avail_max = snd_pcm_plug_client_size(pcm, status->stream, status->bytes_avail_max); + status->frame_io = snd_pcm_plug_client_size(pcm, status->stream, status->frame_io); + status->frame_data = snd_pcm_plug_client_size(pcm, status->stream, status->frame_data); + status->frames_avail = snd_pcm_plug_client_size(pcm, status->stream, status->frames_avail); + status->frames_avail_max = snd_pcm_plug_client_size(pcm, status->stream, status->frames_avail_max); return 0; } @@ -477,10 +465,10 @@ static int snd_pcm_plug_stream_state(snd_pcm_t *pcm, int stream) return snd_pcm_stream_state(plug->slave, stream); } -static int snd_pcm_plug_stream_byte_io(snd_pcm_t *pcm, int stream, int update) +static int snd_pcm_plug_stream_frame_io(snd_pcm_t *pcm, int stream, int update) { snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_stream_byte_io(plug->slave, stream, update); + return snd_pcm_stream_frame_io(plug->slave, stream, update); } static int snd_pcm_plug_stream_prepare(snd_pcm_t *pcm, int stream) @@ -559,12 +547,12 @@ static int snd_pcm_plug_channel_setup(snd_pcm_t *pcm, int stream, snd_pcm_channe return -ENXIO; } -static ssize_t snd_pcm_plug_stream_seek(snd_pcm_t *pcm, int stream, off_t offset) +static ssize_t snd_pcm_plug_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) { ssize_t ret; snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_stream_seek(plug->slave, stream, offset); + return snd_pcm_stream_frame_data(plug->slave, stream, offset); if (offset < 0) { offset = snd_pcm_plug_slave_size(pcm, stream, -offset); if (offset < 0) @@ -575,7 +563,7 @@ static ssize_t snd_pcm_plug_stream_seek(snd_pcm_t *pcm, int stream, off_t offset if (offset < 0) return offset; } - ret = snd_pcm_stream_seek(plug->slave, stream, offset); + ret = snd_pcm_stream_frame_data(plug->slave, stream, offset); if (ret < 0) return ret; return snd_pcm_plug_client_size(pcm, stream, ret); @@ -677,7 +665,15 @@ ssize_t snd_pcm_plug_read(snd_pcm_t *pcm, void *buf, size_t count) return snd_pcm_plug_read_transfer(pcm, channels, expected); } -static int snd_pcm_plug_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control, size_t csize UNUSED) +static int snd_pcm_plug_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status) +{ + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + if (snd_pcm_plug_direct(pcm, stream)) + return snd_pcm_mmap_status(plug->slave, stream, status); + return -EBADFD; +} + +static int snd_pcm_plug_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control) { snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; if (snd_pcm_plug_direct(pcm, stream)) @@ -693,7 +689,15 @@ static int snd_pcm_plug_mmap_data(snd_pcm_t *pcm, int stream, void **buffer, siz return -EBADFD; } -static int snd_pcm_plug_munmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t *control UNUSED, size_t csize UNUSED) +static int snd_pcm_plug_munmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t *status UNUSED) +{ + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + if (snd_pcm_plug_direct(pcm, stream)) + return snd_pcm_munmap_status(plug->slave, stream); + return -EBADFD; +} + +static int snd_pcm_plug_munmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t *control UNUSED) { snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; if (snd_pcm_plug_direct(pcm, stream)) @@ -736,7 +740,7 @@ struct snd_pcm_ops snd_pcm_plug_ops = { stream_setup: snd_pcm_plug_stream_setup, channel_setup: snd_pcm_plug_channel_setup, stream_status: snd_pcm_plug_stream_status, - stream_byte_io: snd_pcm_plug_stream_byte_io, + stream_frame_io: snd_pcm_plug_stream_frame_io, stream_state: snd_pcm_plug_stream_state, stream_prepare: snd_pcm_plug_stream_prepare, stream_go: snd_pcm_plug_stream_go, @@ -744,13 +748,15 @@ struct snd_pcm_ops snd_pcm_plug_ops = { stream_drain: snd_pcm_plug_stream_drain, stream_flush: snd_pcm_plug_stream_flush, stream_pause: snd_pcm_plug_stream_pause, - stream_seek: snd_pcm_plug_stream_seek, + stream_frame_data: snd_pcm_plug_stream_frame_data, write: snd_pcm_plug_write, writev: snd_pcm_plug_writev, read: snd_pcm_plug_read, readv: snd_pcm_plug_readv, + mmap_status: snd_pcm_plug_mmap_status, mmap_control: snd_pcm_plug_mmap_control, mmap_data: snd_pcm_plug_mmap_data, + munmap_status: snd_pcm_plug_munmap_status, munmap_control: snd_pcm_plug_munmap_control, munmap_data: snd_pcm_plug_munmap_data, file_descriptor: snd_pcm_plug_file_descriptor, diff --git a/src/pcm/plugin/io.c b/src/pcm/plugin/io.c index afdd5732..d7c7e4b8 100644 --- a/src/pcm/plugin/io.c +++ b/src/pcm/plugin/io.c @@ -51,7 +51,6 @@ static ssize_t io_transfer(snd_pcm_plugin_t *plugin, size_t frames) { io_t *data; - ssize_t result; struct iovec *vec; int count, channel; @@ -61,50 +60,38 @@ static ssize_t io_transfer(snd_pcm_plugin_t *plugin, vec = (struct iovec *)((char *)data + sizeof(*data)); if (plugin->stream == SND_PCM_STREAM_PLAYBACK) { assert(src_channels); - if ((result = snd_pcm_plugin_src_frames_to_size(plugin, frames)) < 0) - return result; count = plugin->src_format.channels; if (plugin->src_format.interleave) { - result = snd_pcm_write(data->slave, src_channels->area.addr, result); + return snd_pcm_write(data->slave, src_channels->area.addr, frames); } else { - result /= count; for (channel = 0; channel < count; channel++) { if (src_channels[channel].enabled) vec[channel].iov_base = src_channels[channel].area.addr; else vec[channel].iov_base = 0; - vec[channel].iov_len = result; + vec[channel].iov_len = frames; } - result = snd_pcm_writev(data->slave, vec, count); + return snd_pcm_writev(data->slave, vec, count); } - if (result < 0) - return result; - return snd_pcm_plugin_src_size_to_frames(plugin, result); } else if (plugin->stream == SND_PCM_STREAM_CAPTURE) { assert(dst_channels); - if ((result = snd_pcm_plugin_dst_frames_to_size(plugin, frames)) < 0) - return result; count = plugin->dst_format.channels; if (plugin->dst_format.interleave) { - result = snd_pcm_read(data->slave, dst_channels->area.addr, result); for (channel = 0; channel < count; channel++) { dst_channels[channel].enabled = src_channels[channel].enabled; } + return snd_pcm_read(data->slave, dst_channels->area.addr, frames); } else { - result /= count; for (channel = 0; channel < count; channel++) { dst_channels[channel].enabled = src_channels[channel].enabled; if (dst_channels[channel].enabled) vec[channel].iov_base = dst_channels[channel].area.addr; else vec[channel].iov_base = 0; - vec[channel].iov_len = result; + vec[channel].iov_len = frames; } - result = snd_pcm_readv(data->slave, vec, count); + return snd_pcm_readv(data->slave, vec, count); } - if (result < 0) - return result; - return snd_pcm_plugin_dst_size_to_frames(plugin, result); } else { assert(0); } diff --git a/src/pcm/plugin/mmap.c b/src/pcm/plugin/mmap.c index 4db2b665..2f46bd9b 100644 --- a/src/pcm/plugin/mmap.c +++ b/src/pcm/plugin/mmap.c @@ -35,7 +35,6 @@ typedef struct mmap_private_data { snd_pcm_t *slave; - snd_pcm_mmap_control_t *control; void *buffer; #if 0 char *silence; @@ -52,18 +51,16 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin, snd_pcm_channel_area_t *dv; snd_pcm_stream_t *stream; snd_pcm_stream_setup_t *setup; - snd_pcm_mmap_control_t *ctrl; size_t pos; int ready; unsigned int channel; assert(plugin && channels); data = (mmap_t *)plugin->extra_data; - ctrl = data->control; stream = &data->slave->stream[plugin->stream]; setup = &stream->setup; - if (ctrl->state < SND_PCM_STATE_PREPARED) + if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) < SND_PCM_STATE_PREPARED) return -EBADFD; ready = snd_pcm_mmap_ready(data->slave, plugin->stream); @@ -71,7 +68,7 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin, return ready; if (!ready) { struct pollfd pfd; - if (ctrl->state != SND_PCM_STATE_RUNNING) + if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) != SND_PCM_STATE_RUNNING) return -EPIPE; if (stream->mode & SND_PCM_NONBLOCK) return -EAGAIN; @@ -84,9 +81,8 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin, return -EPIPE; assert(snd_pcm_mmap_ready(data->slave, plugin->stream)); } - pos = ctrl->byte_data % setup->buffer_size; - assert(pos % setup->bytes_align == 0); - pos = (pos * 8) / stream->bits_per_frame; + pos = snd_pcm_mmap_frames_offset(data->slave, plugin->stream); + assert(pos % setup->frames_align == 0); sv = plugin->src_channels; dv = stream->channels; @@ -119,7 +115,6 @@ static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin, snd_pcm_channel_area_t *sv; snd_pcm_stream_t *stream; snd_pcm_stream_setup_t *setup; - snd_pcm_mmap_control_t *ctrl; size_t pos; int ready; @@ -128,10 +123,9 @@ static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin, stream = &data->slave->stream[plugin->stream]; setup = &stream->setup; - ctrl = data->control; - if (ctrl->state < SND_PCM_STATE_PREPARED) + if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) < SND_PCM_STATE_PREPARED) return -EBADFD; - if (ctrl->state == SND_PCM_STATE_PREPARED && + if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) == SND_PCM_STATE_PREPARED && stream->setup.start_mode == SND_PCM_START_DATA) { err = snd_pcm_stream_go(data->slave, plugin->stream); if (err < 0) @@ -142,7 +136,7 @@ static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin, return ready; if (!ready) { struct pollfd pfd; - if (ctrl->state != SND_PCM_STATE_RUNNING) + if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) != SND_PCM_STATE_RUNNING) return -EPIPE; if (stream->mode & SND_PCM_NONBLOCK) return -EAGAIN; @@ -155,9 +149,8 @@ static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin, return -EPIPE; assert(snd_pcm_mmap_ready(data->slave, plugin->stream)); } - pos = ctrl->byte_data % setup->buffer_size; - assert(pos % setup->bytes_align == 0); - pos = (pos * 8) / stream->bits_per_frame; + pos = snd_pcm_mmap_frames_offset(data->slave, plugin->stream); + assert(pos % setup->frames_align == 0); sv = stream->channels; dv = plugin->dst_channels; @@ -182,15 +175,12 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, { mmap_t *data; snd_pcm_stream_setup_t *setup; - snd_pcm_mmap_control_t *ctrl; snd_pcm_stream_t *str; int err; assert(plugin && plugin->prev); assert(src_channels); data = (mmap_t *)plugin->extra_data; - ctrl = data->control; - assert(ctrl); str = &data->slave->stream[SND_PCM_STREAM_PLAYBACK]; setup = &str->setup; @@ -201,8 +191,8 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, } #endif - snd_pcm_stream_seek(data->slave, SND_PCM_STREAM_PLAYBACK, frames * str->bits_per_frame / 8); - if (ctrl->state == SND_PCM_STATE_PREPARED && + snd_pcm_mmap_stream_frame_data(data->slave, SND_PCM_STREAM_PLAYBACK, frames); + if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) == SND_PCM_STATE_PREPARED && (str->setup.start_mode == SND_PCM_START_DATA || (str->setup.start_mode == SND_PCM_START_FULL && !snd_pcm_mmap_ready(data->slave, plugin->stream)))) { @@ -219,17 +209,14 @@ static ssize_t mmap_capture_transfer(snd_pcm_plugin_t *plugin, size_t frames) { mmap_t *data; - snd_pcm_mmap_control_t *ctrl; snd_pcm_stream_t *str; assert(plugin && plugin->next); data = (mmap_t *)plugin->extra_data; - ctrl = data->control; - assert(ctrl); str = &data->slave->stream[SND_PCM_STREAM_CAPTURE]; /* FIXME: not here the increment */ - snd_pcm_stream_seek(data->slave, SND_PCM_STREAM_CAPTURE, frames * str->bits_per_frame / 8); + snd_pcm_mmap_stream_frame_data(data->slave, SND_PCM_STREAM_CAPTURE, frames); return frames; } @@ -246,9 +233,11 @@ static int mmap_action(snd_pcm_plugin_t *plugin, snd_pcm_stream_setup_t *setup; int result; - if (data->control) + if (data->buffer) { snd_pcm_munmap(data->slave, plugin->stream); - result = snd_pcm_mmap(data->slave, plugin->stream, &data->control, (void **)&data->buffer); + data->buffer = 0; + } + result = snd_pcm_mmap(data->slave, plugin->stream, NULL, NULL, (void **)&data->buffer); if (result < 0) return result; setup = &data->slave->stream[plugin->stream].setup; @@ -276,7 +265,7 @@ static void mmap_free(snd_pcm_plugin_t *plugin, void *private_data UNUSED) if (data->silence) free(data->silence); #endif - if (data->control) + if (data->buffer) snd_pcm_munmap(data->slave, plugin->stream); } diff --git a/src/pcm/plugin/plugin_ops.h b/src/pcm/plugin/plugin_ops.h index e97178df..ed91a2c1 100644 --- a/src/pcm/plugin/plugin_ops.h +++ b/src/pcm/plugin/plugin_ops.h @@ -304,8 +304,8 @@ static void *get_s16_labels[4 * 2 * 2] = { #ifdef GET_S16_END while(0) { -get_s16_xxx1_xx10: sample = (u_int32_t)as_u8(src) << 8; goto GET_S16_END; -get_s16_xxx1_xx90: sample = (u_int32_t)(as_u8(src) ^ 0x80) << 8; goto GET_S16_END; +get_s16_xxx1_xx10: sample = (u_int16_t)as_u8(src) << 8; goto GET_S16_END; +get_s16_xxx1_xx90: sample = (u_int16_t)(as_u8(src) ^ 0x80) << 8; goto GET_S16_END; get_s16_xx12_xx12: sample = as_u16(src); goto GET_S16_END; get_s16_xx12_xx92: sample = as_u16(src) ^ 0x8000; goto GET_S16_END; get_s16_xx12_xx21: sample = bswap_16(as_u16(src)); goto GET_S16_END; -- 2.47.1