]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm handle split. Moved buffer to plugin struct
authorAbramo Bagnara <abramo@alsa-project.org>
Wed, 21 Jun 2000 15:03:06 +0000 (15:03 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Wed, 21 Jun 2000 15:03:06 +0000 (15:03 +0000)
src/pcm/pcm_common.c
src/pcm/pcm_plug.c
src/pcm/plugin/adpcm.c
src/pcm/plugin/alaw.c
src/pcm/plugin/copy.c
src/pcm/plugin/io.c
src/pcm/plugin/linear.c
src/pcm/plugin/mmap.c
src/pcm/plugin/mulaw.c
src/pcm/plugin/rate.c
src/pcm/plugin/route.c

index 01f7458fb29ca8dc7eaf416091b982d7a62c6fbd..cdf8d2ac18e2858073e0597284b176d9cae21f65 100644 (file)
 #ifdef __KERNEL__
 #include "../../include/driver.h"
 #include "../../include/pcm.h"
-#define snd_pcm_plug_first(handle, stream) ((handle)->runtime->oss.plugin_first)
-#define snd_pcm_plug_last(handle, stream) ((handle)->runtime->oss.plugin_last)
+#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
+#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
+#define vmalloc snd_vmalloc
+#define vfree snd_vfree
 #else
 #include <malloc.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/uio.h>
 #include "pcm_local.h"
+#define snd_pcm_plug_first(plug) ((plug)->first)
+#define snd_pcm_plug_last(plug) ((plug)->last)
+#define vmalloc malloc
+#define vfree free
 #endif
 
 static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin,
-                                         bitset_t *dst_vmask,
-                                         bitset_t **src_vmask)
+                                           bitset_t *dst_vmask,
+                                           bitset_t **src_vmask)
 {
        bitset_t *vmask = plugin->src_vmask;
        bitset_copy(vmask, dst_vmask, plugin->src_format.channels);
@@ -48,8 +54,8 @@ static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin,
 }
 
 static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin,
-                                         bitset_t *src_vmask,
-                                         bitset_t **dst_vmask)
+                                           bitset_t *src_vmask,
+                                           bitset_t **dst_vmask)
 {
        bitset_t *vmask = plugin->dst_vmask;
        bitset_copy(vmask, src_vmask, plugin->dst_format.channels);
@@ -57,71 +63,97 @@ static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin,
        return 0;
 }
 
-static ssize_t snd_pcm_plugin_side_channels(snd_pcm_plugin_t *plugin,
-                                         int client_side,
-                                         size_t frames,
-                                         snd_pcm_plugin_channel_t **channels)
+static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, size_t frames)
 {
-       char *ptr;
-       int width;
-       unsigned int channel;
-       long size;
-       snd_pcm_plugin_channel_t *v;
        snd_pcm_format_t *format;
-       if ((plugin->stream == SND_PCM_STREAM_PLAYBACK && client_side) ||
-           (plugin->stream == SND_PCM_STREAM_CAPTURE && !client_side)) {
+       ssize_t width;
+       size_t size;
+       unsigned int channel;
+       snd_pcm_plugin_channel_t *c;
+       if (plugin->stream == SND_PCM_STREAM_PLAYBACK)
                format = &plugin->src_format;
-               v = plugin->src_channels;
-       } else {
+       else
                format = &plugin->dst_format;
-               v = plugin->dst_channels;
-       }
-
-       *channels = v;
        if ((width = snd_pcm_format_physical_width(format->format)) < 0)
-               return width;   
+               return width;
        size = frames * format->channels * width;
        assert(size % 8 == 0);
        size /= 8;
-       ptr = (char *)snd_pcm_plug_buf_alloc(plugin->handle, plugin->stream, size);
-       if (ptr == NULL)
+       if (plugin->buf_frames < frames) {
+               if (plugin->buf)
+                       vfree(plugin->buf);
+               plugin->buf = vmalloc(size);
+               plugin->buf_frames = frames;
+       }
+       if (!plugin->buf)
                return -ENOMEM;
-       assert(size % format->channels == 0);
-       size /= format->channels;
-       for (channel = 0; channel < format->channels; channel++, v++) {
-               v->enabled = 1;
-               v->wanted = 0;
-               v->aptr = ptr;
-               if (format->interleave) {
-                       v->area.addr = ptr;
-                       v->area.first = channel * width;
-                       v->area.step = format->channels * width;
-               } else {
-                       v->area.addr = ptr + (channel * size);
-                       v->area.first = 0;
-                       v->area.step = width;
+       c = plugin->buf_channels;
+       if (format->interleave) {
+               for (channel = 0; channel < format->channels; channel++, c++) {
+                       c->enabled = 1;
+                       c->wanted = 0;
+                       c->area.addr = plugin->buf;
+                       c->area.first = channel * width;
+                       c->area.step = format->channels * width;
+               }
+       } else {
+               assert(size % format->channels == 0);
+               size /= format->channels;
+               for (channel = 0; channel < format->channels; channel++, c++) {
+                       c->enabled = 1;
+                       c->wanted = 0;
+                       c->area.addr = plugin->buf + (channel * size);
+                       c->area.first = 0;
+                       c->area.step = width;
                }
        }
-       return frames;
+       return 0;
 }
 
-ssize_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin,
-                                    size_t frames,
-                                    snd_pcm_plugin_channel_t **channels)
+int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, size_t frames)
 {
-       return snd_pcm_plugin_side_channels(plugin, 1, frames, channels);
+       int err;
+#ifndef __KERNEL__
+       plug->frames_alloc = frames;
+#endif
+       assert(snd_pcm_plug_first(plug));
+       if (snd_pcm_plug_stream(plug) == SND_PCM_STREAM_PLAYBACK) {
+               snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
+               while (plugin->next) {
+                       if (plugin->dst_frames)
+                               frames = plugin->dst_frames(plugin, frames);
+                       assert(frames > 0);
+                       plugin = plugin->next;
+                       err = snd_pcm_plugin_alloc(plugin, frames);
+                       if (err < 0)
+                               return err;
+               }
+       } else {
+               snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
+               while (plugin->prev) {
+                       if (plugin->dst_frames)
+                               frames = plugin->dst_frames(plugin, frames);
+                       assert(frames > 0);
+                       plugin = plugin->prev;
+                       err = snd_pcm_plugin_alloc(plugin, frames);
+                       if (err < 0)
+                               return err;
+               }
+       }
+       return 0;
 }
 
-ssize_t snd_pcm_plugin_slave_channels(snd_pcm_plugin_t *plugin,
-                                   size_t frames,
-                                   snd_pcm_plugin_channel_t **channels)
+
+ssize_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin,
+                                      size_t frames,
+                                      snd_pcm_plugin_channel_t **channels)
 {
-       return snd_pcm_plugin_side_channels(plugin, 0, frames, channels);
+       assert(frames <= plugin->buf_frames);
+       *channels = plugin->buf_channels;
+       return frames;
 }
 
-
-int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle,
-                        int stream,
+int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
                         const char *name,
                         snd_pcm_format_t *src_format,
                         snd_pcm_format_t *dst_format,
@@ -129,44 +161,40 @@ int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle,
                         snd_pcm_plugin_t **ret)
 {
        snd_pcm_plugin_t *plugin;
+       size_t channels;
        
-       assert(handle);
-       assert(stream >= 0 && stream <= 1);
+       assert(plug);
        assert(src_format && dst_format);
        plugin = (snd_pcm_plugin_t *)calloc(1, sizeof(*plugin) + extra);
        if (plugin == NULL)
                return -ENOMEM;
        plugin->name = name ? strdup(name) : NULL;
-       plugin->handle = handle;
-       plugin->stream = stream;
+       plugin->plug = plug;
+       plugin->stream = snd_pcm_plug_stream(plug);
        plugin->src_format = *src_format;
        plugin->src_width = snd_pcm_format_physical_width(src_format->format);
        assert(plugin->src_width > 0);
        plugin->dst_format = *dst_format;
        plugin->dst_width = snd_pcm_format_physical_width(dst_format->format);
        assert(plugin->dst_width > 0);
-       plugin->src_channels = calloc(src_format->channels, sizeof(snd_pcm_plugin_channel_t));
-       if (plugin->src_channels == NULL) {
-               free(plugin);
-               return -ENOMEM;
-       }
-       plugin->dst_channels = calloc(dst_format->channels, sizeof(snd_pcm_plugin_channel_t));
-       if (plugin->dst_channels == NULL) {
-               free(plugin->src_channels);
+       if (plugin->stream == SND_PCM_STREAM_PLAYBACK)
+               channels = src_format->channels;
+       else
+               channels = dst_format->channels;
+       plugin->buf_channels = calloc(channels, sizeof(*plugin->buf_channels));
+       if (plugin->buf_channels == NULL) {
                free(plugin);
                return -ENOMEM;
        }
        plugin->src_vmask = bitset_alloc(src_format->channels);
        if (plugin->src_vmask == NULL) {
-               free(plugin->src_channels);
-               free(plugin->dst_channels);
+               free(plugin->buf_channels);
                free(plugin);
                return -ENOMEM;
        }
        plugin->dst_vmask = bitset_alloc(dst_format->channels);
        if (plugin->dst_vmask == NULL) {
-               free(plugin->src_channels);
-               free(plugin->dst_channels);
+               free(plugin->buf_channels);
                free(plugin->src_vmask);
                free(plugin);
                return -ENOMEM;
@@ -180,29 +208,30 @@ int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle,
 
 int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin)
 {
-       if (plugin) {
-               if (plugin->private_free)
-                       plugin->private_free(plugin, plugin->private_data);
-               if (plugin->name)
-                       free(plugin->name);
-               free(plugin->src_channels);
-               free(plugin->dst_channels);
-               free(plugin->src_vmask);
-               free(plugin->dst_vmask);
-               free(plugin);
-       }
+       assert(plugin);
+       if (plugin->private_free)
+               plugin->private_free(plugin, plugin->private_data);
+       if (plugin->name)
+               free(plugin->name);
+       free(plugin->buf_channels);
+       if (plugin->buf)
+               vfree(plugin->buf);
+       free(plugin->src_vmask);
+       free(plugin->dst_vmask);
+       free(plugin);
        return 0;
 }
 
-ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, size_t drv_frames)
+ssize_t snd_pcm_plug_client_size(snd_pcm_plug_t *plug, size_t drv_frames)
 {
        snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
-       
-       assert(handle);
+       int stream = snd_pcm_plug_stream(plug);
+
+       assert(plug);
        if (drv_frames == 0)
                return 0;
        if (stream == SND_PCM_STREAM_PLAYBACK) {
-               plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_PLAYBACK);
+               plugin = snd_pcm_plug_last(plug);
                while (plugin && drv_frames > 0) {
                        plugin_prev = plugin->prev;
                        if (plugin->src_frames)
@@ -210,7 +239,7 @@ ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, si
                        plugin = plugin_prev;
                }
        } else if (stream == SND_PCM_STREAM_CAPTURE) {
-               plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE);
+               plugin = snd_pcm_plug_first(plug);
                while (plugin && drv_frames > 0) {
                        plugin_next = plugin->next;
                        if (plugin->dst_frames)
@@ -222,17 +251,18 @@ ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, si
        return drv_frames;
 }
 
-ssize_t snd_pcm_plug_slave_size(snd_pcm_plugin_handle_t *handle, int stream, size_t clt_frames)
+ssize_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, size_t clt_frames)
 {
        snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
        ssize_t frames;
+       int stream = snd_pcm_plug_stream(plug);
        
-       assert(handle);
+       assert(plug);
        if (clt_frames == 0)
                return 0;
        frames = clt_frames;
        if (stream == SND_PCM_STREAM_PLAYBACK) {
-               plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK);
+               plugin = snd_pcm_plug_first(plug);
                while (plugin && frames > 0) {
                        plugin_next = plugin->next;
                        if (plugin->dst_frames) {
@@ -243,7 +273,7 @@ ssize_t snd_pcm_plug_slave_size(snd_pcm_plugin_handle_t *handle, int stream, siz
                        plugin = plugin_next;
                }
        } else if (stream == SND_PCM_STREAM_CAPTURE) {
-               plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE);
+               plugin = snd_pcm_plug_last(plug);
                while (plugin) {
                        plugin_prev = plugin->prev;
                        if (plugin->src_frames) {
@@ -294,9 +324,9 @@ static int preferred_formats[] = {
        SND_PCM_SFMT_U8
 };
 
-int snd_pcm_plug_slave_params(snd_pcm_stream_params_t *params,
-                             snd_pcm_stream_info_t *slave_info,
-                             snd_pcm_stream_params_t *slave_params)
+int snd_pcm_plug_slave_params(snd_pcm_params_t *params,
+                             snd_pcm_info_t *slave_info,
+                             snd_pcm_params_t *slave_params)
 {
        *slave_params = *params;
        if ((slave_info->formats & (1 << params->format.format)) == 0) {
@@ -373,24 +403,24 @@ int snd_pcm_plug_slave_params(snd_pcm_stream_params_t *params,
        }
 
        /* interleave */
-       if (!(slave_info->flags & SND_PCM_STREAM_INFO_INTERLEAVE))
+       if (!(slave_info->flags & SND_PCM_INFO_INTERLEAVE))
                slave_params->format.interleave = 0;
-       if (!(slave_info->flags & SND_PCM_STREAM_INFO_NONINTERLEAVE))
+       if (!(slave_info->flags & SND_PCM_INFO_NONINTERLEAVE))
                slave_params->format.interleave = 1;
        return 0;
 }
 
-int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle
-                       snd_pcm_stream_params_t *params, 
-                       snd_pcm_stream_params_t *slave_params)
+int snd_pcm_plug_format(snd_pcm_plug_t *plug
+                       snd_pcm_params_t *params, 
+                       snd_pcm_params_t *slave_params)
 {
-       snd_pcm_stream_params_t tmpparams;
-       snd_pcm_stream_params_t dstparams;
-       snd_pcm_stream_params_t *srcparams;
+       snd_pcm_params_t tmpparams;
+       snd_pcm_params_t dstparams;
+       snd_pcm_params_t *srcparams;
        snd_pcm_plugin_t *plugin;
        int err;
        
-       switch (params->stream) {
+       switch (snd_pcm_plug_stream(plug)) {
        case SND_PCM_STREAM_PLAYBACK:
                dstparams = *slave_params;
                srcparams = slave_params;
@@ -433,23 +463,20 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
                tmpparams.format.interleave = dstparams.format.interleave;
                switch (srcparams->format.format) {
                case SND_PCM_SFMT_MU_LAW:
-                       err = snd_pcm_plugin_build_mulaw(handle,
-                                                        params->stream,
+                       err = snd_pcm_plugin_build_mulaw(plug,
                                                         &srcparams->format,
                                                         &tmpparams.format,
                                                         &plugin);
                        break;
 #ifndef __KERNEL__
                case SND_PCM_SFMT_A_LAW:
-                       err = snd_pcm_plugin_build_alaw(handle,
-                                                       params->stream,
+                       err = snd_pcm_plugin_build_alaw(plug,
                                                        &srcparams->format,
                                                        &tmpparams.format,
                                                        &plugin);
                        break;
                case SND_PCM_SFMT_IMA_ADPCM:
-                       err = snd_pcm_plugin_build_adpcm(handle,
-                                                        params->stream,
+                       err = snd_pcm_plugin_build_adpcm(plug,
                                                         &srcparams->format,
                                                         &tmpparams.format,
                                                         &plugin);
@@ -490,8 +517,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
                if (srcparams->format.rate == dstparams.format.rate &&
                    snd_pcm_format_linear(dstparams.format.format))
                        tmpparams.format.format = dstparams.format.format;
-               err = snd_pcm_plugin_build_route(handle,
-                                                params->stream,
+               err = snd_pcm_plugin_build_route(plug,
                                                 &srcparams->format,
                                                 &tmpparams.format,
                                                 ttable,
@@ -517,8 +543,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
                if (srcparams->format.channels == dstparams.format.channels &&
                    snd_pcm_format_linear(dstparams.format.format))
                        tmpparams.format.format = dstparams.format.format;
-               err = snd_pcm_plugin_build_rate(handle,
-                                               params->stream,
+               err = snd_pcm_plugin_build_rate(plug,
                                                &srcparams->format,
                                                &tmpparams.format,
                                                &plugin);
@@ -562,8 +587,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
                tmpparams.format.interleave = dstparams.format.interleave;
                if (snd_pcm_format_linear(dstparams.format.format))
                        tmpparams.format.format = dstparams.format.format;
-               err = snd_pcm_plugin_build_route(handle,
-                                                params->stream,
+               err = snd_pcm_plugin_build_route(plug,
                                                 &srcparams->format,
                                                 &tmpparams.format,
                                                 ttable,
@@ -587,23 +611,20 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
                tmpparams.format.format = dstparams.format.format;
                tmpparams.format.interleave = dstparams.format.interleave;
                if (tmpparams.format.format == SND_PCM_SFMT_MU_LAW) {
-                       err = snd_pcm_plugin_build_mulaw(handle,
-                                                        params->stream,
+                       err = snd_pcm_plugin_build_mulaw(plug,
                                                         &srcparams->format,
                                                         &tmpparams.format,
                                                         &plugin);
                }
 #ifndef __KERNEL__
                else if (tmpparams.format.format == SND_PCM_SFMT_A_LAW) {
-                       err = snd_pcm_plugin_build_alaw(handle,
-                                                       params->stream,
+                       err = snd_pcm_plugin_build_alaw(plug,
                                                        &srcparams->format,
                                                        &tmpparams.format,
                                                        &plugin);
                }
                else if (tmpparams.format.format == SND_PCM_SFMT_IMA_ADPCM) {
-                       err = snd_pcm_plugin_build_adpcm(handle,
-                                                        params->stream,
+                       err = snd_pcm_plugin_build_adpcm(plug,
                                                         &srcparams->format,
                                                         &tmpparams.format,
                                                         &plugin);
@@ -611,8 +632,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
 #endif
                else if (snd_pcm_format_linear(srcparams->format.format) &&
                         snd_pcm_format_linear(tmpparams.format.format)) {
-                       err = snd_pcm_plugin_build_linear(handle,
-                                                         params->stream,
+                       err = snd_pcm_plugin_build_linear(plug,
                                                          &srcparams->format,
                                                          &tmpparams.format,
                                                          &plugin);
@@ -633,8 +653,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
        /* interleave */
        if (srcparams->format.interleave != dstparams.format.interleave) {
                tmpparams.format.interleave = dstparams.format.interleave;
-               err = snd_pcm_plugin_build_copy(handle,
-                                               params->stream,
+               err = snd_pcm_plugin_build_copy(plug,
                                                &srcparams->format,
                                                &tmpparams.format,
                                                &plugin);
@@ -652,8 +671,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
        return 0;
 }
 
-ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle,
-                                        int stream,
+ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,
                                         char *buf,
                                         size_t count,
                                         snd_pcm_plugin_channel_t **channels)
@@ -662,18 +680,18 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle,
        snd_pcm_plugin_channel_t *v;
        snd_pcm_format_t *format;
        int width, nchannels, channel;
+       int stream = snd_pcm_plug_stream(plug);
 
        assert(buf);
        if (stream == SND_PCM_STREAM_PLAYBACK) {
-               plugin = snd_pcm_plug_first(handle, stream);
+               plugin = snd_pcm_plug_first(plug);
                format = &plugin->src_format;
-               v = plugin->src_channels;
        }
        else {
-               plugin = snd_pcm_plug_last(handle, stream);
+               plugin = snd_pcm_plug_last(plug);
                format = &plugin->dst_format;
-               v = plugin->dst_channels;
        }
+       v = plugin->buf_channels;
        *channels = v;
        if ((width = snd_pcm_format_physical_width(format->format)) < 0)
                return width;
@@ -682,7 +700,6 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle,
        for (channel = 0; channel < nchannels; channel++, v++) {
                v->enabled = 1;
                v->wanted = (stream == SND_PCM_STREAM_CAPTURE);
-               v->aptr = NULL;
                v->area.addr = buf;
                v->area.first = channel * width;
                v->area.step = nchannels * width;
@@ -690,8 +707,7 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle,
        return count;
 }
 
-ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle,
-                                          int stream,
+ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plug_t *plug,
                                           const struct iovec *vector,
                                           unsigned long count,
                                           snd_pcm_plugin_channel_t **channels)
@@ -701,17 +717,17 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle,
        snd_pcm_format_t *format;
        int width;
        unsigned int nchannels, channel;
+       int stream = snd_pcm_plug_stream(plug);
 
        if (stream == SND_PCM_STREAM_PLAYBACK) {
-               plugin = snd_pcm_plug_first(handle, stream);
+               plugin = snd_pcm_plug_first(plug);
                format = &plugin->src_format;
-               v = plugin->src_channels;
        }
        else {
-               plugin = snd_pcm_plug_last(handle, stream);
+               plugin = snd_pcm_plug_last(plug);
                format = &plugin->dst_format;
-               v = plugin->dst_channels;
        }
+       v = plugin->buf_channels;
        *channels = v;
        if ((width = snd_pcm_format_physical_width(format->format)) < 0)
                return width;
@@ -722,7 +738,6 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle,
                for (channel = 0; channel < nchannels; channel++, v++) {
                        v->enabled = 1;
                        v->wanted = (stream == SND_PCM_STREAM_CAPTURE);
-                       v->aptr = NULL;
                        v->area.addr = vector->iov_base;
                        v->area.first = channel * width;
                        v->area.step = nchannels * width;
@@ -736,7 +751,6 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle,
                        assert(vector->iov_len == len);
                        v->enabled = (vector->iov_base != NULL);
                        v->wanted = (v->enabled && (stream == SND_PCM_STREAM_CAPTURE));
-                       v->aptr = NULL;
                        v->area.addr = vector->iov_base;
                        v->area.first = 0;
                        v->area.step = width;
@@ -745,16 +759,13 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle,
        }
 }
 
-int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle,
+int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
                                        bitset_t *client_vmask)
 {
-#ifndef __KERNEL__
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &handle->private;
-#endif
-       snd_pcm_plugin_t *plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_PLAYBACK);
+       snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
        if (plugin == NULL) {
 #ifndef __KERNEL__
-               return snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_PLAYBACK, client_vmask);
+               return snd_pcm_channels_mask(plug->slave, client_vmask);
 #else
                return 0;
 #endif
@@ -766,7 +777,7 @@ int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle,
                int err;
                bitset_one(dstmask, schannels);
 #ifndef __KERNEL__
-               err = snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_PLAYBACK, dstmask);
+               err = snd_pcm_channels_mask(plug->slave, dstmask);
                if (err < 0)
                        return err;
 #endif
@@ -788,16 +799,13 @@ int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle,
        }
 }
 
-int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle,
+int snd_pcm_plug_capture_channels_mask(snd_pcm_plug_t *plug,
                                       bitset_t *client_vmask)
 {
-#ifndef __KERNEL__
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &handle->private;
-#endif
-       snd_pcm_plugin_t *plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE);
+       snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
        if (plugin == NULL) {
 #ifndef __KERNEL__
-               return snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_CAPTURE, client_vmask);
+               return snd_pcm_channels_mask(plug->slave, client_vmask);
 #else
                return 0;
 #endif
@@ -809,7 +817,7 @@ int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle,
                int err;
                bitset_one(srcmask, schannels);
 #ifndef __KERNEL__
-               err = snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_CAPTURE, srcmask);
+               err = snd_pcm_channels_mask(plug->slave, srcmask);
                if (err < 0)
                        return err;
 #endif
@@ -827,10 +835,10 @@ int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle,
        }
 }
 
-static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_t *handle,
+static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plug_t *plug,
                                                          snd_pcm_plugin_channel_t *src_channels)
 {
-       snd_pcm_plugin_t *plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK);
+       snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
        unsigned int nchannels = plugin->src_format.channels;
        bitset_t bs[bitset_size(nchannels)];
        bitset_t *srcmask = bs;
@@ -842,7 +850,7 @@ static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_
                else
                        bitset_reset(srcmask, channel);
        }
-       err = snd_pcm_plug_playback_channels_mask(handle, srcmask);
+       err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
        if (err < 0)
                return err;
        for (channel = 0; channel < nchannels; channel++) {
@@ -852,14 +860,11 @@ static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_
        return 0;
 }
 
-static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plugin_handle_t *handle,
+static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plug_t *plug,
                                                         snd_pcm_plugin_channel_t *src_channels,
                                                         snd_pcm_plugin_channel_t *client_channels)
 {
-#ifndef __KERNEL__
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &handle->private;
-#endif
-       snd_pcm_plugin_t *plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE);
+       snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
        unsigned int nchannels = plugin->dst_format.channels;
        bitset_t bs[bitset_size(nchannels)];
        bitset_t *dstmask = bs;
@@ -880,11 +885,11 @@ static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plugin_handle_t
                plugin = plugin->prev;
        }
 #ifndef __KERNEL__
-       err = snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_CAPTURE, dstmask);
+       err = snd_pcm_channels_mask(plug->slave, dstmask);
        if (err < 0)
                return err;
 #endif
-       plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE);
+       plugin = snd_pcm_plug_first(plug);
        nchannels = plugin->src_format.channels;
        for (channel = 0; channel < nchannels; channel++) {
                if (!bitset_get(dstmask, channel))
@@ -893,24 +898,23 @@ static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plugin_handle_t
        return 0;
 }
 
-ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plugin_channel_t *src_channels, size_t size)
+ssize_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, size_t size)
 {
        snd_pcm_plugin_t *plugin, *next;
        snd_pcm_plugin_channel_t *dst_channels;
        int err;
        ssize_t frames = size;
 
-       if ((err = snd_pcm_plug_playback_disable_useless_channels(handle, src_channels)) < 0)
+       if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)
                return err;
        
-       plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK);
+       plugin = snd_pcm_plug_first(plug);
        while (plugin && frames > 0) {
                if ((next = plugin->next) != NULL) {
                        ssize_t frames1 = frames;
                        if (plugin->dst_frames)
                                frames1 = plugin->dst_frames(plugin, frames);
                        if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {
-                               snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr);
                                return err;
                        }
                        if (err != frames1) {
@@ -918,76 +922,49 @@ ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plu
                                if (plugin->src_frames)
                                        frames = plugin->src_frames(plugin, frames1);
                        }
-               } else {
-                       if ((err = snd_pcm_plugin_slave_channels(plugin, frames, &dst_channels)) < 0)
-                               return err;
-               }
+               } else
+                       dst_channels = 0;
                pdprintf("write plugin: %s, %i\n", plugin->name, frames);
-               if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) {
-                       snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr);
-                       snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, dst_channels->aptr);
+               if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
                        return frames;
-               }
-               snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr);
                src_channels = dst_channels;
                plugin = next;
        }
-       snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr);
-       return snd_pcm_plug_client_size(handle, SND_PCM_STREAM_PLAYBACK, frames);
+       return snd_pcm_plug_client_size(plug, 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)
+ssize_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, 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 = size;
        int err;
 
-       plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE);
-       frames = snd_pcm_plug_slave_size(handle, SND_PCM_STREAM_CAPTURE, frames);
+       frames = snd_pcm_plug_slave_size(plug, frames);
        if (frames < 0)
                return frames;
 
-       plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE);
-       if ((err = snd_pcm_plugin_slave_channels(plugin, frames, &src_channels)) < 0)
-               return err;
-       if ((err = snd_pcm_plug_capture_disable_useless_channels(handle, src_channels, dst_channels_final) < 0))
-               return err;
-       
+       src_channels = 0;
+       plugin = snd_pcm_plug_first(plug);
        while (plugin && frames > 0) {
                if ((next = plugin->next) != NULL) {
                        if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) {
-                               snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr);
                                return err;
                        }
                        frames = err;
+                       if (!plugin->prev) {
+                               if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final) < 0))
+                                       return err;
+                       }
                } else {
                        dst_channels = dst_channels_final;
                }
                pdprintf("read plugin: %s, %i\n", plugin->name, frames);
-               if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) {
-                       snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr);
-                       snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, dst_channels->aptr);
+               if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
                        return frames;
-               }
-#if 0
-               {
-                 unsigned int channel;
-                 for (channel = 0; channel < plugin->src_format.channels; ++channel) {
-                   fprintf(stderr, "%d%d ", src_channels[channel].enabled, src_channels[channel].wanted);
-                 }
-                 fprintf(stderr, " -> ");
-                 for (channel = 0; channel < plugin->dst_format.channels; ++channel) {
-                   fprintf(stderr, "%d%d ", dst_channels[channel].enabled, dst_channels[channel].wanted);
-                 }
-                 fprintf(stderr, "\n");
-               }
-#endif
-               snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr);
                plugin = next;
                src_channels = dst_channels;
        }
-       snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr);
        return frames;
 }
 
index 8cc7465133f37869309adac7815947fccf6f1613..d4e9a4faf09476fd21931459b72d36b410984ff7 100644 (file)
 #include <sys/uio.h>
 #include "pcm_local.h"
 
-/* snd_pcm_plug helpers */
-
-void *snd_pcm_plug_buf_alloc(snd_pcm_t *pcm, int stream, size_t size)
-{
-       int idx;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       snd_pcm_plug_stream_t *plugstr = &plug->stream[stream];
-
-       for (idx = 0; idx < 2; idx++) {
-               if (plugstr->alloc_lock[idx])
-                       continue;
-               if (plugstr->alloc_size[idx] >= size) {
-                       plugstr->alloc_lock[idx] = 1;
-                       return plugstr->alloc_ptr[idx];
-               }
-       }
-       for (idx = 0; idx < 2; idx++) {
-               if (plugstr->alloc_lock[idx])
-                       continue;
-               if (plugstr->alloc_ptr[idx] != NULL)
-                       free(plugstr->alloc_ptr[idx]);
-               plugstr->alloc_ptr[idx] = malloc(size);
-               if (plugstr->alloc_ptr[idx] == NULL)
-                       return NULL;
-               plugstr->alloc_size[idx] = size;
-               plugstr->alloc_lock[idx] = 1;
-               return plugstr->alloc_ptr[idx];
-       }
-       return NULL;
-}
-
-void snd_pcm_plug_buf_unlock(snd_pcm_t *pcm, int stream, void *ptr)
-{
-       int idx;
-
-       snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-
-       if (!ptr)
-               return;
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[stream];
-
-       for (idx = 0; idx < 2; idx++) {
-               if (plugstr->alloc_ptr[idx] == ptr) {
-                       plugstr->alloc_lock[idx] = 0;
-                       return;
-               }
-       }
-}
-
 /* snd_pcm_plugin externs */
 
 int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin)
 {
        snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       snd_pcm_t *pcm;
        assert(plugin);
-       pcm = plugin->handle;
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[plugin->stream];
-       plugin->next = plugstr->first;
+       plug = plugin->plug;
+       plugin->next = plug->first;
        plugin->prev = NULL;
-       if (plugstr->first) {
-               plugstr->first->prev = plugin;
-               plugstr->first = plugin;
+       if (plug->first) {
+               plug->first->prev = plugin;
+               plug->first = plugin;
        } else {
-               plugstr->last =
-               plugstr->first = plugin;
+               plug->last =
+               plug->first = plugin;
        }
        return 0;
 }
@@ -105,181 +50,78 @@ int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin)
 int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
 {
        snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       snd_pcm_t *pcm;
        assert(plugin);
-       pcm = plugin->handle;
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[plugin->stream];
-
+       plug = plugin->plug;
        plugin->next = NULL;
-       plugin->prev = plugstr->last;
-       if (plugstr->last) {
-               plugstr->last->next = plugin;
-               plugstr->last = plugin;
+       plugin->prev = plug->last;
+       if (plug->last) {
+               plug->last->next = plugin;
+               plug->last = plugin;
        } else {
-               plugstr->last =
-               plugstr->first = plugin;
+               plug->last =
+               plug->first = plugin;
        }
        return 0;
 }
 
-#if 0
-int snd_pcm_plugin_remove_to(snd_pcm_plugin_t *plugin)
-{
-       snd_pcm_plugin_t *plugin1, *plugin1_prev;
-       snd_pcm_plug_t *plug;
-       snd_pcm_t *pcm;
-       snd_pcm_plug_stream_t *plugstr;
-       assert(plugin);
-       pcm = plugin->handle;
-
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[plugin->stream];
-
-       plugin1 = plugin;
-       while (plugin1->prev)
-               plugin1 = plugin1->prev;
-       if (plugstr->first != plugin1)
-               return -EINVAL;
-       plugstr->first = plugin;
-       plugin1 = plugin->prev;
-       plugin->prev = NULL;
-       while (plugin1) {
-               plugin1_prev = plugin1->prev;
-               snd_pcm_plugin_free(plugin1);
-               plugin1 = plugin1_prev;
-       }
-       return 0;
-}
-
-int snd_pcm_plug_remove_first(snd_pcm_t *pcm, int stream)
-{
-       snd_pcm_plugin_t *plugin;
-       snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       assert(pcm);
-       assert(stream >= 0 && stream <= 1);
-       assert(pcm->stream[stream].open);
-
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[stream];
-
-       plugin = plugstr->first;
-       if (plugin->next) {
-               plugin = plugin->next;
-       } else {
-               return snd_pcm_plug_clear(pcm, stream);
-       }
-       return snd_pcm_plugin_remove_to(plugin);
-}
-#endif
-
 /* snd_pcm_plug externs */
 
-int snd_pcm_plug_clear(snd_pcm_t *pcm, int stream)
+int snd_pcm_plug_clear(snd_pcm_plug_t *plug)
 {
        snd_pcm_plugin_t *plugin, *plugin_next;
-       snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       int idx;
        
-       assert(pcm);
-       assert(stream >= 0 && stream <= 1);
-       assert(pcm->stream[stream].open);
-
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[stream];
-       plugin = plugstr->first;
-       plugstr->first = NULL;
-       plugstr->last = NULL;
+       assert(plug);
+
+       plugin = plug->first;
+       plug->first = NULL;
+       plug->last = NULL;
        while (plugin) {
                plugin_next = plugin->next;
                snd_pcm_plugin_free(plugin);
                plugin = plugin_next;
        }
-       for (idx = 0; idx < 2; idx++) {
-               if (plugstr->alloc_ptr[idx]) {
-                       free(plugstr->alloc_ptr[idx]);
-                       plugstr->alloc_ptr[idx] = 0;
-               }
-               plugstr->alloc_size[idx] = 0;
-               plugstr->alloc_lock[idx] = 0;
-       }
        return 0;
 }
 
-snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_t *pcm, int stream)
+snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_plug_t *plug)
 {
-       snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       if (!pcm)
-               return NULL;
-       if (stream < 0 || stream > 1)
-               return NULL;
-       if (!pcm->stream[stream].open)
-               return NULL;
-
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[stream];
-
-       return plugstr->first;
+       assert(plug);
+       return plug->first;
 }
 
-snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_t *pcm, int stream)
+snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_plug_t *plug)
 {
-       snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       if (!pcm)
-               return NULL;
-       if (stream < 0 || stream > 1)
-               return NULL;
-       if (!pcm->stream[stream].open)
-               return NULL;
-
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[stream];
-
-       return plugstr->last;
-}
-
-int snd_pcm_plug_direct(snd_pcm_t *pcm, int stream)
-{
-       return snd_pcm_plug_first(pcm, stream) == NULL;
+       assert(plug);
+       return plug->last;
 }
 
 /*
  *
  */
 
-static int snd_pcm_plug_stream_close(snd_pcm_t *pcm, int stream)
+static int snd_pcm_plug_close(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       snd_pcm_plug_clear(pcm, stream);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_plug_clear(plug);
+       free(plug->handle->ops);
        if (plug->close_slave)
-               return snd_pcm_stream_close(plug->slave, stream);
+               return snd_pcm_close(plug->slave);
+       free(private);
        return 0;
 }
 
-static int snd_pcm_plug_stream_nonblock(snd_pcm_t *pcm, int stream, int nonblock)
-{
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       return snd_pcm_stream_nonblock(plug->slave, stream, nonblock);
-}
-
-static int snd_pcm_plug_info(snd_pcm_t *pcm, int stream UNUSED, snd_pcm_info_t * info)
+static int snd_pcm_plug_nonblock(void *private, int nonblock)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       return snd_pcm_info(plug->slave, info);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       return snd_pcm_nonblock(plug->slave, nonblock);
 }
 
-static int snd_pcm_plug_stream_info(snd_pcm_t *pcm, snd_pcm_stream_info_t *info)
+static int snd_pcm_plug_info(void *private, snd_pcm_info_t *info)
 {
        int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       snd_pcm_stream_t *str;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        
-       if ((err = snd_pcm_stream_info(plug->slave, info)) < 0)
+       if ((err = snd_pcm_info(plug->slave, info)) < 0)
                return err;
        info->formats = snd_pcm_plug_formats(info->formats);
        info->min_rate = 4000;
@@ -287,37 +129,26 @@ static int snd_pcm_plug_stream_info(snd_pcm_t *pcm, snd_pcm_stream_info_t *info)
        info->min_channels = 1;
        info->max_channels = 32;
        info->rates = SND_PCM_RATE_CONTINUOUS | SND_PCM_RATE_8000_192000;
-       info->flags |= SND_PCM_STREAM_INFO_INTERLEAVE | SND_PCM_STREAM_INFO_NONINTERLEAVE;
-
-       str = &pcm->stream[info->stream];
-       if (pcm->stream[info->stream].valid_setup) {
-               info->buffer_size = snd_pcm_plug_client_size(pcm, info->stream, info->buffer_size);
-               info->min_fragment_size = snd_pcm_plug_client_size(pcm, info->stream, info->min_fragment_size);
-               info->max_fragment_size = snd_pcm_plug_client_size(pcm, info->stream, info->max_fragment_size);
-               info->fragment_align = snd_pcm_plug_client_size(pcm, info->stream, info->fragment_align);
-               info->fifo_size = snd_pcm_plug_client_size(pcm, info->stream, info->fifo_size);
-               info->transfer_block_size = snd_pcm_plug_client_size(pcm, info->stream, info->transfer_block_size);
-               if (str->setup.mode == SND_PCM_MODE_FRAGMENT)
-                       info->mmap_size = str->setup.buffer_size;
-               else
-                       info->mmap_size = snd_pcm_plug_client_size(pcm, info->stream, info->mmap_size);
+       info->flags |= SND_PCM_INFO_INTERLEAVE | SND_PCM_INFO_NONINTERLEAVE;
+
+       if (plug->slave->valid_setup) {
+               info->buffer_size = snd_pcm_plug_client_size(plug, info->buffer_size);
+               info->min_fragment_size = snd_pcm_plug_client_size(plug, info->min_fragment_size);
+               info->max_fragment_size = snd_pcm_plug_client_size(plug, info->max_fragment_size);
+               info->fragment_align = snd_pcm_plug_client_size(plug, info->fragment_align);
+               info->fifo_size = snd_pcm_plug_client_size(plug, info->fifo_size);
+               info->transfer_block_size = snd_pcm_plug_client_size(plug, info->transfer_block_size);
        }
-       if (!snd_pcm_plug_direct(pcm, info->stream))
-               info->flags &= ~(SND_PCM_STREAM_INFO_MMAP | SND_PCM_STREAM_INFO_MMAP_VALID);
+       info->mmap_size = 0;
+       info->flags &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
        return 0;
 }
 
-static int snd_pcm_plug_action(snd_pcm_t *pcm, int stream, int action,
+static int snd_pcm_plug_action(snd_pcm_plug_t *plug, int action,
                               unsigned long data)
 {
-       snd_pcm_plugin_t *plugin;
        int err;
-       snd_pcm_plug_t *plug;
-       snd_pcm_plug_stream_t *plugstr;
-       plug = (snd_pcm_plug_t*) &pcm->private;
-       plugstr = &plug->stream[stream];
-
-       plugin = plugstr->first;
+       snd_pcm_plugin_t *plugin = plug->first;
        while (plugin) {
                if (plugin->action) {
                        if ((err = plugin->action(plugin, action, data))<0)
@@ -328,291 +159,204 @@ static int snd_pcm_plug_action(snd_pcm_t *pcm, int stream, int action,
        return 0;
 }
 
-static int snd_pcm_plug_stream_params(snd_pcm_t *pcm, snd_pcm_stream_params_t *params)
+static int snd_pcm_plug_setup(void *private, snd_pcm_setup_t *setup)
 {
-       snd_pcm_stream_params_t slave_params, params1;
-       snd_pcm_stream_info_t slave_info;
-       snd_pcm_plugin_t *plugin;
-       snd_pcm_plug_t *plug;
        int err;
-       int stream = params->stream;
-       
-       plug = (snd_pcm_plug_t*) &pcm->private;
-
-       /*
-        *  try to decide, if a conversion is required
-         */
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
 
-       memset(&slave_info, 0, sizeof(slave_info));
-       slave_info.stream = stream;
-       if ((err = snd_pcm_stream_info(plug->slave, &slave_info)) < 0) {
-               snd_pcm_plug_clear(pcm, stream);
-               return err;
-       }
-
-       if ((err = snd_pcm_plug_slave_params(params, &slave_info, &slave_params)) < 0)
-               return err;
-
-
-       snd_pcm_plug_clear(pcm, stream);
-
-       /* add necessary plugins */
-       params1 = *params;
-       if ((err = snd_pcm_plug_format(pcm, &params1, &slave_params)) < 0)
-               return err;
-
-       if (snd_pcm_plug_direct(pcm, stream))
-               return snd_pcm_stream_params(plug->slave, params);
-
-       /* compute right sizes */
-       slave_params.frag_size = snd_pcm_plug_slave_size(pcm, stream, params1.frag_size);
-       slave_params.buffer_size = snd_pcm_plug_slave_size(pcm, stream, params1.buffer_size);
-       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.frame_boundary *= slave_params.buffer_size;
-
-       /*
-        *  I/O plugins
-        */
-
-       if (slave_info.flags & SND_PCM_STREAM_INFO_MMAP) {
-               pdprintf("params mmap plugin\n");
-               err = snd_pcm_plugin_build_mmap(pcm, stream, plug->slave, &slave_params.format, &plugin);
-       } else {
-               pdprintf("params I/O plugin\n");
-               err = snd_pcm_plugin_build_io(pcm, stream, plug->slave, &slave_params.format, &plugin);
-       }
-       if (err < 0)
-               return err;
-       if (stream == SND_PCM_STREAM_PLAYBACK) {
-               err = snd_pcm_plugin_append(plugin);
-       } else {
-               err = snd_pcm_plugin_insert(plugin);
-       }
-       if (err < 0) {
-               snd_pcm_plugin_free(plugin);
-               return err;
-       }
-
-       pdprintf("params requested params: format = %i, rate = %i, channels = %i\n", slave_params.format.format, slave_params.format.rate, slave_params.format.channels);
-       err = snd_pcm_stream_params(plug->slave, &slave_params);
+       err = snd_pcm_setup(plug->slave, setup);
        if (err < 0)
                return err;
-
-       err = snd_pcm_plug_action(pcm, stream, INIT, 0);
-       if (err < 0)
-               return err;
-       return 0;
-}
-
-static int snd_pcm_plug_stream_setup(snd_pcm_t *pcm, snd_pcm_stream_setup_t *setup)
-{
-       int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       snd_pcm_plug_stream_t *plugstr;
-
-       err = snd_pcm_stream_setup(plug->slave, setup);
-       if (err < 0)
-               return err;
-       if (snd_pcm_plug_direct(pcm, setup->stream))
+       if (!plug->first)
                return 0;
        setup->frame_boundary /= setup->frag_size;
-       setup->frag_size = snd_pcm_plug_client_size(pcm, setup->stream, setup->frag_size);
+       setup->frag_size = snd_pcm_plug_client_size(plug, setup->frag_size);
        setup->frame_boundary *= setup->frag_size;
        setup->buffer_size = setup->frags * setup->frag_size;
-       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)
-               setup->format = plugstr->first->src_format;
+       setup->frames_min = snd_pcm_plug_client_size(plug, setup->frames_min);
+       setup->frames_align = snd_pcm_plug_client_size(plug, setup->frames_align);
+       setup->frames_xrun_max = snd_pcm_plug_client_size(plug, setup->frames_xrun_max);
+       setup->frames_fill_max = snd_pcm_plug_client_size(plug, setup->frames_fill_max);
+
+       if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK)
+               setup->format = plug->first->src_format;
        else
-               setup->format = plugstr->last->dst_format;
+               setup->format = plug->last->dst_format;
+       err = snd_pcm_plug_alloc(plug, setup->frag_size);
+       if (err < 0)
+               return err;
        return 0;       
 }
 
-static int snd_pcm_plug_stream_status(snd_pcm_t *pcm, snd_pcm_stream_status_t *status)
+static int snd_pcm_plug_status(void *private, snd_pcm_status_t *status)
 {
        int err;
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
 
-       err = snd_pcm_stream_status(plug->slave, status);
+       err = snd_pcm_status(plug->slave, status);
        if (err < 0)
                return err;
-       if (snd_pcm_plug_direct(pcm, status->stream))
-               return 0;
 
-       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);
+       status->frame_io = snd_pcm_plug_client_size(plug, status->frame_io);
+       status->frame_data = snd_pcm_plug_client_size(plug, status->frame_data);
+       status->frames_avail = snd_pcm_plug_client_size(plug, status->frames_avail);
+       status->frames_avail_max = snd_pcm_plug_client_size(plug, status->frames_avail_max);
        return 0;       
 }
 
-static int snd_pcm_plug_stream_state(snd_pcm_t *pcm, int stream)
+static int snd_pcm_plug_state(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       return snd_pcm_stream_state(plug->slave, stream);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       return snd_pcm_state(plug->slave);
 }
 
-static int snd_pcm_plug_stream_frame_io(snd_pcm_t *pcm, int stream, int update)
+static int snd_pcm_plug_frame_io(void *private, int update)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       return snd_pcm_stream_frame_io(plug->slave, stream, update);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       ssize_t frame_io = snd_pcm_frame_io(plug->slave, update);
+       if (frame_io < 0)
+               return frame_io;
+       return snd_pcm_plug_client_size(plug, frame_io);
 }
 
-static int snd_pcm_plug_stream_prepare(snd_pcm_t *pcm, int stream)
+static int snd_pcm_plug_prepare(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        int err;
-       err = snd_pcm_stream_prepare(plug->slave, stream);
+       err = snd_pcm_prepare(plug->slave);
        if (err < 0)
                return err;
-       if (snd_pcm_plug_direct(pcm, stream))
-               return 0;
-       if ((err = snd_pcm_plug_action(pcm, stream, PREPARE, 0))<0)
+       if ((err = snd_pcm_plug_action(plug, PREPARE, 0))<0)
                return err;
        return 0;
 }
 
-static int snd_pcm_plug_stream_go(snd_pcm_t *pcm, int stream)
+static int snd_pcm_plug_go(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       return snd_pcm_stream_go(plug->slave, stream);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       return snd_pcm_go(plug->slave);
 }
 
-static int snd_pcm_plug_sync_go(snd_pcm_t *pcm, int stream UNUSED, snd_pcm_sync_t *sync)
+static int snd_pcm_plug_sync_go(void *private, snd_pcm_sync_t *sync)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        return snd_pcm_sync_go(plug->slave, sync);
 }
 
-static int snd_pcm_plug_stream_drain(snd_pcm_t *pcm, int stream)
+static int snd_pcm_plug_drain(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        int err;
 
-       if ((err = snd_pcm_stream_drain(plug->slave, stream)) < 0)
+       if ((err = snd_pcm_drain(plug->slave)) < 0)
                return err;
-       if (snd_pcm_plug_direct(pcm, stream))
-               return 0;
-       if ((err = snd_pcm_plug_action(pcm, stream, DRAIN, 0))<0)
+       if ((err = snd_pcm_plug_action(plug, DRAIN, 0))<0)
                return err;
        return 0;
 }
 
-static int snd_pcm_plug_stream_flush(snd_pcm_t *pcm, int stream)
+static int snd_pcm_plug_flush(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        int err;
 
-       if ((err = snd_pcm_stream_flush(plug->slave, stream)) < 0)
+       if ((err = snd_pcm_flush(plug->slave)) < 0)
                return err;
-       if (snd_pcm_plug_direct(pcm, stream))
-               return 0;
-       if ((err = snd_pcm_plug_action(pcm, stream, FLUSH, 0))<0)
+       if ((err = snd_pcm_plug_action(plug, FLUSH, 0))<0)
                return err;
        return 0;
 }
 
-static int snd_pcm_plug_stream_pause(snd_pcm_t *pcm, int stream, int enable)
+static int snd_pcm_plug_pause(void *private, int enable)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        int err;
        
-       if ((err = snd_pcm_stream_pause(plug->slave, stream, enable)) < 0)
+       if ((err = snd_pcm_pause(plug->slave, enable)) < 0)
                return err;
-       if ((err = snd_pcm_plug_action(pcm, stream, PAUSE, 0))<0)
+       if ((err = snd_pcm_plug_action(plug, PAUSE, 0))<0)
                return err;
        return 0;
 }
 
-static int snd_pcm_plug_channel_setup(snd_pcm_t *pcm, int stream, snd_pcm_channel_setup_t *setup)
+static int snd_pcm_plug_channel_setup(void *private UNUSED, snd_pcm_channel_setup_t *setup UNUSED)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-
-       if (snd_pcm_plug_direct(pcm, stream))
-               return snd_pcm_channel_setup(plug->slave, stream, setup);
        /* FIXME: non mmap setups */
        return -ENXIO;
 }
 
-static ssize_t snd_pcm_plug_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset)
+static ssize_t snd_pcm_plug_frame_data(void *private, 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_frame_data(plug->slave, stream, offset);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
        if (offset < 0) {
-               offset = snd_pcm_plug_slave_size(pcm, stream, -offset);
+               offset = snd_pcm_plug_slave_size(plug, -offset);
                if (offset < 0)
                        return offset;
                offset = -offset;
        } else {
-               offset = snd_pcm_plug_slave_size(pcm, stream, offset);
+               offset = snd_pcm_plug_slave_size(plug, offset);
                if (offset < 0)
                        return offset;
        }
-       ret = snd_pcm_stream_frame_data(plug->slave, stream, offset);
+       ret = snd_pcm_frame_data(plug->slave, offset);
        if (ret < 0)
                return ret;
-       return snd_pcm_plug_client_size(pcm, stream, ret);
+       return snd_pcm_plug_client_size(plug, ret);
 }
   
-ssize_t snd_pcm_plug_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count)
+ssize_t snd_pcm_plug_writev(void *private, const struct iovec *vector, unsigned long count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK];
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_t *handle = plug->handle;
        unsigned int k, step, channels;
-       int size = 0;
-       if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_PLAYBACK))
-               return snd_pcm_writev(plug->slave, vector, count);
-       channels = str->setup.format.channels;
-       if (str->setup.format.interleave)
+       size_t size = 0;
+       assert(plug->frames_alloc);
+       channels = handle->setup.format.channels;
+       if (handle->setup.format.interleave)
                step = 1;
        else {
                step = channels;
                assert(count % channels == 0);
        }
-       for (k = 0; k < count; k += step, vector += step) {
+       for (k = 0; k < count; k += step) {
                snd_pcm_plugin_channel_t *channels;
-               int expected, ret;
-               expected = snd_pcm_plug_client_channels_iovec(pcm, SND_PCM_STREAM_PLAYBACK, vector, count, &channels);
-               if (expected < 0)
-                       return expected;
-               ret = snd_pcm_plug_write_transfer(pcm, channels, expected);
-               if (ret < 0) {
-                       if (size > 0)
-                               return size;
-                       return ret;
+               ssize_t frames;
+               frames = snd_pcm_plug_client_channels_iovec(plug, vector, count, &channels);
+               if (frames < 0)
+                       return frames;
+               while (1) {
+                       unsigned int c;
+                       ssize_t ret;
+                       size_t frames1 = frames;
+                       if (frames1 > plug->frames_alloc)
+                               frames1 = plug->frames_alloc;
+                       ret = snd_pcm_plug_write_transfer(plug, channels, frames1);
+                       if (ret < 0) {
+                               if (size > 0)
+                                       return size;
+                               return ret;
+                       }
+                       size += ret;
+                       frames -= ret;
+                       if (frames == 0)
+                               break;
+                       for (c = 0; c < handle->setup.format.channels; ++c)
+                               channels[c].area.addr += ret * channels[c].area.step / 8;
                }
-               size += ret;
-               if (ret != expected)
-                       return size;
        }
        return size;
 }
 
-ssize_t snd_pcm_plug_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count)
+ssize_t snd_pcm_plug_readv(void *private, const struct iovec *vector, unsigned long count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE];
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_t *handle = plug->handle;
        unsigned int k, step, channels;
-       int size = 0;
-       if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_CAPTURE))
-               return snd_pcm_readv(plug->slave, vector, count);
-       channels = str->setup.format.channels;
-       if (str->setup.format.interleave)
+       size_t size = 0;
+       assert(plug->frames_alloc);
+       channels = handle->setup.format.channels;
+       if (handle->setup.format.interleave)
                step = 1;
        else {
                step = channels;
@@ -620,135 +364,166 @@ ssize_t snd_pcm_plug_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned
        }
        for (k = 0; k < count; k += step) {
                snd_pcm_plugin_channel_t *channels;
-               int expected, ret;
-               expected = snd_pcm_plug_client_channels_iovec(pcm, SND_PCM_STREAM_CAPTURE, vector, count, &channels);
-               if (expected < 0)
-                       return expected;
-               ret = snd_pcm_plug_read_transfer(pcm, channels, expected);
+               ssize_t frames;
+               frames = snd_pcm_plug_client_channels_iovec(plug, vector, count, &channels);
+               if (frames < 0)
+                       return frames;
+               while (1) {
+                       unsigned int c;
+                       ssize_t ret;
+                       size_t frames1 = frames;
+                       if (frames1 > plug->frames_alloc)
+                               frames1 = plug->frames_alloc;
+                       ret = snd_pcm_plug_read_transfer(plug, channels, frames1);
+                       if (ret < 0) {
+                               if (size > 0)
+                                       return size;
+                               return ret;
+                       }
+                       size += ret;
+                       frames -= ret;
+                       if (frames == 0)
+                               break;
+                       for (c = 0; c < handle->setup.format.channels; ++c)
+                               channels[c].area.addr += ret * channels[c].area.step / 8;
+               }
+       }
+       return size;
+}
+
+ssize_t snd_pcm_plug_write(void *private, const void *buf, size_t count)
+{
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_t *handle = plug->handle;
+       ssize_t frames;
+       snd_pcm_plugin_channel_t *channels;
+       size_t size = 0;
+       assert(plug->frames_alloc);
+       frames = snd_pcm_plug_client_channels_buf(plug, (char *)buf, count, &channels);
+       if (frames < 0)
+               return frames;
+
+       while (1) {
+               unsigned int c;
+               ssize_t ret;
+               size_t frames1 = frames;
+               if (frames1 > plug->frames_alloc)
+                       frames1 = plug->frames_alloc;
+               ret = snd_pcm_plug_write_transfer(plug, channels, frames1);
                if (ret < 0) {
                        if (size > 0)
                                return size;
                        return ret;
                }
                size += ret;
-               if (ret != expected)
-                       return size;
+               frames -= ret;
+               if (frames == 0)
+                       break;
+               for (c = 0; c < handle->setup.format.channels; ++c)
+                       channels[c].area.addr += ret * channels[c].area.step / 8;
        }
        return size;
 }
 
-ssize_t snd_pcm_plug_write(snd_pcm_t *pcm, const void *buf, size_t count)
+ssize_t snd_pcm_plug_read(void *private, void *buf, size_t count)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       int expected;
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       snd_pcm_t *handle = plug->handle;
+       ssize_t frames;
        snd_pcm_plugin_channel_t *channels;
-
-       if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_PLAYBACK))
-               return snd_pcm_write(plug->slave, buf, count);
-       expected = snd_pcm_plug_client_channels_buf(pcm, SND_PCM_STREAM_PLAYBACK, (char *)buf, count, &channels);
-       if (expected < 0)
-               return expected;
-        return snd_pcm_plug_write_transfer(pcm, channels, expected);
-}
-
-ssize_t snd_pcm_plug_read(snd_pcm_t *pcm, void *buf, size_t count)
-{
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       int expected;
-       snd_pcm_plugin_channel_t *channels;
-
-       if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_CAPTURE))
-               return snd_pcm_read(plug->slave, buf, count);
-       expected = snd_pcm_plug_client_channels_buf(pcm, SND_PCM_STREAM_CAPTURE, buf, count, &channels);
-       if (expected < 0)
-               return expected;
-       return snd_pcm_plug_read_transfer(pcm, channels, expected);
+       size_t size = 0;
+       assert(plug->frames_alloc);
+       frames = snd_pcm_plug_client_channels_buf(plug, buf, count, &channels);
+       if (frames < 0)
+               return frames;
+
+       while (1) {
+               unsigned int c;
+               ssize_t ret;
+               size_t frames1 = frames;
+               if (frames1 > plug->frames_alloc)
+                       frames1 = plug->frames_alloc;
+               ret = snd_pcm_plug_read_transfer(plug, channels, frames1);
+               if (ret < 0) {
+                       if (size > 0)
+                               return size;
+                       return ret;
+               }
+               size += ret;
+               frames -= ret;
+               if (frames == 0)
+                       break;
+               for (c = 0; c < handle->setup.format.channels; ++c)
+                       channels[c].area.addr += ret * channels[c].area.step / 8;
+       }
+       return size;
 }
 
-static int snd_pcm_plug_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status)
+static int snd_pcm_plug_mmap_status(void *private UNUSED, 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_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)
+static int snd_pcm_plug_mmap_control(void *private UNUSED, 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))
-               return snd_pcm_mmap_control(plug->slave, stream, control);
        return -EBADFD;
 }
 
-static int snd_pcm_plug_mmap_data(snd_pcm_t *pcm, int stream, void **buffer, size_t bsize UNUSED)
+static int snd_pcm_plug_mmap_data(void *private UNUSED, void **buffer UNUSED, size_t bsize UNUSED)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       if (snd_pcm_plug_direct(pcm, stream))
-               return snd_pcm_mmap_data(plug->slave, stream, buffer);
        return -EBADFD;
 }
 
-static int snd_pcm_plug_munmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t *status UNUSED)
+static int snd_pcm_plug_munmap_status(void *private UNUSED, 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)
+static int snd_pcm_plug_munmap_control(void *private UNUSED, 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))
-               return snd_pcm_munmap_control(plug->slave, stream);
        return -EBADFD;
 }
                
-static int snd_pcm_plug_munmap_data(snd_pcm_t *pcm, int stream, void *buffer UNUSED, size_t size UNUSED)
+static int snd_pcm_plug_munmap_data(void *private UNUSED, void *buffer UNUSED, size_t size UNUSED)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       if (snd_pcm_plug_direct(pcm, stream))
-               return snd_pcm_munmap_data(plug->slave, stream);
        return -EBADFD;
 }
                
-static int snd_pcm_plug_channels_mask(snd_pcm_t *pcm, int stream,
+static int snd_pcm_plug_channels_mask(void *private,
                                    bitset_t *client_vmask)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       if (snd_pcm_plug_direct(pcm, stream))
-               return snd_pcm_channels_mask(plug->slave, stream, client_vmask);
-       if (stream == SND_PCM_STREAM_PLAYBACK)
-               return snd_pcm_plug_playback_channels_mask(pcm, client_vmask);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK)
+               return snd_pcm_plug_playback_channels_mask(plug, client_vmask);
        else
-               return snd_pcm_plug_capture_channels_mask(pcm, client_vmask);
+               return snd_pcm_plug_capture_channels_mask(plug, client_vmask);
 }
 
-int snd_pcm_plug_file_descriptor(snd_pcm_t* pcm, int stream)
+int snd_pcm_plug_file_descriptor(void *private)
 {
-       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private;
-       return snd_pcm_file_descriptor(plug->slave, stream);
+       snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+       return snd_pcm_file_descriptor(plug->slave);
 }
 
+static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params);
+
 struct snd_pcm_ops snd_pcm_plug_ops = {
-       stream_close: snd_pcm_plug_stream_close,
-       stream_nonblock: snd_pcm_plug_stream_nonblock,
+       close: snd_pcm_plug_close,
+       nonblock: snd_pcm_plug_nonblock,
        info: snd_pcm_plug_info,
-       stream_info: snd_pcm_plug_stream_info,
-       stream_params: snd_pcm_plug_stream_params,
-       stream_setup: snd_pcm_plug_stream_setup,
+       params: snd_pcm_plug_params,
+       setup: snd_pcm_plug_setup,
        channel_setup: snd_pcm_plug_channel_setup,
-       stream_status: snd_pcm_plug_stream_status,
-       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,
+       status: snd_pcm_plug_status,
+       frame_io: snd_pcm_plug_frame_io,
+       state: snd_pcm_plug_state,
+       prepare: snd_pcm_plug_prepare,
+       go: snd_pcm_plug_go,
        sync_go: snd_pcm_plug_sync_go,
-       stream_drain: snd_pcm_plug_stream_drain,
-       stream_flush: snd_pcm_plug_stream_flush,
-       stream_pause: snd_pcm_plug_stream_pause,
-       stream_frame_data: snd_pcm_plug_stream_frame_data,
+       drain: snd_pcm_plug_drain,
+       flush: snd_pcm_plug_flush,
+       pause: snd_pcm_plug_pause,
+       frame_data: snd_pcm_plug_frame_data,
        write: snd_pcm_plug_write,
        writev: snd_pcm_plug_writev,
        read: snd_pcm_plug_read,
@@ -763,38 +538,145 @@ struct snd_pcm_ops snd_pcm_plug_ops = {
        channels_mask: snd_pcm_plug_channels_mask,
 };
 
-int snd_pcm_plug_connect(snd_pcm_t **handle, snd_pcm_t *slave, int mode, int close_slave)
+static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
 {
-       snd_pcm_t *pcm;
+       snd_pcm_params_t slave_params, params1;
+       snd_pcm_info_t slave_info;
+       snd_pcm_plugin_t *plugin;
        snd_pcm_plug_t *plug;
        int err;
-       err = snd_pcm_abstract_open(handle, mode, SND_PCM_TYPE_PLUG, sizeof(snd_pcm_plug_t));
+       
+       plug = (snd_pcm_plug_t*) private;
+
+       /*
+        *  try to decide, if a conversion is required
+         */
+
+       memset(&slave_info, 0, sizeof(slave_info));
+       slave_info.stream = plug->slave->stream;
+       if ((err = snd_pcm_info(plug->slave, &slave_info)) < 0) {
+               snd_pcm_plug_clear(plug);
+               return err;
+       }
+
+       if ((err = snd_pcm_plug_slave_params(params, &slave_info, &slave_params)) < 0)
+               return err;
+
+
+       snd_pcm_plug_clear(plug);
+
+       /* add necessary plugins */
+       params1 = *params;
+       if ((err = snd_pcm_plug_format(plug, &params1, &slave_params)) < 0)
+               return err;
+
+       if (!plug->first) {
+               err = snd_pcm_params(plug->slave, params);
+               if (err < 0)
+                       return err;
+               *plug->handle->ops = *plug->slave->ops;
+               plug->handle->ops->params = snd_pcm_plug_params;
+               plug->handle->ops->setup = snd_pcm_plug_setup;
+               plug->handle->ops->info = snd_pcm_plug_info;
+               plug->handle->op_arg = plug->slave->op_arg;
+               return 0;
+       } else {
+               *plug->handle->ops = snd_pcm_plug_ops;
+               plug->handle->op_arg = plug;
+       }
+
+       /* compute right sizes */
+       slave_params.frag_size = snd_pcm_plug_slave_size(plug, params1.frag_size);
+       slave_params.buffer_size = snd_pcm_plug_slave_size(plug, params1.buffer_size);
+       slave_params.frames_fill_max = snd_pcm_plug_slave_size(plug, params1.frames_fill_max);
+       slave_params.frames_min = snd_pcm_plug_slave_size(plug, params1.frames_min);
+       slave_params.frames_xrun_max = snd_pcm_plug_slave_size(plug, params1.frames_xrun_max);
+       slave_params.frames_align = snd_pcm_plug_slave_size(plug, params1.frames_align);
+       if (slave_params.frame_boundary == 0 || slave_params.frame_boundary > INT_MAX)
+               slave_params.frame_boundary = INT_MAX;
+       assert(params->buffer_size > 0);
+       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.frame_boundary *= slave_params.buffer_size;
+
+       /*
+        *  I/O plugins
+        */
+
+       if (slave_info.flags & SND_PCM_INFO_MMAP) {
+               pdprintf("params mmap plugin\n");
+               err = snd_pcm_plugin_build_mmap(plug, &slave_params.format, &plugin);
+       } else {
+               pdprintf("params I/O plugin\n");
+               err = snd_pcm_plugin_build_io(plug, &slave_params.format, &plugin);
+       }
+       if (err < 0)
+               return err;
+       if (plug->slave->stream == SND_PCM_STREAM_PLAYBACK) {
+               err = snd_pcm_plugin_append(plugin);
+       } else {
+               err = snd_pcm_plugin_insert(plugin);
+       }
        if (err < 0) {
-               if (close_slave)
-                       snd_pcm_close(slave);
+               snd_pcm_plugin_free(plugin);
                return err;
        }
-       pcm = *handle;
-       pcm->ops = &snd_pcm_plug_ops;
-        plug = (snd_pcm_plug_t*) &pcm->private;
+
+       pdprintf("params requested params: format = %i, rate = %i, channels = %i\n", slave_params.format.format, slave_params.format.rate, slave_params.format.channels);
+       err = snd_pcm_params(plug->slave, &slave_params);
+       if (err < 0)
+               return err;
+
+       err = snd_pcm_plug_action(plug, INIT, 0);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+int snd_pcm_plug_create(snd_pcm_t **handlep, snd_pcm_t *slave, int close_slave)
+{
+       snd_pcm_t *handle;
+       snd_pcm_plug_t *plug;
+       handle = calloc(1, sizeof(snd_pcm_t));
+       if (!handle)
+               return -ENOMEM;
+       plug = calloc(1, sizeof(snd_pcm_plug_t));
+       if (!plug) {
+               free(handle);
+               return -ENOMEM;
+       }
+       plug->handle = handle;
        plug->slave = slave;
        plug->close_slave = close_slave;
+       handle->type = SND_PCM_TYPE_PLUG;
+       handle->stream = slave->stream;
+       handle->ops = malloc(sizeof(*handle->ops));
+       *handle->ops = *slave->ops;
+       handle->ops->params = snd_pcm_plug_params;
+       handle->ops->setup = snd_pcm_plug_setup;
+       handle->ops->info = snd_pcm_plug_info;
+       handle->op_arg = slave->op_arg;
+       handle->mode = slave->mode;
+       handle->private = plug;
+       *handlep = handle;
        return 0;
 }
 
-int snd_pcm_plug_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode)
+int snd_pcm_plug_open_subdevice(snd_pcm_t **handlep, int card, int device, int subdevice, int stream, int mode)
 {
        snd_pcm_t *slave;
        int err;
-       err = snd_pcm_open_subdevice(&slave, card, device, subdevice, mode);
+       err = snd_pcm_hw_open_subdevice(&slave, card, device, subdevice, stream, mode);
        if (err < 0)
                return err;
-       return snd_pcm_plug_connect(handle, slave, mode, 1);
+       return snd_pcm_plug_create(handlep, slave, 1);
 }
 
-int snd_pcm_plug_open(snd_pcm_t **handle, int card, int device, int mode)
+int snd_pcm_plug_open(snd_pcm_t **handlep, int card, int device, int stream, int mode)
 {
-       return snd_pcm_plug_open_subdevice(handle, card, device, -1, mode);
+       return snd_pcm_plug_open_subdevice(handlep, card, device, -1, stream, mode);
 }
 
 
index 13cb76d162c71e707cf0dde09e4f44a95667a68f..4b7a9ce250d67b1396fd51c978ba451ad1339fa2 100644 (file)
@@ -372,8 +372,7 @@ static int adpcm_action(snd_pcm_plugin_t * plugin,
        return 0;       /* silenty ignore other actions */
 }
 
-int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle,
-                              int stream,
+int snd_pcm_plugin_build_adpcm(snd_pcm_plug_t *plug,
                               snd_pcm_format_t *src_format,
                               snd_pcm_format_t *dst_format,
                               snd_pcm_plugin_t **r_plugin)
@@ -402,10 +401,8 @@ int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle,
                assert(0);
        assert(snd_pcm_format_linear(format->format));
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "Ima-ADPCM<->linear conversion",
-                                  src_format,
-                                  dst_format,
+       err = snd_pcm_plugin_build(plug, "Ima-ADPCM<->linear conversion",
+                                  src_format, dst_format,
                                   sizeof(adpcm_t) + src_format->channels * sizeof(adpcm_channel_t),
                                   &plugin);
        if (err < 0)
index 5357c207111801caf2e29fda2980b7e1d315da67..b563b01b93b11b738e09ba46bb33b5834eddb83a 100644 (file)
@@ -248,8 +248,7 @@ static ssize_t alaw_transfer(snd_pcm_plugin_t *plugin,
         return frames;
 }
 
-int snd_pcm_plugin_build_alaw(snd_pcm_plugin_handle_t *handle,
-                             int stream,
+int snd_pcm_plugin_build_alaw(snd_pcm_plug_t *plug,
                              snd_pcm_format_t *src_format,
                              snd_pcm_format_t *dst_format,
                              snd_pcm_plugin_t **r_plugin)
@@ -278,12 +277,9 @@ int snd_pcm_plugin_build_alaw(snd_pcm_plugin_handle_t *handle,
                assert(0);
        assert(snd_pcm_format_linear(format->format));
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "A-Law<->linear conversion",
-                                  src_format,
-                                  dst_format,
-                                  sizeof(alaw_t),
-                                  &plugin);
+       err = snd_pcm_plugin_build(plug, "A-Law<->linear conversion",
+                                  src_format, dst_format,
+                                  sizeof(alaw_t), &plugin);
        if (err < 0)
                return err;
        data = (alaw_t*)plugin->extra_data;
index 63ef714b7a42c02bea6a70d7fd0452c1f9ae271d..de4762dd7879dd4ae585fac720fc3a74b7220398 100644 (file)
@@ -65,8 +65,7 @@ static ssize_t copy_transfer(snd_pcm_plugin_t *plugin,
        return frames;
 }
 
-int snd_pcm_plugin_build_copy(snd_pcm_plugin_handle_t *handle,
-                             int stream,
+int snd_pcm_plugin_build_copy(snd_pcm_plug_t *plug,
                              snd_pcm_format_t *src_format,
                              snd_pcm_format_t *dst_format,
                              snd_pcm_plugin_t **r_plugin)
@@ -85,12 +84,8 @@ int snd_pcm_plugin_build_copy(snd_pcm_plugin_handle_t *handle,
        width = snd_pcm_format_physical_width(src_format->format);
        assert(width > 0);
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "copy",
-                                  src_format,
-                                  dst_format,
-                                  0,
-                                  &plugin);
+       err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format,
+                                  0, &plugin);
        if (err < 0)
                return err;
        plugin->transfer = copy_transfer;
index d7c7e4b8a5d7f4848168c8a70921637c6453b4fd..a449ec672f028f2c2dbfc0f9c2830937eff89e44 100644 (file)
 #include "../../include/driver.h"
 #include "../../include/pcm.h"
 #include "../../include/pcm_plugin.h"
-#define snd_pcm_write(handle,buf,count) snd_pcm_oss_write3(handle,buf,count,1)
-#define snd_pcm_writev(handle,vec,count) snd_pcm_oss_writev3(handle,vec,count,1)
-#define snd_pcm_read(handle,buf,count) snd_pcm_oss_read3(handle,buf,count,1)
-#define snd_pcm_readv(handle,vec,count) snd_pcm_oss_readv3(handle,vec,count,1)
+#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
+#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
+#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
+#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
 #else
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <sys/uio.h>
 #include "../pcm_local.h"
+#define pcm_write(plug,buf,count) snd_pcm_write(plug->slave,buf,count)
+#define pcm_writev(plug,vec,count) snd_pcm_writev(plug->slave,vec,count)
+#define pcm_read(plug,buf,count) snd_pcm_read(plug->slave,buf,count)
+#define pcm_readv(plug,vec,count) snd_pcm_readv(plug->slave,vec,count)
 #endif
 
 /*
  *  Basic io plugin
  */
  
-typedef struct io_private_data {
-       snd_pcm_plugin_handle_t *slave;
-} io_t;
-
-static ssize_t io_transfer(snd_pcm_plugin_t *plugin,
-                             const snd_pcm_plugin_channel_t *src_channels,
-                             snd_pcm_plugin_channel_t *dst_channels,
-                             size_t frames)
+static ssize_t io_playback_transfer(snd_pcm_plugin_t *plugin,
+                                   const snd_pcm_plugin_channel_t *src_channels,
+                                   snd_pcm_plugin_channel_t *dst_channels UNUSED,
+                                   size_t frames)
 {
-       io_t *data;
        struct iovec *vec;
        int count, channel;
 
        assert(plugin);
-       data = (io_t *)plugin->extra_data;
-       assert(data);
-       vec = (struct iovec *)((char *)data + sizeof(*data));
-       if (plugin->stream == SND_PCM_STREAM_PLAYBACK) {
-               assert(src_channels);
-               count = plugin->src_format.channels;
-               if (plugin->src_format.interleave) {
-                       return snd_pcm_write(data->slave, src_channels->area.addr, frames);
-               } else {
-                       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 = frames;
-                       }
-                       return snd_pcm_writev(data->slave, vec, count);
-               }
-       } else if (plugin->stream == SND_PCM_STREAM_CAPTURE) {
-               assert(dst_channels);
-               count = plugin->dst_format.channels;
-               if (plugin->dst_format.interleave) {
-                       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 {
-                       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 = frames;
-                       }
-                       return snd_pcm_readv(data->slave, vec, count);
+       vec = (struct iovec *)plugin->extra_data;
+       assert(vec);
+       assert(src_channels);
+       count = plugin->src_format.channels;
+       if (plugin->src_format.interleave) {
+               return pcm_write(plugin->plug, src_channels->area.addr, frames);
+       } else {
+               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 = frames;
                }
+               return pcm_writev(plugin->plug, vec, count);
+       }
+}
+static ssize_t io_capture_transfer(snd_pcm_plugin_t *plugin,
+                                  const snd_pcm_plugin_channel_t *src_channels UNUSED,
+                                  snd_pcm_plugin_channel_t *dst_channels,
+                                  size_t frames)
+{
+       struct iovec *vec;
+       int count, channel;
+
+       assert(plugin);
+       vec = (struct iovec *)plugin->extra_data;
+       assert(vec);
+       assert(dst_channels);
+       count = plugin->dst_format.channels;
+       if (plugin->dst_format.interleave) {
+               return pcm_read(plugin->plug, dst_channels->area.addr, frames);
        } else {
-               assert(0);
+               for (channel = 0; channel < count; channel++) {
+                       if (dst_channels[channel].enabled)
+                               vec[channel].iov_base = dst_channels[channel].area.addr;
+                       else
+                               vec[channel].iov_base = 0;
+                       vec[channel].iov_len = frames;
+               }
+               return pcm_readv(plugin->plug, vec, count);
        }
        return 0;
 }
@@ -109,36 +111,37 @@ static ssize_t io_src_channels(snd_pcm_plugin_t *plugin,
        if (err < 0)
                return err;
        *channels = v;
-       for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v)
-               v->wanted = 1;
+       if (plugin->src_format.interleave) {
+               for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v)
+                       v->wanted = 1;
+       }
        return frames;
 }
 
-int snd_pcm_plugin_build_io(snd_pcm_plugin_handle_t *pcm,
-                              int stream,
-                              snd_pcm_plugin_handle_t *slave,
-                              snd_pcm_format_t *format,
-                              snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug,
+                           snd_pcm_format_t *format,
+                           snd_pcm_plugin_t **r_plugin)
 {
        int err;
-       io_t *data;
        snd_pcm_plugin_t *plugin;
 
        assert(r_plugin);
        *r_plugin = NULL;
-       assert(pcm && format);
-       err = snd_pcm_plugin_build(pcm, stream,
-                                  "I/O io",
+       assert(plug && format);
+       err = snd_pcm_plugin_build(plug, "I/O io",
                                   format, format,
-                                  sizeof(io_t) + sizeof(struct iovec) * format->channels,
+                                  sizeof(struct iovec) * format->channels,
                                   &plugin);
        if (err < 0)
                return err;
-       data = (io_t *)plugin->extra_data;
-       data->slave = slave;
-       plugin->transfer = io_transfer;
-       if (format->interleave && stream == SND_PCM_STREAM_PLAYBACK)
-               plugin->client_channels = io_src_channels;
+       if (snd_pcm_plug_stream(plug) == SND_PCM_STREAM_PLAYBACK) {
+               plugin->transfer = io_playback_transfer;
+               if (format->interleave)
+                       plugin->client_channels = io_src_channels;
+       } else {
+               plugin->transfer = io_capture_transfer;
+       }
+
        *r_plugin = plugin;
        return 0;
 }
index 2ede815e8396ae9010435fedea8f163afb1e3a6e..83b5e9b709e718aa332d3b5b192f49224031de4e 100644 (file)
@@ -131,8 +131,7 @@ int conv_index(int src_format, int dst_format)
        return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian;
 }
 
-int snd_pcm_plugin_build_linear(snd_pcm_plugin_handle_t *handle,
-                               int stream,
+int snd_pcm_plugin_build_linear(snd_pcm_plug_t *plug,
                                snd_pcm_format_t *src_format,
                                snd_pcm_format_t *dst_format,
                                snd_pcm_plugin_t **r_plugin)
@@ -149,12 +148,9 @@ int snd_pcm_plugin_build_linear(snd_pcm_plugin_handle_t *handle,
        assert(snd_pcm_format_linear(src_format->format) &&
               snd_pcm_format_linear(dst_format->format));
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "linear format conversion",
-                                  src_format,
-                                  dst_format,
-                                  sizeof(linear_t),
-                                  &plugin);
+       err = snd_pcm_plugin_build(plug, "linear format conversion",
+                                  src_format, dst_format,
+                                  sizeof(linear_t), &plugin);
        if (err < 0)
                return err;
        data = (linear_t *)plugin->extra_data;
index 2f46bd9b1af4d7d92b0b1fcafa16b99a341c25d8..5bfb2193a8346b3b12921c3446d2c70a2cb1361b 100644 (file)
@@ -34,7 +34,6 @@
  */
  
 typedef struct mmap_private_data {
-       snd_pcm_t *slave;
        void *buffer;
 #if 0
        char *silence;
@@ -49,42 +48,42 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin,
        mmap_t *data;
         snd_pcm_plugin_channel_t *sv;
        snd_pcm_channel_area_t *dv;
-       snd_pcm_stream_t *stream;
-       snd_pcm_stream_setup_t *setup;
+       snd_pcm_t *stream;
+       snd_pcm_setup_t *setup;
        size_t pos;
        int ready;
        unsigned int channel;
 
        assert(plugin && channels);
        data = (mmap_t *)plugin->extra_data;
-       stream = &data->slave->stream[plugin->stream];
+       stream = plugin->plug->slave;
 
        setup = &stream->setup;
-       if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) < SND_PCM_STATE_PREPARED)
+       if (snd_pcm_mmap_state(stream) < SND_PCM_STATE_PREPARED)
                return -EBADFD;
 
-       ready = snd_pcm_mmap_ready(data->slave, plugin->stream);
+       ready = snd_pcm_mmap_ready(stream);
        if (ready < 0)
                return ready;
        if (!ready) {
                struct pollfd pfd;
-               if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) != SND_PCM_STATE_RUNNING)
+               if (snd_pcm_mmap_state(stream) != SND_PCM_STATE_RUNNING)
                        return -EPIPE;
                if (stream->mode & SND_PCM_NONBLOCK)
                        return -EAGAIN;
-               pfd.fd = snd_pcm_file_descriptor(data->slave, plugin->stream);
+               pfd.fd = snd_pcm_file_descriptor(stream);
                pfd.events = POLLOUT | POLLERR;
                ready = poll(&pfd, 1, 10000);
                if (ready < 0)
                        return ready;
                if (ready && pfd.revents & POLLERR)
                        return -EPIPE;
-               assert(snd_pcm_mmap_ready(data->slave, plugin->stream));
+               assert(snd_pcm_mmap_ready(stream));
        }
-       pos = snd_pcm_mmap_frames_offset(data->slave, plugin->stream);
+       pos = snd_pcm_mmap_frames_offset(stream);
        assert(pos % setup->frames_align == 0);
 
-       sv = plugin->src_channels;
+       sv = plugin->buf_channels;
        dv = stream->channels;
        *channels = sv;
        for (channel = 0; channel < plugin->src_format.channels; ++channel) {
@@ -94,78 +93,76 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin,
 #else
                sv->wanted = 1;
 #endif
-               sv->aptr = 0;
                sv->area.addr = dv->addr + dv->step * pos / 8;
                sv->area.first = dv->first;
                sv->area.step = dv->step;
                ++sv;
                ++dv;
        }
-       return snd_pcm_mmap_frames_xfer(data->slave, plugin->stream, frames);
+       return snd_pcm_mmap_frames_xfer(stream, frames);
 }
 
 static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin,
-                              size_t frames,
-                              snd_pcm_plugin_channel_t **channels)
+                                size_t frames,
+                                snd_pcm_plugin_channel_t **channels)
 {
        mmap_t *data;
        int err;
        unsigned int channel;
         snd_pcm_plugin_channel_t *dv;
        snd_pcm_channel_area_t *sv;
-       snd_pcm_stream_t *stream;
-       snd_pcm_stream_setup_t *setup;
+       snd_pcm_t *stream;
+       snd_pcm_setup_t *setup;
        size_t pos;
        int ready;
 
        assert(plugin && channels);
        data = (mmap_t *)plugin->extra_data;
-       stream = &data->slave->stream[plugin->stream];
+       stream = plugin->plug->slave;
 
        setup = &stream->setup;
-       if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) < SND_PCM_STATE_PREPARED)
+       if (snd_pcm_mmap_state(stream) < SND_PCM_STATE_PREPARED)
                return -EBADFD;
-       if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) == SND_PCM_STATE_PREPARED &&
+       if (snd_pcm_mmap_state(stream) == SND_PCM_STATE_PREPARED &&
            stream->setup.start_mode == SND_PCM_START_DATA) {
-               err = snd_pcm_stream_go(data->slave, plugin->stream);
+               err = snd_pcm_go(stream);
                if (err < 0)
                        return err;
        }
-       ready = snd_pcm_mmap_ready(data->slave, plugin->stream);
+       ready = snd_pcm_mmap_ready(stream);
        if (ready < 0)
                return ready;
        if (!ready) {
                struct pollfd pfd;
-               if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) != SND_PCM_STATE_RUNNING)
+               if (snd_pcm_mmap_state(stream) != SND_PCM_STATE_RUNNING)
                        return -EPIPE;
                if (stream->mode & SND_PCM_NONBLOCK)
                        return -EAGAIN;
-               pfd.fd = snd_pcm_file_descriptor(data->slave, plugin->stream);
+               pfd.fd = snd_pcm_file_descriptor(stream);
                pfd.events = POLLIN | POLLERR;
                ready = poll(&pfd, 1, 10000);
                if (ready < 0)
                        return ready;
                if (ready && pfd.revents & POLLERR)
                        return -EPIPE;
-               assert(snd_pcm_mmap_ready(data->slave, plugin->stream));
+               assert(snd_pcm_mmap_ready(stream));
        }
-       pos = snd_pcm_mmap_frames_offset(data->slave, plugin->stream);
+       pos = snd_pcm_mmap_frames_offset(stream);
        assert(pos % setup->frames_align == 0);
 
        sv = stream->channels;
-       dv = plugin->dst_channels;
+       dv = plugin->buf_channels;
        *channels = dv;
        for (channel = 0; channel < plugin->dst_format.channels; ++channel) {
                dv->enabled = 1;
                dv->wanted = 0;
-               dv->aptr = 0;
                dv->area.addr = sv->addr + sv->step * pos / 8;
                dv->area.first = sv->first;
                dv->area.step = sv->step;
                ++sv;
                ++dv;
        }
-       return snd_pcm_mmap_frames_xfer(data->slave, plugin->stream, frames);
+       return snd_pcm_mmap_frames_xfer(stream, frames);
 }
 
 static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin,
@@ -174,15 +171,15 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin,
                                      size_t frames)
 {
        mmap_t *data;
-       snd_pcm_stream_setup_t *setup;
-       snd_pcm_stream_t *str;
+       snd_pcm_setup_t *setup;
+       snd_pcm_t *stream;
        int err;
 
        assert(plugin && plugin->prev);
        assert(src_channels);
        data = (mmap_t *)plugin->extra_data;
-       str = &data->slave->stream[SND_PCM_STREAM_PLAYBACK];
-       setup = &str->setup;
+       stream = plugin->plug->slave;
+       setup = &stream->setup;
 
 #if 0
        for (channel = 0; channel < plugin->src_format.channels; channel++) {
@@ -191,12 +188,12 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin,
        }
 #endif
 
-       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)))) {
-               err = snd_pcm_stream_go(data->slave, plugin->stream);
+       snd_pcm_frame_data(stream, frames);
+       if (snd_pcm_mmap_state(stream) == SND_PCM_STATE_PREPARED &&
+           (setup->start_mode == SND_PCM_START_DATA ||
+            (setup->start_mode == SND_PCM_START_FULL &&
+             !snd_pcm_mmap_ready(stream)))) {
+               err = snd_pcm_go(stream);
                if (err < 0)
                        return err;
        }
@@ -209,14 +206,14 @@ static ssize_t mmap_capture_transfer(snd_pcm_plugin_t *plugin,
                                     size_t frames)
 {
        mmap_t *data;
-       snd_pcm_stream_t *str;
+       snd_pcm_t *stream;
 
        assert(plugin && plugin->next);
        data = (mmap_t *)plugin->extra_data;
-       str = &data->slave->stream[SND_PCM_STREAM_CAPTURE];
+       stream = plugin->plug->slave;
 
        /* FIXME: not here the increment */
-       snd_pcm_mmap_stream_frame_data(data->slave, SND_PCM_STREAM_CAPTURE, frames);
+       snd_pcm_frame_data(stream, frames);
 
        return frames;
 }
@@ -226,21 +223,23 @@ static int mmap_action(snd_pcm_plugin_t *plugin,
                       unsigned long udata UNUSED)
 {
        struct mmap_private_data *data;
+       snd_pcm_t *stream;
 
        assert(plugin);
+       stream = plugin->plug->slave;
        data = (mmap_t *)plugin->extra_data;
        if (action == INIT) {
-               snd_pcm_stream_setup_t *setup;
+               snd_pcm_setup_t *setup;
                int result;
 
                if (data->buffer) {
-                       snd_pcm_munmap(data->slave, plugin->stream);
+                       snd_pcm_munmap(stream);
                        data->buffer = 0;
                }
-               result = snd_pcm_mmap(data->slave, plugin->stream, NULL, NULL, (void **)&data->buffer);
+               result = snd_pcm_mmap(stream, NULL, NULL, (void **)&data->buffer);
                if (result < 0)
                        return result;
-               setup = &data->slave->stream[plugin->stream].setup;
+               setup = &stream->setup;
 
 #if 0
                if (plugin->stream == SND_PCM_STREAM_PLAYBACK) {
@@ -266,12 +265,10 @@ static void mmap_free(snd_pcm_plugin_t *plugin, void *private_data UNUSED)
                free(data->silence);
 #endif
        if (data->buffer)
-               snd_pcm_munmap(data->slave, plugin->stream);
+               snd_pcm_munmap(plugin->plug->slave);
 }
  
-int snd_pcm_plugin_build_mmap(snd_pcm_plugin_handle_t *pcm,
-                             int stream,
-                             snd_pcm_t *slave,
+int snd_pcm_plugin_build_mmap(snd_pcm_plug_t *plug,
                              snd_pcm_format_t *format,
                              snd_pcm_plugin_t **r_plugin)
 {
@@ -281,17 +278,15 @@ int snd_pcm_plugin_build_mmap(snd_pcm_plugin_handle_t *pcm,
 
        assert(r_plugin);
        *r_plugin = NULL;
-       assert(pcm);
-       err = snd_pcm_plugin_build(pcm, stream,
-                                  "I/O mmap",
+       assert(plug);
+       err = snd_pcm_plugin_build(plug, "I/O mmap",
                                   format, format,
                                   sizeof(mmap_t) + sizeof(snd_pcm_plugin_channel_t) * format->channels,
                                   &plugin);
        if (err < 0)
                return err;
        data = (mmap_t *)plugin->extra_data;
-       data->slave = slave;
-       if (stream == SND_PCM_STREAM_PLAYBACK) {
+       if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK) {
                plugin->client_channels = mmap_src_channels;
                plugin->transfer = mmap_playback_transfer;
        } else {
index cc46159200da06d0daf3f5cb49b745d2a78126a9..74beeb30b2dc907d60969329f5c44662a9df7122 100644 (file)
@@ -264,8 +264,7 @@ static ssize_t mulaw_transfer(snd_pcm_plugin_t *plugin,
        return frames;
 }
 
-int snd_pcm_plugin_build_mulaw(snd_pcm_plugin_handle_t *handle,
-                              int stream,
+int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *plug,
                               snd_pcm_format_t *src_format,
                               snd_pcm_format_t *dst_format,
                               snd_pcm_plugin_t **r_plugin)
@@ -296,12 +295,9 @@ int snd_pcm_plugin_build_mulaw(snd_pcm_plugin_handle_t *handle,
        }
        assert(snd_pcm_format_linear(format->format));
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "Mu-Law<->linear conversion",
-                                  src_format,
-                                  dst_format,
-                                  sizeof(mulaw_t),
-                                  &plugin);
+       err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion",
+                                  src_format, dst_format,
+                                  sizeof(mulaw_t), &plugin);
        if (err < 0)
                return err;
        data = (mulaw_t*)plugin->extra_data;
index 2383ddbdca411c095b49ccd77fe80ec7dac85e29..a7853075a7164a10f92ae09ceaeb808cc2d1db01 100644 (file)
@@ -343,8 +343,7 @@ static int rate_action(snd_pcm_plugin_t *plugin,
        return 0;       /* silenty ignore other actions */
 }
 
-int snd_pcm_plugin_build_rate(snd_pcm_plugin_handle_t *handle,
-                             int stream,
+int snd_pcm_plugin_build_rate(snd_pcm_plug_t *plug,
                              snd_pcm_format_t *src_format,
                              snd_pcm_format_t *dst_format,
                              snd_pcm_plugin_t **r_plugin)
@@ -362,10 +361,8 @@ int snd_pcm_plugin_build_rate(snd_pcm_plugin_handle_t *handle,
        assert(snd_pcm_format_linear(dst_format->format) > 0);
        assert(src_format->rate != dst_format->rate);
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "rate conversion",
-                                  src_format,
-                                  dst_format,
+       err = snd_pcm_plugin_build(plug, "rate conversion",
+                                  src_format, dst_format,
                                   sizeof(rate_t) + src_format->channels * sizeof(rate_channel_t),
                                   &plugin);
        if (err < 0)
index 4112e1f60b811395066c9eae546d5a47ac1ef3d6..b7a21d1c43ed6511006233f5218c939ba5871572 100644 (file)
@@ -534,8 +534,7 @@ int getput_index(int format)
        return width * 4 + endian * 2 + sign;
 }
 
-int snd_pcm_plugin_build_route(snd_pcm_plugin_handle_t *handle,
-                              int stream,
+int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug,
                               snd_pcm_format_t *src_format,
                               snd_pcm_format_t *dst_format,
                               route_ttable_entry_t *ttable,
@@ -551,10 +550,8 @@ int snd_pcm_plugin_build_route(snd_pcm_plugin_handle_t *handle,
        assert(snd_pcm_format_linear(src_format->format) &&
               snd_pcm_format_linear(dst_format->format));
 
-       err = snd_pcm_plugin_build(handle, stream,
-                                  "attenuated route conversion",
-                                  src_format,
-                                  dst_format,
+       err = snd_pcm_plugin_build(plug, "attenuated route conversion",
+                                  src_format, dst_format,
                                   sizeof(route_t) + sizeof(data->ttable[0]) * dst_format->channels,
                                   &plugin);
        if (err < 0)