]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Removed frag_* fields. Collapsed I/O plugins. Added to mmap plugin support for stream...
authorAbramo Bagnara <abramo@alsa-project.org>
Tue, 23 May 2000 12:52:06 +0000 (12:52 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Tue, 23 May 2000 12:52:06 +0000 (12:52 +0000)
include/pcm.h
src/pcm/pcm.c
src/pcm/pcm_common.c
src/pcm/pcm_mmap.c
src/pcm/pcm_plug.c
src/pcm/plugin/Makefile.am
src/pcm/plugin/io.c [moved from src/pcm/plugin/block.c with 88% similarity]
src/pcm/plugin/mmap.c
src/pcm/plugin/stream.c [deleted file]

index a4f685e78c40a395a3d8a637ecd61e72f5f14b95..30eab3aa4c8a5970b69194b335bab9f7bf526469 100644 (file)
@@ -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,
index c014bc2ccb067c670f48bb8733e51f1b70180123..6e0cb42ba88a1bc6343f565a7d7a0abd0a94808c 100644 (file)
@@ -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);
index 6640cb7e0e64446bd308d27c89ce9845184fe965..95b57ffe3fd81b1558ecec0763a49a01df615289 100644 (file)
@@ -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;
                }
index cdef4a92ad07124a2914a3c84a399e5f1595b09a..e720d58a46970cd457c1ee56468ff2fed3b855fa 100644 (file)
@@ -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;
 }
index a53cf4122f114ad93fb2b357bd575b8793f3a22c..077e31f8d79799cd9966208889a29ab51936de56 100644 (file)
@@ -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;       
 }
 
index bdbada97d8a392dfa41545e358943f79dd7bd30e..5d79297eb5cdf4008eb6732da34c584a68b2e653 100644 (file)
@@ -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
 
similarity index 88%
rename from src/pcm/plugin/block.c
rename to src/pcm/plugin/io.c
index e463ebd4a434f41a933a3465a64305e38c7bb8af..58ed540b3ec915944279db1041e476daa617fb84 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  PCM Block Plug-In Interface
+ *  PCM I/O Plug-In Interface
  *  Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
  *
  *
 #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;
 }
index ccc6b3b8aaee2b60a3f9db6e745449aead3c3df0..a0ae6d42f0e9fbc656d5c5a29cc1363b8784c43e 100644 (file)
@@ -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 (file)
index 79ef50e..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *  PCM Stream Plug-In Interface
- *  Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
- *
- *
- *   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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/uio.h>
-#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;
-}