From: Abramo Bagnara Date: Tue, 23 May 2000 12:52:06 +0000 (+0000) Subject: Removed frag_* fields. Collapsed I/O plugins. Added to mmap plugin support for stream... X-Git-Tag: v1.0.3~1259 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=c582ff51b68bd1d18263b5694c90c36cd830298e;p=alsa-lib.git Removed frag_* fields. Collapsed I/O plugins. Added to mmap plugin support for stream mode --- diff --git a/include/pcm.h b/include/pcm.h index a4f685e7..30eab3aa 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -213,9 +213,9 @@ struct snd_stru_pcm_plugin { int dst_width; /* sample width in bits */ ssize_t (*src_samples)(snd_pcm_plugin_t *plugin, size_t dst_samples); ssize_t (*dst_samples)(snd_pcm_plugin_t *plugin, size_t src_samples); - int (*client_voices)(snd_pcm_plugin_t *plugin, - size_t samples, - snd_pcm_plugin_voice_t **voices); + ssize_t (*client_voices)(snd_pcm_plugin_t *plugin, + size_t samples, + snd_pcm_plugin_voice_t **voices); int (*src_voices_mask)(snd_pcm_plugin_t *plugin, bitset_t *dst_vmask, bitset_t **src_vmask); @@ -288,16 +288,11 @@ int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle, int extra, snd_pcm_plugin_t **ret); /* basic I/O */ -int snd_pcm_plugin_build_stream(snd_pcm_plugin_handle_t *handle, - int channel, - snd_pcm_t *slave, - snd_pcm_format_t *format, - snd_pcm_plugin_t **r_plugin); -int snd_pcm_plugin_build_block(snd_pcm_plugin_handle_t *handle, - int channel, - snd_pcm_t *slave, - snd_pcm_format_t *format, - snd_pcm_plugin_t **r_plugin); +int snd_pcm_plugin_build_io(snd_pcm_plugin_handle_t *handle, + int channel, + snd_pcm_t *slave, + snd_pcm_format_t *format, + snd_pcm_plugin_t **r_plugin); int snd_pcm_plugin_build_mmap(snd_pcm_plugin_handle_t *handle, int channel, snd_pcm_t *slave, diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index c014bc2c..6e0cb42b 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -269,7 +269,7 @@ static int mmap_playback_go(snd_pcm_t *pcm, int channel) struct snd_pcm_chan *chan = &pcm->chan[channel]; if (chan->mmap_control->status != SND_PCM_STATUS_PREPARED) return -EBADFD; - if (chan->mmap_control->frag_data == 0) + if (chan->mmap_control->byte_data == 0) return -EIO; chan->mmap_control->status = SND_PCM_STATUS_RUNNING; pthread_mutex_lock(&chan->mutex); diff --git a/src/pcm/pcm_common.c b/src/pcm/pcm_common.c index 6640cb7e..95b57ffe 100644 --- a/src/pcm/pcm_common.c +++ b/src/pcm/pcm_common.c @@ -57,10 +57,10 @@ static int snd_pcm_plugin_dst_voices_mask(snd_pcm_plugin_t *plugin, return 0; } -static int snd_pcm_plugin_side_voices(snd_pcm_plugin_t *plugin, - int client_side, - size_t samples, - snd_pcm_plugin_voice_t **voices) +static ssize_t snd_pcm_plugin_side_voices(snd_pcm_plugin_t *plugin, + int client_side, + size_t samples, + snd_pcm_plugin_voice_t **voices) { char *ptr; int width; @@ -104,19 +104,19 @@ static int snd_pcm_plugin_side_voices(snd_pcm_plugin_t *plugin, v->area.step = width; } } - return 0; + return samples; } -int snd_pcm_plugin_client_voices(snd_pcm_plugin_t *plugin, - size_t samples, - snd_pcm_plugin_voice_t **voices) +ssize_t snd_pcm_plugin_client_voices(snd_pcm_plugin_t *plugin, + size_t samples, + snd_pcm_plugin_voice_t **voices) { return snd_pcm_plugin_side_voices(plugin, 1, samples, voices); } -int snd_pcm_plugin_slave_voices(snd_pcm_plugin_t *plugin, - size_t samples, - snd_pcm_plugin_voice_t **voices) +ssize_t snd_pcm_plugin_slave_voices(snd_pcm_plugin_t *plugin, + size_t samples, + snd_pcm_plugin_voice_t **voices) { return snd_pcm_plugin_side_voices(plugin, 0, samples, voices); } @@ -1073,6 +1073,11 @@ ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plu snd_pcm_plug_buf_unlock(handle, SND_PCM_CHANNEL_PLAYBACK, src_voices->aptr); return err; } + if (err != samples1) { + samples = err; + if (plugin->src_samples) + samples = plugin->src_samples(plugin, samples1); + } } else { if ((err = snd_pcm_plugin_slave_voices(plugin, samples, &dst_voices)) < 0) return err; @@ -1121,6 +1126,7 @@ ssize_t snd_pcm_plug_read_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plug snd_pcm_plug_buf_unlock(handle, SND_PCM_CHANNEL_CAPTURE, src_voices->aptr); return err; } + samples = err; } else { dst_voices = dst_voices_final; } diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index cdef4a92..e720d58a 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -29,8 +29,6 @@ static void snd_pcm_mmap_clear(snd_pcm_t *pcm, int channel) { struct snd_pcm_chan *chan = &pcm->chan[channel]; - chan->mmap_control->frag_io = 0; - chan->mmap_control->frag_data = 0; chan->mmap_control->byte_io = 0; chan->mmap_control->byte_data = 0; } @@ -61,15 +59,6 @@ void snd_pcm_mmap_status_change(snd_pcm_t *pcm, int channel, int newstatus) } } -static inline ssize_t snd_pcm_mmap_playback_frags_used(struct snd_pcm_chan *chan) -{ - ssize_t frags_used; - frags_used = chan->mmap_control->frag_data - chan->mmap_control->frag_io; - if (frags_used < (ssize_t)(chan->setup.frags - chan->setup.frag_boundary)) - frags_used += chan->setup.frag_boundary; - return frags_used; -} - static inline ssize_t snd_pcm_mmap_playback_bytes_used(struct snd_pcm_chan *chan) { ssize_t bytes_used; @@ -81,24 +70,9 @@ static inline ssize_t snd_pcm_mmap_playback_bytes_used(struct snd_pcm_chan *chan static ssize_t snd_pcm_mmap_playback_samples_used(snd_pcm_t *pcm) { - struct snd_pcm_chan *chan; - chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - ssize_t frags = snd_pcm_mmap_playback_frags_used(chan); - return frags * chan->samples_per_frag; - } else { - ssize_t bytes = snd_pcm_mmap_playback_bytes_used(chan); - return bytes * 8 / chan->bits_per_sample; - } -} - -static inline size_t snd_pcm_mmap_capture_frags_used(struct snd_pcm_chan *chan) -{ - ssize_t frags_used; - frags_used = chan->mmap_control->frag_io - chan->mmap_control->frag_data; - if (frags_used < 0) - frags_used += chan->setup.frag_boundary; - return frags_used; + struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; + ssize_t bytes = snd_pcm_mmap_playback_bytes_used(chan); + return bytes * 8 / chan->bits_per_sample; } static inline size_t snd_pcm_mmap_capture_bytes_used(struct snd_pcm_chan *chan) @@ -112,15 +86,9 @@ static inline size_t snd_pcm_mmap_capture_bytes_used(struct snd_pcm_chan *chan) static size_t snd_pcm_mmap_capture_samples_used(snd_pcm_t *pcm) { - struct snd_pcm_chan *chan; - chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - size_t frags = snd_pcm_mmap_capture_frags_used(chan); - return frags * chan->samples_per_frag; - } else { - size_t bytes = snd_pcm_mmap_capture_bytes_used(chan); - return bytes * 8 / chan->bits_per_sample; - } + struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; + size_t bytes = snd_pcm_mmap_capture_bytes_used(chan); + return bytes * 8 / chan->bits_per_sample; } int snd_pcm_mmap_samples_used(snd_pcm_t *pcm, int channel, ssize_t *samples) @@ -140,11 +108,6 @@ int snd_pcm_mmap_samples_used(snd_pcm_t *pcm, int channel, ssize_t *samples) return 0; } -static inline size_t snd_pcm_mmap_playback_frags_free(struct snd_pcm_chan *chan) -{ - return chan->setup.frags - snd_pcm_mmap_playback_frags_used(chan); -} - static inline size_t snd_pcm_mmap_playback_bytes_free(struct snd_pcm_chan *chan) { return chan->setup.buffer_size - snd_pcm_mmap_playback_bytes_used(chan); @@ -152,23 +115,11 @@ static inline size_t snd_pcm_mmap_playback_bytes_free(struct snd_pcm_chan *chan) static size_t snd_pcm_mmap_playback_samples_free(snd_pcm_t *pcm) { - struct snd_pcm_chan *chan; - chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - size_t frags = snd_pcm_mmap_playback_frags_free(chan); - return frags * chan->samples_per_frag; - } else { - size_t bytes = snd_pcm_mmap_playback_bytes_free(chan); - return bytes * 8 / chan->bits_per_sample; - } -} - -static inline ssize_t snd_pcm_mmap_capture_frags_free(struct snd_pcm_chan *chan) -{ - return chan->setup.frags - snd_pcm_mmap_capture_frags_used(chan); + struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; + size_t bytes = snd_pcm_mmap_playback_bytes_free(chan); + return bytes * 8 / chan->bits_per_sample; } - static inline ssize_t snd_pcm_mmap_capture_bytes_free(struct snd_pcm_chan *chan) { return chan->setup.buffer_size - snd_pcm_mmap_capture_bytes_used(chan); @@ -176,15 +127,9 @@ static inline ssize_t snd_pcm_mmap_capture_bytes_free(struct snd_pcm_chan *chan) static ssize_t snd_pcm_mmap_capture_samples_free(snd_pcm_t *pcm) { - struct snd_pcm_chan *chan; - chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - ssize_t frags = snd_pcm_mmap_capture_frags_free(chan); - return frags * chan->samples_per_frag; - } else { - ssize_t bytes = snd_pcm_mmap_capture_bytes_free(chan); - return bytes * 8 / chan->bits_per_sample; - } + struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; + ssize_t bytes = snd_pcm_mmap_capture_bytes_free(chan); + return bytes * 8 / chan->bits_per_sample; } int snd_pcm_mmap_samples_free(snd_pcm_t *pcm, int channel, ssize_t *samples) @@ -210,11 +155,7 @@ static int snd_pcm_mmap_playback_ready(snd_pcm_t *pcm) chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; if (chan->mmap_control->status == SND_PCM_STATUS_XRUN) return -EPIPE; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - return (chan->setup.frags - snd_pcm_mmap_playback_frags_used(chan)) >= chan->setup.buf.block.frags_min; - } else { - return (chan->setup.buffer_size - snd_pcm_mmap_playback_bytes_used(chan)) >= chan->setup.buf.stream.bytes_min; - } + return (chan->setup.buffer_size - snd_pcm_mmap_playback_bytes_used(chan)) >= chan->setup.bytes_min; } static int snd_pcm_mmap_capture_ready(snd_pcm_t *pcm) @@ -227,13 +168,8 @@ static int snd_pcm_mmap_capture_ready(snd_pcm_t *pcm) if (chan->setup.xrun_mode == SND_PCM_XRUN_DRAIN) return -EPIPE; } - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - if (snd_pcm_mmap_capture_frags_used(chan) >= chan->setup.buf.block.frags_min) - return 1; - } else { - if (snd_pcm_mmap_capture_bytes_used(chan) >= chan->setup.buf.stream.bytes_min) - return 1; - } + if (snd_pcm_mmap_capture_bytes_used(chan) >= chan->setup.bytes_min) + return 1; return ret; } @@ -258,36 +194,6 @@ int snd_pcm_mmap_ready(snd_pcm_t *pcm, int channel) } } -static size_t snd_pcm_mmap_playback_frags_xfer(snd_pcm_t *pcm, size_t frags) -{ - struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; - snd_pcm_mmap_control_t *ctrl = chan->mmap_control; - size_t frags_cont; - size_t frag_data = ctrl->frag_data; - size_t frags_free = snd_pcm_mmap_playback_frags_free(chan); - if (frags_free < frags) - frags = frags_free; - frags_cont = chan->setup.frags - (frag_data % chan->setup.frags); - if (frags_cont < frags) - frags = frags_cont; - return frags; -} - -static size_t snd_pcm_mmap_capture_frags_xfer(snd_pcm_t *pcm, size_t frags) -{ - struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; - snd_pcm_mmap_control_t *ctrl = chan->mmap_control; - size_t frags_cont; - size_t frag_data = ctrl->frag_data; - size_t frags_used = snd_pcm_mmap_capture_frags_used(chan); - if (frags_used < frags) - frags = frags_used; - frags_cont = chan->setup.frags - (frag_data % chan->setup.frags); - if (frags_cont < frags) - frags = frags_cont; - return frags; -} - static size_t snd_pcm_mmap_playback_bytes_xfer(snd_pcm_t *pcm, size_t bytes) { struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; @@ -300,7 +206,7 @@ static size_t snd_pcm_mmap_playback_bytes_xfer(snd_pcm_t *pcm, size_t bytes) bytes_cont = chan->setup.buffer_size - (byte_data % chan->setup.buffer_size); if (bytes_cont < bytes) bytes = bytes_cont; - bytes -= bytes % chan->setup.buf.stream.bytes_align; + bytes -= bytes % chan->setup.bytes_align; return bytes; } @@ -316,38 +222,24 @@ static size_t snd_pcm_mmap_capture_bytes_xfer(snd_pcm_t *pcm, size_t bytes) bytes_cont = chan->setup.buffer_size - (byte_data % chan->setup.buffer_size); if (bytes_cont < bytes) bytes = bytes_cont; - bytes -= bytes % chan->setup.buf.stream.bytes_align; + bytes -= bytes % chan->setup.bytes_align; return bytes; } static ssize_t snd_pcm_mmap_playback_samples_xfer(snd_pcm_t *pcm, size_t samples) { - struct snd_pcm_chan *chan; - chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - size_t frags = samples / chan->samples_per_frag; - frags = snd_pcm_mmap_playback_frags_xfer(pcm, frags); - return frags * chan->samples_per_frag; - } else { - size_t bytes = samples * chan->bits_per_sample / 8; - bytes = snd_pcm_mmap_playback_bytes_xfer(pcm, bytes); - return bytes * 8 / chan->bits_per_sample; - } + struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; + size_t bytes = samples * chan->bits_per_sample / 8; + bytes = snd_pcm_mmap_playback_bytes_xfer(pcm, bytes); + return bytes * 8 / chan->bits_per_sample; } static ssize_t snd_pcm_mmap_capture_samples_xfer(snd_pcm_t *pcm, size_t samples) { - struct snd_pcm_chan *chan; - chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - size_t frags = samples / chan->samples_per_frag; - frags = snd_pcm_mmap_capture_frags_xfer(pcm, frags); - return frags * chan->samples_per_frag; - } else { - size_t bytes = samples * chan->bits_per_sample / 8; - bytes = snd_pcm_mmap_capture_bytes_xfer(pcm, bytes); - return bytes * 8 / chan->bits_per_sample; - } + struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_CAPTURE]; + size_t bytes = samples * chan->bits_per_sample / 8; + bytes = snd_pcm_mmap_capture_bytes_xfer(pcm, bytes); + return bytes * 8 / chan->bits_per_sample; } ssize_t snd_pcm_mmap_samples_xfer(snd_pcm_t *pcm, int channel, size_t samples) @@ -380,16 +272,14 @@ ssize_t snd_pcm_mmap_samples_offset(snd_pcm_t *pcm, int channel) ctrl = chan->mmap_control; if (!ctrl) return -EBADFD; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) - return (ctrl->frag_data % chan->setup.frags) * chan->samples_per_frag; - else - return (ctrl->byte_data % chan->setup.buffer_size) * 8 / chan->bits_per_sample; + return (ctrl->byte_data % chan->setup.buffer_size) * 8 / chan->bits_per_sample; } int snd_pcm_mmap_commit_samples(snd_pcm_t *pcm, int channel, int samples) { struct snd_pcm_chan *chan; snd_pcm_mmap_control_t *ctrl; + size_t byte_data, bytes; if (!pcm) return -EFAULT; if (channel < 0 || channel > 1) @@ -400,33 +290,15 @@ int snd_pcm_mmap_commit_samples(snd_pcm_t *pcm, int channel, int samples) ctrl = chan->mmap_control; if (!ctrl) return -EBADFD; - if (chan->setup.mode == SND_PCM_MODE_BLOCK) { - size_t frag_data, frags; - if (samples % chan->samples_per_frag) - return -EINVAL; - frags = samples / chan->samples_per_frag; - frag_data = ctrl->frag_data + frags; - if (frag_data == chan->setup.frag_boundary) { - ctrl->frag_data = 0; - ctrl->byte_data = 0; - } else { - ctrl->frag_data = frag_data; - ctrl->byte_data = frag_data * chan->setup.frag_size; - } + bytes = samples * chan->bits_per_sample; + if (bytes % 8) + return -EINVAL; + bytes /= 8; + byte_data = ctrl->byte_data + bytes; + if (byte_data == chan->setup.byte_boundary) { + ctrl->byte_data = 0; } else { - size_t byte_data; - size_t bytes = samples * chan->bits_per_sample; - if (bytes % 8) - return -EINVAL; - bytes /= 8; - byte_data = ctrl->byte_data + bytes; - if (byte_data == chan->setup.byte_boundary) { - ctrl->byte_data = 0; - ctrl->frag_data = 0; - } else { - ctrl->byte_data = byte_data; - ctrl->frag_data = byte_data / chan->setup.frag_size; - } + ctrl->byte_data = byte_data; } return 0; } @@ -788,26 +660,48 @@ ssize_t snd_pcm_mmap_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned return result * chan->bits_per_sample / 8; } +static ssize_t mmap_playback_bytes_xfer(struct snd_pcm_chan *chan) +{ + snd_pcm_mmap_control_t *ctrl = chan->mmap_control; + size_t bytes_cont; + size_t byte_io = ctrl->byte_io; + ssize_t bytes = snd_pcm_mmap_playback_bytes_used(chan); + bytes_cont = chan->setup.buffer_size - (byte_io % chan->setup.buffer_size); + if ((ssize_t)bytes_cont < bytes) + bytes = bytes_cont; + bytes -= bytes % chan->setup.bytes_align; + return bytes; +} + +static ssize_t mmap_capture_bytes_xfer(struct snd_pcm_chan *chan) +{ + snd_pcm_mmap_control_t *ctrl = chan->mmap_control; + size_t bytes_cont; + size_t byte_io = ctrl->byte_io; + ssize_t bytes = snd_pcm_mmap_capture_bytes_free(chan); + bytes_cont = chan->setup.buffer_size - (byte_io % chan->setup.buffer_size); + if ((ssize_t)bytes_cont < bytes) + bytes = bytes_cont; + bytes -= bytes % chan->setup.bytes_align; + return bytes; +} + static void *playback_mmap(void *d) { snd_pcm_t *pcm = d; struct snd_pcm_chan *chan = &pcm->chan[SND_PCM_CHANNEL_PLAYBACK]; snd_pcm_mmap_control_t *control; char *data; - int frags; - int frag_size, voice_size, voice_frag_size; + size_t voice_size; int voices; control = chan->mmap_control; data = chan->mmap_data; - frags = chan->setup.frags; - frag_size = chan->setup.frag_size; voices = chan->setup.format.voices; voice_size = chan->mmap_data_size / voices; - voice_frag_size = voice_size / frags; while (1) { int err; struct pollfd pfd; - unsigned int f, frag; + size_t pos, p, bytes; if (chan->mmap_thread_stop) break; @@ -832,25 +726,28 @@ static void *playback_mmap(void *d) continue; } - frag = control->frag_io; - if (snd_pcm_mmap_playback_frags_used(chan) <= 0) { + pos = control->byte_io; + bytes = mmap_playback_bytes_xfer(chan); + if (bytes <= 0) { fprintf(stderr, "underrun\n"); usleep(10000); continue; } - f = frag % frags; + p = pos % chan->setup.buffer_size; if (chan->setup.format.interleave) { - err = snd_pcm_write(pcm, data + f * frag_size, frag_size); + err = snd_pcm_write(pcm, data + pos, bytes); } else { struct iovec vector[voices]; struct iovec *v = vector; int voice; + size_t size = bytes / voices; + size_t posv = p / voices; for (voice = 0; voice < voices; ++voice) { - v->iov_base = data + voice_size * voice + f * voice_frag_size; - v->iov_len = voice_frag_size; + v->iov_base = data + voice_size * voice + posv; + v->iov_len = size; v++; } - err = snd_pcm_writev(pcm, vector, voice_frag_size); + err = snd_pcm_writev(pcm, vector, voices); } if (err <= 0) { fprintf(stderr, "write err=%d\n", err); @@ -860,10 +757,10 @@ static void *playback_mmap(void *d) pthread_mutex_lock(&chan->mutex); pthread_cond_signal(&chan->ready_cond); pthread_mutex_unlock(&chan->mutex); - frag++; - if (frag == chan->setup.frag_boundary) - frag = 0; - control->frag_io = frag; + pos += bytes; + if (pos == chan->setup.byte_boundary) + pos = 0; + control->byte_io = pos; } return 0; } @@ -887,7 +784,7 @@ static void *capture_mmap(void *d) while (1) { int err; struct pollfd pfd; - unsigned int f, frag; + size_t pos, p, bytes; if (chan->mmap_thread_stop) break; @@ -912,35 +809,41 @@ static void *capture_mmap(void *d) continue; } - frag = control->frag_io; - if (snd_pcm_mmap_capture_frags_free(chan) <= 0) { + pos = control->byte_io; + bytes = mmap_capture_bytes_xfer(chan); + if (bytes <= 0) { fprintf(stderr, "overrun\n"); usleep(10000); continue; } - f = frag % frags; + p = pos % chan->setup.buffer_size; if (chan->setup.format.interleave) { - err = snd_pcm_read(pcm, data + f * frag_size, frag_size); + err = snd_pcm_read(pcm, data + pos, bytes); } else { struct iovec vector[voices]; struct iovec *v = vector; int voice; + size_t size = bytes / voices; + size_t posv = p / voices; for (voice = 0; voice < voices; ++voice) { - v->iov_base = data + voice_size * voice + f * voice_frag_size; - v->iov_len = voice_frag_size; + v->iov_base = data + voice_size * voice + posv; + v->iov_len = size; v++; } - err = snd_pcm_readv(pcm, vector, voice_frag_size); + err = snd_pcm_readv(pcm, vector, voices); } if (err < 0) { fprintf(stderr, "read err=%d\n", err); snd_pcm_mmap_status_change(pcm, SND_PCM_CHANNEL_CAPTURE, -1); continue; } - frag++; - if (frag == chan->setup.frag_boundary) - frag = 0; - control->frag_io = frag; + pthread_mutex_lock(&chan->mutex); + pthread_cond_signal(&chan->ready_cond); + pthread_mutex_unlock(&chan->mutex); + pos += bytes; + if (pos == chan->setup.byte_boundary) + pos = 0; + control->byte_io = pos; } return 0; } diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index a53cf412..077e31f8 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -411,19 +411,12 @@ static int snd_pcm_plug_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t * I/O plugins */ - if (params->mode == SND_PCM_MODE_STREAM) { - pdprintf("params stream plugin\n"); - err = snd_pcm_plugin_build_stream(pcm, channel, plug->slave, &slave_params.format, &plugin); - } else if (params->mode == SND_PCM_MODE_BLOCK) { - if (slave_info.flags & SND_PCM_CHNINFO_MMAP) { - pdprintf("params mmap plugin\n"); - err = snd_pcm_plugin_build_mmap(pcm, channel, plug->slave, &slave_params.format, &plugin); - } else { - pdprintf("params block plugin\n"); - err = snd_pcm_plugin_build_block(pcm, channel, plug->slave, &slave_params.format, &plugin); - } + if (slave_info.flags & SND_PCM_CHNINFO_MMAP) { + pdprintf("params mmap plugin\n"); + err = snd_pcm_plugin_build_mmap(pcm, channel, plug->slave, &slave_params.format, &plugin); } else { - return -EINVAL; + pdprintf("params I/O plugin\n"); + err = snd_pcm_plugin_build_io(pcm, channel, plug->slave, &slave_params.format, &plugin); } if (err < 0) return err; @@ -440,13 +433,11 @@ static int snd_pcm_plug_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t /* compute right sizes */ slave_params.buffer_size = snd_pcm_plug_slave_size(pcm, channel, slave_params.buffer_size); slave_params.frag_size = snd_pcm_plug_slave_size(pcm, channel, slave_params.frag_size); - if (params->mode == SND_PCM_MODE_STREAM) { - slave_params.buf.stream.bytes_fill_max = snd_pcm_plug_slave_size(pcm, channel, slave_params.buf.stream.bytes_fill_max); - slave_params.buf.stream.bytes_min = snd_pcm_plug_slave_size(pcm, channel, slave_params.buf.stream.bytes_min); - slave_params.buf.stream.bytes_xrun_max = snd_pcm_plug_slave_size(pcm, channel, slave_params.buf.stream.bytes_xrun_max); - slave_params.buf.stream.bytes_align = snd_pcm_plug_slave_size(pcm, channel, slave_params.buf.stream.bytes_align); - } else if (params->mode != SND_PCM_MODE_BLOCK) - return -EINVAL; + slave_params.bytes_fill_max = snd_pcm_plug_slave_size(pcm, channel, slave_params.bytes_fill_max); + slave_params.bytes_min = snd_pcm_plug_slave_size(pcm, channel, slave_params.bytes_min); + slave_params.bytes_xrun_max = snd_pcm_plug_slave_size(pcm, channel, slave_params.bytes_xrun_max); + slave_params.bytes_align = snd_pcm_plug_slave_size(pcm, channel, slave_params.bytes_align); + pdprintf("params requested params: format = %i, rate = %i, voices = %i\n", slave_params.format.format, slave_params.format.rate, slave_params.format.voices); err = snd_pcm_channel_params(plug->slave, &slave_params); if (err < 0) @@ -469,17 +460,14 @@ static int snd_pcm_plug_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *s return err; if (snd_pcm_plug_direct(pcm, setup->channel)) return 0; + setup->byte_boundary /= setup->frag_size; setup->frag_size = snd_pcm_plug_client_size(pcm, setup->channel, setup->frag_size); + setup->byte_boundary *= setup->frag_size; setup->buffer_size = setup->frags * setup->frag_size; - setup->byte_boundary = setup->frag_boundary * setup->frag_size; - if (setup->mode == SND_PCM_MODE_STREAM) { - setup->buf.stream.bytes_min = snd_pcm_plug_client_size(pcm, setup->channel, setup->buf.stream.bytes_min); - setup->buf.stream.bytes_align = snd_pcm_plug_client_size(pcm, setup->channel, setup->buf.stream.bytes_align); - setup->buf.stream.bytes_xrun_max = snd_pcm_plug_client_size(pcm, setup->channel, setup->buf.stream.bytes_xrun_max); - setup->buf.stream.bytes_fill_max = snd_pcm_plug_client_size(pcm, setup->channel, setup->buf.stream.bytes_fill_max); - } else if (setup->mode != SND_PCM_MODE_BLOCK) { - return -EINVAL; - } + setup->bytes_min = snd_pcm_plug_client_size(pcm, setup->channel, setup->bytes_min); + setup->bytes_align = snd_pcm_plug_client_size(pcm, setup->channel, setup->bytes_align); + setup->bytes_xrun_max = snd_pcm_plug_client_size(pcm, setup->channel, setup->bytes_xrun_max); + setup->bytes_fill_max = snd_pcm_plug_client_size(pcm, setup->channel, setup->bytes_fill_max); plugchan = &plug->chan[setup->channel]; if (setup->channel == SND_PCM_CHANNEL_PLAYBACK) @@ -504,7 +492,6 @@ static int snd_pcm_plug_channel_status(snd_pcm_t *pcm, snd_pcm_channel_status_t status->byte_io = snd_pcm_plug_client_size(pcm, status->channel, status->byte_io); status->byte_data = snd_pcm_plug_client_size(pcm, status->channel, status->byte_data); status->bytes_used = snd_pcm_plug_client_size(pcm, status->channel, status->bytes_used); - status->bytes_free = snd_pcm_plug_client_size(pcm, status->channel, status->bytes_free); return 0; } diff --git a/src/pcm/plugin/Makefile.am b/src/pcm/plugin/Makefile.am index bdbada97..5d79297e 100644 --- a/src/pcm/plugin/Makefile.am +++ b/src/pcm/plugin/Makefile.am @@ -1,6 +1,6 @@ EXTRA_LTLIBRARIES = libpcmplugin.la -libpcmplugin_la_SOURCES = block.c mmap.c stream.c copy.c linear.c \ +libpcmplugin_la_SOURCES = io.c mmap.c copy.c linear.c \ mulaw.c alaw.c adpcm.c rate.c route.c all: libpcmplugin.la diff --git a/src/pcm/plugin/block.c b/src/pcm/plugin/io.c similarity index 88% rename from src/pcm/plugin/block.c rename to src/pcm/plugin/io.c index e463ebd4..58ed540b 100644 --- a/src/pcm/plugin/block.c +++ b/src/pcm/plugin/io.c @@ -1,5 +1,5 @@ /* - * PCM Block Plug-In Interface + * PCM I/O Plug-In Interface * Copyright (c) 1999 by Jaroslav Kysela * * @@ -38,26 +38,26 @@ #endif /* - * Basic block plugin + * Basic io plugin */ -typedef struct block_private_data { +typedef struct io_private_data { snd_pcm_plugin_handle_t *slave; -} block_t; +} io_t; -static ssize_t block_transfer(snd_pcm_plugin_t *plugin, +static ssize_t io_transfer(snd_pcm_plugin_t *plugin, const snd_pcm_plugin_voice_t *src_voices, snd_pcm_plugin_voice_t *dst_voices, size_t samples) { - block_t *data; + io_t *data; ssize_t result; struct iovec *vec; int count, voice; if (plugin == NULL) return -EINVAL; - data = (block_t *)plugin->extra_data; + data = (io_t *)plugin->extra_data; if (data == NULL) return -EINVAL; vec = (struct iovec *)((char *)data + sizeof(*data)); @@ -114,7 +114,7 @@ static ssize_t block_transfer(snd_pcm_plugin_t *plugin, } } -static int block_src_voices(snd_pcm_plugin_t *plugin, +static int io_src_voices(snd_pcm_plugin_t *plugin, size_t samples, snd_pcm_plugin_voice_t **voices) { @@ -130,14 +130,14 @@ static int block_src_voices(snd_pcm_plugin_t *plugin, return 0; } -int snd_pcm_plugin_build_block(snd_pcm_plugin_handle_t *pcm, +int snd_pcm_plugin_build_io(snd_pcm_plugin_handle_t *pcm, int channel, snd_pcm_plugin_handle_t *slave, snd_pcm_format_t *format, snd_pcm_plugin_t **r_plugin) { int err; - block_t *data; + io_t *data; snd_pcm_plugin_t *plugin; if (r_plugin == NULL) @@ -146,17 +146,17 @@ int snd_pcm_plugin_build_block(snd_pcm_plugin_handle_t *pcm, if (pcm == NULL || format == NULL) return -EINVAL; err = snd_pcm_plugin_build(pcm, channel, - "I/O block", + "I/O io", format, format, - sizeof(block_t) + sizeof(struct iovec) * format->voices, + sizeof(io_t) + sizeof(struct iovec) * format->voices, &plugin); if (err < 0) return err; - data = (block_t *)plugin->extra_data; + data = (io_t *)plugin->extra_data; data->slave = slave; - plugin->transfer = block_transfer; + plugin->transfer = io_transfer; if (format->interleave && channel == SND_PCM_CHANNEL_PLAYBACK) - plugin->client_voices = block_src_voices; + plugin->client_voices = io_src_voices; *r_plugin = plugin; return 0; } diff --git a/src/pcm/plugin/mmap.c b/src/pcm/plugin/mmap.c index ccc6b3b8..a0ae6d42 100644 --- a/src/pcm/plugin/mmap.c +++ b/src/pcm/plugin/mmap.c @@ -37,32 +37,31 @@ typedef struct mmap_private_data { snd_pcm_t *slave; snd_pcm_mmap_control_t *control; void *buffer; - unsigned int frag; +#if 0 char *silence; +#endif } mmap_t; -static int mmap_src_voices(snd_pcm_plugin_t *plugin, - size_t samples, - snd_pcm_plugin_voice_t **voices) +static ssize_t mmap_src_voices(snd_pcm_plugin_t *plugin, + size_t samples, + snd_pcm_plugin_voice_t **voices) { mmap_t *data; - unsigned int voice; snd_pcm_plugin_voice_t *sv; snd_pcm_voice_area_t *dv; struct snd_pcm_chan *chan; snd_pcm_channel_setup_t *setup; snd_pcm_mmap_control_t *ctrl; - int frag, f; + size_t pos; int ready; + unsigned int voice; if (plugin == NULL || voices == NULL) return -EINVAL; data = (mmap_t *)plugin->extra_data; ctrl = data->control; chan = &data->slave->chan[plugin->channel]; - if (samples != chan->samples_per_frag) - return -EINVAL; setup = &chan->setup; if (ctrl->status < SND_PCM_STATUS_PREPARED) @@ -86,29 +85,34 @@ static int mmap_src_voices(snd_pcm_plugin_t *plugin, return -EPIPE; assert(snd_pcm_mmap_ready(data->slave, plugin->channel)); } - frag = ctrl->frag_data; - f = frag % setup->frags; + pos = ctrl->byte_data % setup->buffer_size; + if ((pos * 8) % chan->bits_per_sample != 0) + return -EINVAL; + pos = (pos * 8) / chan->bits_per_sample; sv = plugin->src_voices; dv = chan->voices; *voices = sv; for (voice = 0; voice < plugin->src_format.voices; ++voice) { sv->enabled = 1; +#if 0 sv->wanted = !data->silence[voice * setup->frags + f]; +#else + sv->wanted = 1; +#endif sv->aptr = 0; - sv->area.addr = dv->addr + (dv->step * chan->samples_per_frag * f) / 8; + sv->area.addr = dv->addr + dv->step * pos / 8; sv->area.first = dv->first; sv->area.step = dv->step; ++sv; ++dv; } - data->frag = frag; - return 0; + return snd_pcm_mmap_samples_xfer(data->slave, plugin->channel, samples); } -static int mmap_dst_voices(snd_pcm_plugin_t *plugin, - size_t samples, - snd_pcm_plugin_voice_t **voices) +static ssize_t mmap_dst_voices(snd_pcm_plugin_t *plugin, + size_t samples, + snd_pcm_plugin_voice_t **voices) { mmap_t *data; int err; @@ -118,15 +122,13 @@ static int mmap_dst_voices(snd_pcm_plugin_t *plugin, struct snd_pcm_chan *chan; snd_pcm_channel_setup_t *setup; snd_pcm_mmap_control_t *ctrl; - int frag, f; + size_t pos; int ready; if (plugin == NULL || voices == NULL) return -EINVAL; data = (mmap_t *)plugin->extra_data; chan = &data->slave->chan[plugin->channel]; - if (samples != chan->samples_per_frag) - return -EINVAL; setup = &chan->setup; ctrl = data->control; @@ -156,9 +158,10 @@ static int mmap_dst_voices(snd_pcm_plugin_t *plugin, return -EPIPE; assert(snd_pcm_mmap_ready(data->slave, plugin->channel)); } - - frag = ctrl->frag_data; - f = frag % setup->frags; + pos = ctrl->byte_data % setup->buffer_size; + if ((pos * 8) % chan->bits_per_sample != 0) + return -EINVAL; + pos = (pos * 8) / chan->bits_per_sample; sv = chan->voices; dv = plugin->dst_voices; @@ -167,14 +170,13 @@ static int mmap_dst_voices(snd_pcm_plugin_t *plugin, dv->enabled = 1; dv->wanted = 0; dv->aptr = 0; - dv->area.addr = sv->addr + (sv->step * chan->samples_per_frag * f) / 8; + dv->area.addr = sv->addr + sv->step * pos / 8; dv->area.first = sv->first; dv->area.step = sv->step; ++sv; ++dv; } - data->frag = frag; - return 0; + return snd_pcm_mmap_samples_xfer(data->slave, plugin->channel, samples); } static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, @@ -183,11 +185,9 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, size_t samples) { mmap_t *data; - unsigned int voice; snd_pcm_channel_setup_t *setup; snd_pcm_mmap_control_t *ctrl; struct snd_pcm_chan *chan; - unsigned int frag, f; int err; if (plugin == NULL) @@ -202,15 +202,13 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, return -EINVAL; chan = &data->slave->chan[SND_PCM_CHANNEL_PLAYBACK]; setup = &chan->setup; - frag = ctrl->frag_data; - if (frag != data->frag) - return -EIO; - f = frag % setup->frags; +#if 0 for (voice = 0; voice < plugin->src_format.voices; voice++) { if (src_voices[voice].enabled) data->silence[voice * setup->frags + f] = 0; } +#endif snd_pcm_mmap_commit_samples(data->slave, SND_PCM_CHANNEL_PLAYBACK, samples); if (ctrl->status == SND_PCM_STATUS_PREPARED && @@ -232,7 +230,6 @@ static ssize_t mmap_capture_transfer(snd_pcm_plugin_t *plugin, mmap_t *data; snd_pcm_channel_setup_t *setup; snd_pcm_mmap_control_t *ctrl; - unsigned int frag; if (plugin == NULL) return -EINVAL; @@ -243,9 +240,6 @@ static ssize_t mmap_capture_transfer(snd_pcm_plugin_t *plugin, ctrl = data->control; if (ctrl == NULL) return -EINVAL; - frag = ctrl->frag_data; - if (frag != data->frag) - return -EIO; setup = &data->slave->chan[SND_PCM_CHANNEL_CAPTURE].setup; /* FIXME: not here the increment */ @@ -273,11 +267,13 @@ static int mmap_action(snd_pcm_plugin_t *plugin, return result; setup = &data->slave->chan[plugin->channel].setup; +#if 0 if (plugin->channel == SND_PCM_CHANNEL_PLAYBACK) { data->silence = malloc(setup->frags * setup->format.voices); memset(data->silence, 0, setup->frags * setup->format.voices); } else data->silence = 0; +#endif return 0; } return 0; /* silenty ignore other actions */ @@ -290,8 +286,10 @@ static void mmap_free(snd_pcm_plugin_t *plugin, void *private_data UNUSED) if (plugin == NULL) return; data = (mmap_t *)plugin->extra_data; +#if 0 if (data->silence) free(data->silence); +#endif if (data->control) snd_pcm_munmap(data->slave, plugin->channel); } diff --git a/src/pcm/plugin/stream.c b/src/pcm/plugin/stream.c deleted file mode 100644 index 79ef50e8..00000000 --- a/src/pcm/plugin/stream.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * PCM Stream Plug-In Interface - * Copyright (c) 1999 by Jaroslav Kysela - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include "../pcm_local.h" - -/* - * Basic stream plugin - */ - -typedef struct stream_private_data { - snd_pcm_t *slave; -} stream_t; - -static ssize_t stream_transfer(snd_pcm_plugin_t *plugin, - const snd_pcm_plugin_voice_t *src_voices, - snd_pcm_plugin_voice_t *dst_voices, - size_t samples) -{ - stream_t *data; - ssize_t result; - struct iovec *vec; - int count, voice; - - if (plugin == NULL) - return -EINVAL; - data = (stream_t *)plugin->extra_data; - if (data == NULL) - return -EINVAL; - vec = (struct iovec *)((char *)data + sizeof(*data)); - if (plugin->channel == SND_PCM_CHANNEL_PLAYBACK) { - if (src_voices == NULL) - return -EINVAL; - if ((result = snd_pcm_plugin_src_samples_to_size(plugin, samples)) < 0) - return result; - count = plugin->src_format.voices; - if (plugin->src_format.interleave) { - result = snd_pcm_write(data->slave, src_voices->area.addr, result); - } else { - result /= count; - for (voice = 0; voice < count; voice++) { - if (src_voices[voice].enabled) - vec[voice].iov_base = src_voices[voice].area.addr; - else - vec[voice].iov_base = 0; - vec[voice].iov_len = result; - } - result = snd_pcm_writev(data->slave, vec, count); - } - if (result < 0) - return result; - return snd_pcm_plugin_src_size_to_samples(plugin, result); - } else if (plugin->channel == SND_PCM_CHANNEL_CAPTURE) { - if (dst_voices == NULL) - return -EINVAL; - if ((result = snd_pcm_plugin_dst_samples_to_size(plugin, samples)) < 0) - return result; - count = plugin->dst_format.voices; - if (plugin->dst_format.interleave) { - result = snd_pcm_read(data->slave, dst_voices->area.addr, result); - for (voice = 0; voice < count; voice++) - dst_voices[voice].enabled = src_voices[voice].enabled; - } else { - result /= count; - for (voice = 0; voice < count; voice++) { - dst_voices[voice].enabled = src_voices[voice].enabled; - if (dst_voices[voice].enabled) - vec[voice].iov_base = dst_voices[voice].area.addr; - else - vec[voice].iov_base = 0; - vec[voice].iov_len = result; - } - result = snd_pcm_readv(data->slave, vec, count); - } - if (result < 0) - return result; - return snd_pcm_plugin_dst_size_to_samples(plugin, result); - } else { - return -EINVAL; - } -} - -static int stream_src_voices(snd_pcm_plugin_t *plugin, - size_t samples, - snd_pcm_plugin_voice_t **voices) -{ - int err; - unsigned int voice; - snd_pcm_plugin_voice_t *v; - err = snd_pcm_plugin_client_voices(plugin, samples, &v); - if (err < 0) - return err; - *voices = v; - for (voice = 0; voice < plugin->src_format.voices; ++voice, ++v) - v->wanted = 1; - return 0; -} - -int snd_pcm_plugin_build_stream(snd_pcm_plugin_handle_t *pcm, - int channel, - snd_pcm_t *slave, - snd_pcm_format_t *format, - snd_pcm_plugin_t **r_plugin) -{ - int err; - stream_t *data; - snd_pcm_plugin_t *plugin; - - if (!r_plugin) - return -EINVAL; - *r_plugin = NULL; - if (!pcm || channel < 0 || channel > 1) - return -EINVAL; - err = snd_pcm_plugin_build(pcm, channel, - "I/O stream", - format, format, - sizeof(stream_t) + sizeof(struct iovec) * format->voices, - &plugin); - if (err < 0) - return err; - data = (stream_t *)plugin->extra_data; - data->slave = slave; - plugin->transfer = stream_transfer; - if (format->interleave && channel == SND_PCM_CHANNEL_PLAYBACK) - plugin->client_voices = stream_src_voices; - *r_plugin = plugin; - return 0; -}