mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-28 05:40:23 -04:00
Changed ALSA unit from bytes to frames. Splitted mmap control structs. Better midlevel interrupt handler
This commit is contained in:
parent
bbdff9fce5
commit
e8cac7de4d
13 changed files with 405 additions and 571 deletions
1
TODO
1
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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
109
src/pcm/pcm.c
109
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(control, csize) < 0)
|
||||
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, 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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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] = {
|
||||
|
|
|
|||
|
|
@ -25,31 +25,17 @@
|
|||
#include <sys/uio.h>
|
||||
#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,13 +122,11 @@ 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;
|
||||
assert(str->mmap_control);
|
||||
return str->mmap_control->frame_data % str->setup.buffer_size;
|
||||
}
|
||||
|
||||
int snd_pcm_mmap_stream_state(snd_pcm_t *pcm, int stream)
|
||||
|
|
@ -169,45 +135,35 @@ int snd_pcm_mmap_stream_state(snd_pcm_t *pcm, int stream)
|
|||
assert(pcm);
|
||||
assert(stream >= 0 && stream <= 1);
|
||||
str = &pcm->stream[stream];
|
||||
assert(str->mmap_control);
|
||||
return str->mmap_control->state;
|
||||
assert(str->mmap_status);
|
||||
return str->mmap_status->state;
|
||||
}
|
||||
|
||||
int snd_pcm_mmap_stream_byte_io(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_io;
|
||||
assert(str->mmap_status);
|
||||
return str->mmap_status->frame_io;
|
||||
}
|
||||
|
||||
int snd_pcm_mmap_stream_byte_data(snd_pcm_t *pcm, int stream)
|
||||
ssize_t snd_pcm_mmap_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset)
|
||||
{
|
||||
snd_pcm_stream_t *str;
|
||||
ssize_t frame_data;
|
||||
assert(pcm);
|
||||
assert(stream >= 0 && stream <= 1);
|
||||
str = &pcm->stream[stream];
|
||||
assert(str->mmap_control);
|
||||
return str->mmap_control->byte_data;
|
||||
}
|
||||
|
||||
ssize_t snd_pcm_mmap_stream_seek(snd_pcm_t *pcm, int stream, off_t offset)
|
||||
{
|
||||
snd_pcm_stream_t *str;
|
||||
ssize_t byte_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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue