Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  Route Plug-In
0003  *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
0004  *
0005  *
0006  *   This library is free software; you can redistribute it and/or modify
0007  *   it under the terms of the GNU Library General Public License as
0008  *   published by the Free Software Foundation; either version 2 of
0009  *   the License, or (at your option) any later version.
0010  *
0011  *   This program is distributed in the hope that it will be useful,
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  *   GNU Library General Public License for more details.
0015  *
0016  *   You should have received a copy of the GNU Library General Public
0017  *   License along with this library; if not, write to the Free Software
0018  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
0019  *
0020  */
0021 
0022 #include <linux/time.h>
0023 #include <sound/core.h>
0024 #include <sound/pcm.h>
0025 #include "pcm_plugin.h"
0026 
0027 static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
0028                snd_pcm_uframes_t frames, snd_pcm_format_t format)
0029 {
0030     int dst = 0;
0031     for (; dst < ndsts; ++dst) {
0032         if (dvp->wanted)
0033             snd_pcm_area_silence(&dvp->area, 0, frames, format);
0034         dvp->enabled = 0;
0035         dvp++;
0036     }
0037 }
0038 
0039 static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
0040                  struct snd_pcm_plugin_channel *dst_channel,
0041                  snd_pcm_uframes_t frames, snd_pcm_format_t format)
0042 {
0043     dst_channel->enabled = 1;
0044     snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
0045 }
0046 
0047 static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
0048                     const struct snd_pcm_plugin_channel *src_channels,
0049                     struct snd_pcm_plugin_channel *dst_channels,
0050                     snd_pcm_uframes_t frames)
0051 {
0052     int nsrcs, ndsts, dst;
0053     struct snd_pcm_plugin_channel *dvp;
0054     snd_pcm_format_t format;
0055 
0056     if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
0057         return -ENXIO;
0058     if (frames == 0)
0059         return 0;
0060     if (frames > dst_channels[0].frames)
0061         frames = dst_channels[0].frames;
0062 
0063     nsrcs = plugin->src_format.channels;
0064     ndsts = plugin->dst_format.channels;
0065 
0066     format = plugin->dst_format.format;
0067     dvp = dst_channels;
0068     if (nsrcs <= 1) {
0069         /* expand to all channels */
0070         for (dst = 0; dst < ndsts; ++dst) {
0071             copy_area(src_channels, dvp, frames, format);
0072             dvp++;
0073         }
0074         return frames;
0075     }
0076 
0077     for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) {
0078         copy_area(src_channels, dvp, frames, format);
0079         dvp++;
0080         src_channels++;
0081     }
0082     if (dst < ndsts)
0083         zero_areas(dvp, ndsts - dst, frames, format);
0084     return frames;
0085 }
0086 
0087 int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
0088                    struct snd_pcm_plugin_format *src_format,
0089                    struct snd_pcm_plugin_format *dst_format,
0090                    struct snd_pcm_plugin **r_plugin)
0091 {
0092     struct snd_pcm_plugin *plugin;
0093     int err;
0094 
0095     if (snd_BUG_ON(!r_plugin))
0096         return -ENXIO;
0097     *r_plugin = NULL;
0098     if (snd_BUG_ON(src_format->rate != dst_format->rate))
0099         return -ENXIO;
0100     if (snd_BUG_ON(src_format->format != dst_format->format))
0101         return -ENXIO;
0102 
0103     err = snd_pcm_plugin_build(plug, "route conversion",
0104                    src_format, dst_format, 0, &plugin);
0105     if (err < 0)
0106         return err;
0107 
0108     plugin->transfer = route_transfer;
0109     *r_plugin = plugin;
0110     return 0;
0111 }