2005-04-16 15:20:36 -07:00
/*
2006-01-13 12:09:12 +01:00
* Route Plug - In
2005-04-16 15:20:36 -07:00
* Copyright ( c ) 2000 by Abramo Bagnara < abramo @ alsa - project . org >
*
*
* This library is free software ; you can redistribute it and / or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation ; either version 2 of
* the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/time.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include "pcm_plugin.h"
2006-01-13 12:09:12 +01:00
static void zero_areas ( struct snd_pcm_plugin_channel * dvp , int ndsts ,
2011-02-14 11:00:47 +01:00
snd_pcm_uframes_t frames , snd_pcm_format_t format )
2005-04-16 15:20:36 -07:00
{
2006-01-13 12:09:12 +01:00
int dst = 0 ;
for ( ; dst < ndsts ; + + dst ) {
if ( dvp - > wanted )
snd_pcm_area_silence ( & dvp - > area , 0 , frames , format ) ;
dvp - > enabled = 0 ;
dvp + + ;
2005-04-16 15:20:36 -07:00
}
}
2006-01-13 12:09:12 +01:00
static inline void copy_area ( const struct snd_pcm_plugin_channel * src_channel ,
2005-11-17 14:01:49 +01:00
struct snd_pcm_plugin_channel * dst_channel ,
2011-02-14 11:00:47 +01:00
snd_pcm_uframes_t frames , snd_pcm_format_t format )
2005-04-16 15:20:36 -07:00
{
dst_channel - > enabled = 1 ;
2006-01-13 12:09:12 +01:00
snd_pcm_area_copy ( & src_channel - > area , 0 , & dst_channel - > area , 0 , frames , format ) ;
2005-04-16 15:20:36 -07:00
}
2005-11-17 14:01:49 +01:00
static snd_pcm_sframes_t route_transfer ( struct snd_pcm_plugin * plugin ,
2006-01-13 12:09:12 +01:00
const struct snd_pcm_plugin_channel * src_channels ,
struct snd_pcm_plugin_channel * dst_channels ,
snd_pcm_uframes_t frames )
2005-04-16 15:20:36 -07:00
{
2006-01-13 12:09:12 +01:00
int nsrcs , ndsts , dst ;
2005-11-17 14:01:49 +01:00
struct snd_pcm_plugin_channel * dvp ;
2011-02-14 11:00:47 +01:00
snd_pcm_format_t format ;
2005-04-16 15:20:36 -07:00
2008-08-08 17:09:09 +02:00
if ( snd_BUG_ON ( ! plugin | | ! src_channels | | ! dst_channels ) )
return - ENXIO ;
2005-04-16 15:20:36 -07:00
if ( frames = = 0 )
return 0 ;
2006-01-13 12:09:12 +01:00
nsrcs = plugin - > src_format . channels ;
ndsts = plugin - > dst_format . channels ;
2005-04-16 15:20:36 -07:00
2006-01-13 12:09:12 +01:00
format = plugin - > dst_format . format ;
dvp = dst_channels ;
if ( nsrcs < = 1 ) {
/* expand to all channels */
for ( dst = 0 ; dst < ndsts ; + + dst ) {
copy_area ( src_channels , dvp , frames , format ) ;
dvp + + ;
2005-04-16 15:20:36 -07:00
}
2006-01-13 12:09:12 +01:00
return frames ;
2005-04-16 15:20:36 -07:00
}
2006-01-13 12:09:12 +01:00
for ( dst = 0 ; dst < ndsts & & dst < nsrcs ; + + dst ) {
copy_area ( src_channels , dvp , frames , format ) ;
2005-04-16 15:20:36 -07:00
dvp + + ;
2006-01-13 12:09:12 +01:00
src_channels + + ;
2005-04-16 15:20:36 -07:00
}
2006-01-13 12:09:12 +01:00
if ( dst < ndsts )
zero_areas ( dvp , ndsts - dst , frames , format ) ;
2005-04-16 15:20:36 -07:00
return frames ;
}
2005-11-17 14:01:49 +01:00
int snd_pcm_plugin_build_route ( struct snd_pcm_substream * plug ,
struct snd_pcm_plugin_format * src_format ,
struct snd_pcm_plugin_format * dst_format ,
struct snd_pcm_plugin * * r_plugin )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:01:49 +01:00
struct snd_pcm_plugin * plugin ;
2005-04-16 15:20:36 -07:00
int err ;
2008-08-08 17:09:09 +02:00
if ( snd_BUG_ON ( ! r_plugin ) )
return - ENXIO ;
2005-04-16 15:20:36 -07:00
* r_plugin = NULL ;
2008-08-08 17:09:09 +02:00
if ( snd_BUG_ON ( src_format - > rate ! = dst_format - > rate ) )
return - ENXIO ;
if ( snd_BUG_ON ( src_format - > format ! = dst_format - > format ) )
return - ENXIO ;
2005-04-16 15:20:36 -07:00
2006-01-13 12:09:12 +01:00
err = snd_pcm_plugin_build ( plug , " route conversion " ,
src_format , dst_format , 0 , & plugin ) ;
2005-04-16 15:20:36 -07:00
if ( err < 0 )
return err ;
plugin - > transfer = route_transfer ;
* r_plugin = plugin ;
return 0 ;
}