linux/sound/core/oss/io.c
<<
>>
Prefs
   1/*
   2 *  PCM I/O Plug-In Interface
   3 *  Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
   4 *
   5 *
   6 *   This library is free software; you can redistribute it and/or modify
   7 *   it under the terms of the GNU Library General Public License as
   8 *   published by the Free Software Foundation; either version 2 of
   9 *   the License, or (at your option) any later version.
  10 *
  11 *   This program is distributed in the hope that it will be useful,
  12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *   GNU Library General Public License for more details.
  15 *
  16 *   You should have received a copy of the GNU Library General Public
  17 *   License along with this library; if not, write to the Free Software
  18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19 *
  20 */
  21  
  22#include <linux/time.h>
  23#include <sound/core.h>
  24#include <sound/pcm.h>
  25#include <sound/pcm_params.h>
  26#include "pcm_plugin.h"
  27
  28#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
  29#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
  30#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
  31#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
  32
  33/*
  34 *  Basic io plugin
  35 */
  36 
  37static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin,
  38                                    const struct snd_pcm_plugin_channel *src_channels,
  39                                    struct snd_pcm_plugin_channel *dst_channels,
  40                                    snd_pcm_uframes_t frames)
  41{
  42        if (snd_BUG_ON(!plugin))
  43                return -ENXIO;
  44        if (snd_BUG_ON(!src_channels))
  45                return -ENXIO;
  46        if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
  47                return pcm_write(plugin->plug, src_channels->area.addr, frames);
  48        } else {
  49                int channel, channels = plugin->dst_format.channels;
  50                void **bufs = (void**)plugin->extra_data;
  51                if (snd_BUG_ON(!bufs))
  52                        return -ENXIO;
  53                for (channel = 0; channel < channels; channel++) {
  54                        if (src_channels[channel].enabled)
  55                                bufs[channel] = src_channels[channel].area.addr;
  56                        else
  57                                bufs[channel] = NULL;
  58                }
  59                return pcm_writev(plugin->plug, bufs, frames);
  60        }
  61}
  62 
  63static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin,
  64                                   const struct snd_pcm_plugin_channel *src_channels,
  65                                   struct snd_pcm_plugin_channel *dst_channels,
  66                                   snd_pcm_uframes_t frames)
  67{
  68        if (snd_BUG_ON(!plugin))
  69                return -ENXIO;
  70        if (snd_BUG_ON(!dst_channels))
  71                return -ENXIO;
  72        if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
  73                return pcm_read(plugin->plug, dst_channels->area.addr, frames);
  74        } else {
  75                int channel, channels = plugin->dst_format.channels;
  76                void **bufs = (void**)plugin->extra_data;
  77                if (snd_BUG_ON(!bufs))
  78                        return -ENXIO;
  79                for (channel = 0; channel < channels; channel++) {
  80                        if (dst_channels[channel].enabled)
  81                                bufs[channel] = dst_channels[channel].area.addr;
  82                        else
  83                                bufs[channel] = NULL;
  84                }
  85                return pcm_readv(plugin->plug, bufs, frames);
  86        }
  87        return 0;
  88}
  89 
  90static snd_pcm_sframes_t io_src_channels(struct snd_pcm_plugin *plugin,
  91                             snd_pcm_uframes_t frames,
  92                             struct snd_pcm_plugin_channel **channels)
  93{
  94        int err;
  95        unsigned int channel;
  96        struct snd_pcm_plugin_channel *v;
  97        err = snd_pcm_plugin_client_channels(plugin, frames, &v);
  98        if (err < 0)
  99                return err;
 100        *channels = v;
 101        if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
 102                for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v)
 103                        v->wanted = 1;
 104        }
 105        return frames;
 106}
 107
 108int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
 109                            struct snd_pcm_hw_params *params,
 110                            struct snd_pcm_plugin **r_plugin)
 111{
 112        int err;
 113        struct snd_pcm_plugin_format format;
 114        struct snd_pcm_plugin *plugin;
 115
 116        if (snd_BUG_ON(!r_plugin))
 117                return -ENXIO;
 118        *r_plugin = NULL;
 119        if (snd_BUG_ON(!plug || !params))
 120                return -ENXIO;
 121        format.format = params_format(params);
 122        format.rate = params_rate(params);
 123        format.channels = params_channels(params);
 124        err = snd_pcm_plugin_build(plug, "I/O io",
 125                                   &format, &format,
 126                                   sizeof(void *) * format.channels,
 127                                   &plugin);
 128        if (err < 0)
 129                return err;
 130        plugin->access = params_access(params);
 131        if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
 132                plugin->transfer = io_playback_transfer;
 133                if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
 134                        plugin->client_channels = io_src_channels;
 135        } else {
 136                plugin->transfer = io_capture_transfer;
 137        }
 138
 139        *r_plugin = plugin;
 140        return 0;
 141}
 142