Blame src/pcm/pcm_extplug.c

Packit Service db8eaa
/**
Packit Service db8eaa
 * \file pcm/pcm_extplug.c
Packit Service db8eaa
 * \ingroup Plugin_SDK
Packit Service db8eaa
 * \brief External Filter Plugin SDK
Packit Service db8eaa
 * \author Takashi Iwai <tiwai@suse.de>
Packit Service db8eaa
 * \date 2005
Packit Service db8eaa
 */
Packit Service db8eaa
/*
Packit Service db8eaa
 *  PCM - External Filter Plugin SDK
Packit Service db8eaa
 *  Copyright (c) 2005 by Takashi Iwai <tiwai@suse.de>
Packit Service db8eaa
 *
Packit Service db8eaa
 *
Packit Service db8eaa
 *   This library is free software; you can redistribute it and/or modify
Packit Service db8eaa
 *   it under the terms of the GNU Lesser General Public License as
Packit Service db8eaa
 *   published by the Free Software Foundation; either version 2.1 of
Packit Service db8eaa
 *   the License, or (at your option) any later version.
Packit Service db8eaa
 *
Packit Service db8eaa
 *   This program is distributed in the hope that it will be useful,
Packit Service db8eaa
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service db8eaa
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service db8eaa
 *   GNU Lesser General Public License for more details.
Packit Service db8eaa
 *
Packit Service db8eaa
 *   You should have received a copy of the GNU Lesser General Public
Packit Service db8eaa
 *   License along with this library; if not, write to the Free Software
Packit Service db8eaa
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service db8eaa
 *
Packit Service db8eaa
 */
Packit Service db8eaa
  
Packit Service db8eaa
#include "pcm_local.h"
Packit Service db8eaa
#include "pcm_plugin.h"
Packit Service db8eaa
#include "pcm_extplug.h"
Packit Service db8eaa
#include "pcm_ext_parm.h"
Packit Service db8eaa
Packit Service db8eaa
#ifndef PIC
Packit Service db8eaa
/* entry for static linking */
Packit Service db8eaa
const char *_snd_module_pcm_extplug = "";
Packit Service db8eaa
#endif
Packit Service db8eaa
Packit Service db8eaa
#ifndef DOC_HIDDEN
Packit Service db8eaa
Packit Service db8eaa
typedef struct snd_pcm_extplug_priv {
Packit Service db8eaa
	snd_pcm_plugin_t plug;
Packit Service db8eaa
	snd_pcm_extplug_t *data;
Packit Service db8eaa
	struct snd_ext_parm params[SND_PCM_EXTPLUG_HW_PARAMS];
Packit Service db8eaa
	struct snd_ext_parm sparams[SND_PCM_EXTPLUG_HW_PARAMS];
Packit Service db8eaa
} extplug_priv_t;
Packit Service db8eaa
Packit Service db8eaa
static const int hw_params_type[SND_PCM_EXTPLUG_HW_PARAMS] = {
Packit Service db8eaa
	[SND_PCM_EXTPLUG_HW_FORMAT] = SND_PCM_HW_PARAM_FORMAT,
Packit Service db8eaa
	[SND_PCM_EXTPLUG_HW_CHANNELS] = SND_PCM_HW_PARAM_CHANNELS
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
#define is_mask_type(i) (hw_params_type[i] < SND_PCM_HW_PARAM_FIRST_INTERVAL)
Packit Service db8eaa
Packit Service db8eaa
static const unsigned int excl_parbits[SND_PCM_EXTPLUG_HW_PARAMS] = {
Packit Service db8eaa
	[SND_PCM_EXTPLUG_HW_FORMAT] = (SND_PCM_HW_PARBIT_FORMAT|
Packit Service db8eaa
				       SND_PCM_HW_PARBIT_SUBFORMAT |
Packit Service db8eaa
				       SND_PCM_HW_PARBIT_SAMPLE_BITS),
Packit Service db8eaa
	[SND_PCM_EXTPLUG_HW_CHANNELS] = (SND_PCM_HW_PARBIT_CHANNELS|
Packit Service db8eaa
					 SND_PCM_HW_PARBIT_FRAME_BITS),
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * set min/max values for the given parameter
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_ext_parm_set_minmax(struct snd_ext_parm *parm, unsigned int min, unsigned int max)
Packit Service db8eaa
{
Packit Service db8eaa
	parm->num_list = 0;
Packit Service db8eaa
	free(parm->list);
Packit Service db8eaa
	parm->list = NULL;
Packit Service db8eaa
	parm->min = min;
Packit Service db8eaa
	parm->max = max;
Packit Service db8eaa
	parm->active = 1;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * set the list of available values for the given parameter
Packit Service db8eaa
 */
Packit Service db8eaa
static int val_compar(const void *ap, const void *bp)
Packit Service db8eaa
{
Packit Service db8eaa
	return *(const unsigned int *)ap - *(const unsigned int *)bp;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int snd_ext_parm_set_list(struct snd_ext_parm *parm, unsigned int num_list, const unsigned int *list)
Packit Service db8eaa
{
Packit Service db8eaa
	unsigned int *new_list;
Packit Service db8eaa
Packit Service db8eaa
	new_list = malloc(sizeof(*new_list) * num_list);
Packit Service db8eaa
	if (new_list == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	memcpy(new_list, list, sizeof(*new_list) * num_list);
Packit Service db8eaa
	qsort(new_list, num_list, sizeof(*new_list), val_compar);
Packit Service db8eaa
Packit Service db8eaa
	free(parm->list);
Packit Service db8eaa
	parm->num_list = num_list;
Packit Service db8eaa
	parm->list = new_list;
Packit Service db8eaa
	parm->active = 1;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void snd_ext_parm_clear(struct snd_ext_parm *parm)
Packit Service db8eaa
{
Packit Service db8eaa
	free(parm->list);
Packit Service db8eaa
	memset(parm, 0, sizeof(*parm));
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * limit the interval to the given list
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_interval_list(snd_interval_t *ival, int num_list, unsigned int *list)
Packit Service db8eaa
{
Packit Service db8eaa
	int imin, imax;
Packit Service db8eaa
	int changed = 0;
Packit Service db8eaa
Packit Service db8eaa
	if (snd_interval_empty(ival))
Packit Service db8eaa
		return -ENOENT;
Packit Service db8eaa
	for (imin = 0; imin < num_list; imin++) {
Packit Service db8eaa
		if (ival->min == list[imin] && ! ival->openmin)
Packit Service db8eaa
			break;
Packit Service db8eaa
		if (ival->min <= list[imin]) {
Packit Service db8eaa
			ival->min = list[imin];
Packit Service db8eaa
			ival->openmin = 0;
Packit Service db8eaa
			changed = 1;
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	if (imin >= num_list)
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	for (imax = num_list - 1; imax >= imin; imax--) {
Packit Service db8eaa
		if (ival->max == list[imax] && ! ival->openmax)
Packit Service db8eaa
			break;
Packit Service db8eaa
		if (ival->max >= list[imax]) {
Packit Service db8eaa
			ival->max = list[imax];
Packit Service db8eaa
			ival->openmax = 0;
Packit Service db8eaa
			changed = 1;
Packit Service db8eaa
			break;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	if (imax < imin)
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	return changed;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * refine the interval parameter
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_ext_parm_interval_refine(snd_interval_t *ival, struct snd_ext_parm *parm, int type)
Packit Service db8eaa
{
Packit Service db8eaa
	parm += type;
Packit Service db8eaa
	if (! parm->active)
Packit Service db8eaa
		return 0;
Packit Service db8eaa
	ival->integer |= parm->integer;
Packit Service db8eaa
	if (parm->num_list) {
Packit Service db8eaa
		return snd_interval_list(ival, parm->num_list, parm->list);
Packit Service db8eaa
	} else if (parm->min || parm->max) {
Packit Service db8eaa
		snd_interval_t t;
Packit Service db8eaa
		memset(&t, 0, sizeof(t));
Packit Service db8eaa
		snd_interval_set_minmax(&t, parm->min, parm->max);
Packit Service db8eaa
		t.integer = ival->integer;
Packit Service db8eaa
		return snd_interval_refine(ival, &t);
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * refine the mask parameter
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_ext_parm_mask_refine(snd_mask_t *mask, struct snd_ext_parm *parm, int type)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_mask_t bits;
Packit Service db8eaa
	unsigned int i;
Packit Service db8eaa
Packit Service db8eaa
	parm += type;
Packit Service db8eaa
	if (!parm->active)
Packit Service db8eaa
		return 0;
Packit Service db8eaa
	memset(&bits, 0, sizeof(bits));
Packit Service db8eaa
	for (i = 0; i < parm->num_list; i++)
Packit Service db8eaa
		bits.bits[parm->list[i] / 32] |= 1U << (parm->list[i] % 32);
Packit Service db8eaa
	return snd_mask_refine(mask, &bits);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * hw_refine callback
Packit Service db8eaa
 */
Packit Service db8eaa
static int extplug_hw_refine(snd_pcm_hw_params_t *hw_params,
Packit Service db8eaa
			     struct snd_ext_parm *parm)
Packit Service db8eaa
{
Packit Service db8eaa
	int i, err, change = 0;
Packit Service db8eaa
	for (i = 0; i < SND_PCM_EXTPLUG_HW_PARAMS; i++) {
Packit Service db8eaa
		int type = hw_params_type[i];
Packit Service db8eaa
		if (is_mask_type(i))
Packit Service db8eaa
			err = snd_ext_parm_mask_refine(hw_param_mask(hw_params, type),
Packit Service db8eaa
						       parm, i);
Packit Service db8eaa
		else
Packit Service db8eaa
			err = snd_ext_parm_interval_refine(hw_param_interval(hw_params, type),
Packit Service db8eaa
							   parm, i);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
		change |= err;
Packit Service db8eaa
	}
Packit Service db8eaa
	return change;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_pcm_extplug_hw_refine_cprepare(snd_pcm_t *pcm,
Packit Service db8eaa
					      snd_pcm_hw_params_t *params)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
	int err;
Packit Service db8eaa
	snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM };
Packit Service db8eaa
	err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
Packit Service db8eaa
					 &access_mask);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	err = extplug_hw_refine(params, ext->params);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_pcm_extplug_hw_refine_sprepare(snd_pcm_t *pcm,
Packit Service db8eaa
					      snd_pcm_hw_params_t *sparams)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
	snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
Packit Service db8eaa
	_snd_pcm_hw_params_any(sparams);
Packit Service db8eaa
	_snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
Packit Service db8eaa
				   &saccess_mask);
Packit Service db8eaa
	extplug_hw_refine(sparams, ext->sparams);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static unsigned int get_links(struct snd_ext_parm *params)
Packit Service db8eaa
{
Packit Service db8eaa
	int i;
Packit Service db8eaa
	unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_SUBFORMAT |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_SAMPLE_BITS |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_CHANNELS |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_FRAME_BITS |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_RATE |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_PERIODS |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_PERIOD_SIZE |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_PERIOD_TIME |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_BUFFER_SIZE |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_BUFFER_TIME |
Packit Service db8eaa
			      SND_PCM_HW_PARBIT_TICK_TIME);
Packit Service db8eaa
Packit Service db8eaa
	for (i = 0; i < SND_PCM_EXTPLUG_HW_PARAMS; i++) {
Packit Service db8eaa
		if (params[i].active && !params[i].keep_link)
Packit Service db8eaa
			links &= ~excl_parbits[i];
Packit Service db8eaa
	}
Packit Service db8eaa
	return links;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_pcm_extplug_hw_refine_schange(snd_pcm_t *pcm,
Packit Service db8eaa
					     snd_pcm_hw_params_t *params,
Packit Service db8eaa
					     snd_pcm_hw_params_t *sparams)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
	unsigned int links = get_links(ext->sparams);
Packit Service db8eaa
Packit Service db8eaa
	return _snd_pcm_hw_params_refine(sparams, links, params);
Packit Service db8eaa
}
Packit Service db8eaa
	
Packit Service db8eaa
static int snd_pcm_extplug_hw_refine_cchange(snd_pcm_t *pcm,
Packit Service db8eaa
					     snd_pcm_hw_params_t *params,
Packit Service db8eaa
					     snd_pcm_hw_params_t *sparams)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
	unsigned int links = get_links(ext->params);
Packit Service db8eaa
Packit Service db8eaa
	return _snd_pcm_hw_params_refine(params, links, sparams);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_pcm_extplug_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Packit Service db8eaa
{
Packit Service db8eaa
	int err = snd_pcm_hw_refine_slave(pcm, params,
Packit Service db8eaa
				       snd_pcm_extplug_hw_refine_cprepare,
Packit Service db8eaa
				       snd_pcm_extplug_hw_refine_cchange,
Packit Service db8eaa
				       snd_pcm_extplug_hw_refine_sprepare,
Packit Service db8eaa
				       snd_pcm_extplug_hw_refine_schange,
Packit Service db8eaa
				       snd_pcm_generic_hw_refine);
Packit Service db8eaa
	return err;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * hw_params callback
Packit Service db8eaa
 */
Packit Service db8eaa
static int snd_pcm_extplug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Packit Service db8eaa
{
Packit Service db8eaa
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
	snd_pcm_t *slave = ext->plug.gen.slave;
Packit Service db8eaa
	int err = snd_pcm_hw_params_slave(pcm, params,
Packit Service db8eaa
					  snd_pcm_extplug_hw_refine_cchange,
Packit Service db8eaa
					  snd_pcm_extplug_hw_refine_sprepare,
Packit Service db8eaa
					  snd_pcm_extplug_hw_refine_schange,
Packit Service db8eaa
					  snd_pcm_generic_hw_params);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	ext->data->slave_format = slave->format;
Packit Service db8eaa
	ext->data->slave_subformat = slave->subformat;
Packit Service db8eaa
	ext->data->slave_channels = slave->channels;
Packit Service db8eaa
	ext->data->rate = slave->rate;
Packit Service db8eaa
	INTERNAL(snd_pcm_hw_params_get_format)(params, &ext->data->format);
Packit Service db8eaa
	INTERNAL(snd_pcm_hw_params_get_subformat)(params, &ext->data->subformat);
Packit Service db8eaa
	INTERNAL(snd_pcm_hw_params_get_channels)(params, &ext->data->channels);
Packit Service db8eaa
Packit Service db8eaa
	if (ext->data->callback->hw_params) {
Packit Service db8eaa
		err = ext->data->callback->hw_params(ext->data, params);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			return err;
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * hw_free callback
Packit Service db8eaa
 */
Packit Service db8eaa
static int snd_pcm_extplug_hw_free(snd_pcm_t *pcm)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	snd_pcm_hw_free(ext->plug.gen.slave);
Packit Service db8eaa
	if (ext->data->callback->hw_free)
Packit Service db8eaa
		return ext->data->callback->hw_free(ext->data);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * write_areas skeleton - call transfer callback
Packit Service db8eaa
 */
Packit Service db8eaa
static snd_pcm_uframes_t
Packit Service db8eaa
snd_pcm_extplug_write_areas(snd_pcm_t *pcm,
Packit Service db8eaa
			    const snd_pcm_channel_area_t *areas,
Packit Service db8eaa
			    snd_pcm_uframes_t offset,
Packit Service db8eaa
			    snd_pcm_uframes_t size,
Packit Service db8eaa
			    const snd_pcm_channel_area_t *slave_areas,
Packit Service db8eaa
			    snd_pcm_uframes_t slave_offset,
Packit Service db8eaa
			    snd_pcm_uframes_t *slave_sizep)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (size > *slave_sizep)
Packit Service db8eaa
		size = *slave_sizep;
Packit Service db8eaa
	size = ext->data->callback->transfer(ext->data, slave_areas, slave_offset,
Packit Service db8eaa
					     areas, offset, size);
Packit Service db8eaa
	*slave_sizep = size;
Packit Service db8eaa
	return size;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * read_areas skeleton - call transfer callback
Packit Service db8eaa
 */
Packit Service db8eaa
static snd_pcm_uframes_t
Packit Service db8eaa
snd_pcm_extplug_read_areas(snd_pcm_t *pcm,
Packit Service db8eaa
			   const snd_pcm_channel_area_t *areas,
Packit Service db8eaa
			   snd_pcm_uframes_t offset,
Packit Service db8eaa
			   snd_pcm_uframes_t size,
Packit Service db8eaa
			   const snd_pcm_channel_area_t *slave_areas,
Packit Service db8eaa
			   snd_pcm_uframes_t slave_offset,
Packit Service db8eaa
			   snd_pcm_uframes_t *slave_sizep)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (size > *slave_sizep)
Packit Service db8eaa
		size = *slave_sizep;
Packit Service db8eaa
	size = ext->data->callback->transfer(ext->data, areas, offset,
Packit Service db8eaa
					     slave_areas, slave_offset, size);
Packit Service db8eaa
	*slave_sizep = size;
Packit Service db8eaa
	return size;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * call init callback
Packit Service db8eaa
 */
Packit Service db8eaa
static int snd_pcm_extplug_init(snd_pcm_t *pcm)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
	return ext->data->callback->init(ext->data);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * dump setup
Packit Service db8eaa
 */
Packit Service db8eaa
static void snd_pcm_extplug_dump(snd_pcm_t *pcm, snd_output_t *out)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (ext->data->callback->dump)
Packit Service db8eaa
		ext->data->callback->dump(ext->data, out);
Packit Service db8eaa
	else {
Packit Service db8eaa
		if (ext->data->name)
Packit Service db8eaa
			snd_output_printf(out, "%s\n", ext->data->name);
Packit Service db8eaa
		else
Packit Service db8eaa
			snd_output_printf(out, "External PCM Plugin\n");
Packit Service db8eaa
		if (pcm->setup) {
Packit Service db8eaa
			snd_output_printf(out, "Its setup is:\n");
Packit Service db8eaa
			snd_pcm_dump_setup(pcm, out);
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	snd_output_printf(out, "Slave: ");
Packit Service db8eaa
	snd_pcm_dump(ext->plug.gen.slave, out);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void clear_ext_params(extplug_priv_t *ext)
Packit Service db8eaa
{
Packit Service db8eaa
	int i;
Packit Service db8eaa
	for (i = 0; i < SND_PCM_EXTPLUG_HW_PARAMS; i++) {
Packit Service db8eaa
		snd_ext_parm_clear(&ext->params[i]);
Packit Service db8eaa
		snd_ext_parm_clear(&ext->sparams[i]);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_pcm_extplug_close(snd_pcm_t *pcm)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	snd_pcm_close(ext->plug.gen.slave);
Packit Service db8eaa
	clear_ext_params(ext);
Packit Service db8eaa
	if (ext->data->callback->close)
Packit Service db8eaa
		ext->data->callback->close(ext->data);
Packit Service db8eaa
	free(ext);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static snd_pcm_chmap_query_t **snd_pcm_extplug_query_chmaps(snd_pcm_t *pcm)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (ext->data->version >= 0x010002 &&
Packit Service db8eaa
	    ext->data->callback->query_chmaps)
Packit Service db8eaa
		return ext->data->callback->query_chmaps(ext->data);
Packit Service db8eaa
	return snd_pcm_generic_query_chmaps(pcm);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static snd_pcm_chmap_t *snd_pcm_extplug_get_chmap(snd_pcm_t *pcm)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (ext->data->version >= 0x010002 &&
Packit Service db8eaa
	    ext->data->callback->get_chmap)
Packit Service db8eaa
		return ext->data->callback->get_chmap(ext->data);
Packit Service db8eaa
	return snd_pcm_generic_get_chmap(pcm);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int snd_pcm_extplug_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (ext->data->version >= 0x010002 &&
Packit Service db8eaa
	    ext->data->callback->set_chmap)
Packit Service db8eaa
		return ext->data->callback->set_chmap(ext->data, map);
Packit Service db8eaa
	return snd_pcm_generic_set_chmap(pcm, map);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static const snd_pcm_ops_t snd_pcm_extplug_ops = {
Packit Service db8eaa
	.close = snd_pcm_extplug_close,
Packit Service db8eaa
	.info = snd_pcm_generic_info,
Packit Service db8eaa
	.hw_refine = snd_pcm_extplug_hw_refine,
Packit Service db8eaa
	.hw_params = snd_pcm_extplug_hw_params,
Packit Service db8eaa
	.hw_free = snd_pcm_extplug_hw_free,
Packit Service db8eaa
	.sw_params = snd_pcm_generic_sw_params,
Packit Service db8eaa
	.channel_info = snd_pcm_generic_channel_info,
Packit Service db8eaa
	.dump = snd_pcm_extplug_dump,
Packit Service db8eaa
	.nonblock = snd_pcm_generic_nonblock,
Packit Service db8eaa
	.async = snd_pcm_generic_async,
Packit Service db8eaa
	.mmap = snd_pcm_generic_mmap,
Packit Service db8eaa
	.munmap = snd_pcm_generic_munmap,
Packit Service db8eaa
	.query_chmaps = snd_pcm_extplug_query_chmaps,
Packit Service db8eaa
	.get_chmap = snd_pcm_extplug_get_chmap,
Packit Service db8eaa
	.set_chmap = snd_pcm_extplug_set_chmap,
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
#endif /* !DOC_HIDDEN */
Packit Service db8eaa
Packit Service db8eaa
/*
Packit Service db8eaa
 * Exported functions
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
/*! \page pcm_external_plugins PCM External Plugin SDK
Packit Service db8eaa
Packit Service db8eaa
\section pcm_externals External Plugins
Packit Service db8eaa
Packit Service db8eaa
The external plugins are implemented in a shared object file located
Packit Service db8eaa
at /usr/lib/alsa-lib (the exact location depends on the build option
Packit Service db8eaa
and asoundrc configuration).  It has to be the file like
Packit Service db8eaa
libasound_module_pcm_MYPLUGIN.so, where MYPLUGIN corresponds to your
Packit Service db8eaa
own plugin name.
Packit Service db8eaa
Packit Service db8eaa
The entry point of the plugin is defined via
Packit Service db8eaa
#SND_PCM_PLUGIN_DEFINE_FUNC() macro.  This macro defines the function
Packit Service db8eaa
with a proper name to be referred from alsa-lib.  The function takes
Packit Service db8eaa
the following 6 arguments:
Packit Service db8eaa
\code
Packit Service db8eaa
int (snd_pcm_t **pcmp, const char *name, snd_config_t *root,
Packit Service db8eaa
	snd_config_t *conf, snd_pcm_stream_t stream, int mode)
Packit Service db8eaa
\endcode
Packit Service db8eaa
The first argument, pcmp, is the pointer to store the resultant PCM
Packit Service db8eaa
handle.  The arguments name, root, stream and mode are the parameters
Packit Service db8eaa
to be passed to the plugin constructor.  The conf is the configuration
Packit Service db8eaa
tree for the plugin.  The arguments above are defined in the macro
Packit Service db8eaa
itself, so don't use variables with the same names to shadow
Packit Service db8eaa
parameters.
Packit Service db8eaa
Packit Service db8eaa
After parsing the configuration parameters in the given conf tree,
Packit Service db8eaa
usually you will call the external plugin API function,
Packit Service db8eaa
#snd_pcm_extplug_create() or #snd_pcm_ioplug_create(), depending
Packit Service db8eaa
on the plugin type.  The PCM handle must be filled *pcmp in return.
Packit Service db8eaa
Then this function must return either a value 0 when succeeded, or a
Packit Service db8eaa
negative value as the error code. 
Packit Service db8eaa
Packit Service db8eaa
Finally, add #SND_PCM_PLUGIN_SYMBOL() with the name of your
Packit Service db8eaa
plugin as the argument at the end.  This defines the proper versioned
Packit Service db8eaa
symbol as the reference.
Packit Service db8eaa
Packit Service db8eaa
The typical code would look like below:
Packit Service db8eaa
\code
Packit Service db8eaa
struct myplug_info {
Packit Service db8eaa
	snd_pcm_extplug_t ext;
Packit Service db8eaa
	int my_own_data;
Packit Service db8eaa
	...
Packit Service db8eaa
};
Packit Service db8eaa
Packit Service db8eaa
SND_PCM_PLUGIN_DEFINE_FUNC(myplug)
Packit Service db8eaa
{
Packit Service db8eaa
	snd_config_iterator_t i, next;
Packit Service db8eaa
	snd_config_t *slave = NULL;
Packit Service db8eaa
	struct myplug_info *myplug;
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	snd_config_for_each(i, next, conf) {
Packit Service db8eaa
		snd_config_t *n = snd_config_iterator_entry(i);
Packit Service db8eaa
		const char *id;
Packit Service db8eaa
		if (snd_config_get_id(n, &id) < 0)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (strcmp(id, "slave") == 0) {
Packit Service db8eaa
			slave = n;
Packit Service db8eaa
			continue;
Packit Service db8eaa
		}
Packit Service db8eaa
		if (strcmp(id, "my_own_parameter") == 0) {
Packit Service db8eaa
			....
Packit Service db8eaa
			continue;
Packit Service db8eaa
		}
Packit Service db8eaa
		SNDERR("Unknown field %s", id);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	if (! slave) {
Packit Service db8eaa
		SNDERR("No slave defined for myplug");
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	myplug = calloc(1, sizeof(*myplug));
Packit Service db8eaa
	if (myplug == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
Packit Service db8eaa
	myplug->ext.version = SND_PCM_EXTPLUG_VERSION;
Packit Service db8eaa
	myplug->ext.name = "My Own Plugin";
Packit Service db8eaa
	myplug->ext.callback = &my_own_callback;
Packit Service db8eaa
	myplug->ext.private_data = myplug;
Packit Service db8eaa
	....
Packit Service db8eaa
Packit Service db8eaa
	err = snd_pcm_extplug_create(&myplug->ext, name, root, conf, stream, mode);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		myplug_free(myplug);
Packit Service db8eaa
		return err;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	*pcmp = myplug->ext.pcm;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
SND_PCM_PLUGIN_SYMBOL(myplug);
Packit Service db8eaa
\endcode
Packit Service db8eaa
Packit Service db8eaa
Read the codes in alsa-plugins package for the real examples.
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
\section pcm_extplug External Plugin: Filter-Type Plugin
Packit Service db8eaa
Packit Service db8eaa
The filter-type plugin is a plugin to convert the PCM signals from the input
Packit Service db8eaa
and feeds to the output.  Thus, this plugin always needs a slave PCM as its output.
Packit Service db8eaa
Packit Service db8eaa
The plugin can modify the format and the channels of the input/output PCM.
Packit Service db8eaa
It can not modify the sample rate (because of simplicity reason).
Packit Service db8eaa
Packit Service db8eaa
The following fields have to be filled in extplug record before calling
Packit Service db8eaa
#snd_pcm_extplug_create() : version, name, callback.
Packit Service db8eaa
Otherfields are optional and should be initialized with zero.
Packit Service db8eaa
Packit Service db8eaa
The constant #SND_PCM_EXTPLUG_VERSION must be passed to the version
Packit Service db8eaa
field for the version check in alsa-lib.  A non-NULL ASCII string
Packit Service db8eaa
has to be passed to the name field.  The callback field contains the 
Packit Service db8eaa
table of callback functions for this plugin (defined as
Packit Service db8eaa
#snd_pcm_extplug_callback_t).
Packit Service db8eaa
Packit Service db8eaa
The driver can set an arbitrary value (pointer) to private_data
Packit Service db8eaa
field to refer its own data in the callbacks.
Packit Service db8eaa
Packit Service db8eaa
The rest fields are filled by #snd_pcm_extplug_create().  The pcm field
Packit Service db8eaa
is the resultant PCM handle.  The others are the current status of the
Packit Service db8eaa
PCM.
Packit Service db8eaa
Packit Service db8eaa
The callback functions in #snd_pcm_extplug_callback_t define the real
Packit Service db8eaa
behavior of the driver.
Packit Service db8eaa
At least, transfer callback must be given.  This callback is called
Packit Service db8eaa
at each time certain size of data block is transfered to the slave
Packit Service db8eaa
PCM.  Other callbacks are optional.  
Packit Service db8eaa
Packit Service db8eaa
The close callback is called when the PCM is closed.  If the plugin
Packit Service db8eaa
allocates private resources, this is the place to release them
Packit Service db8eaa
again.  The hw_params and hw_free callbacks are called at
Packit Service db8eaa
#snd_pcm_hw_params() and #snd_pcm_hw_free() API calls,
Packit Service db8eaa
respectively.  The last, dump callback, is called for printing the
Packit Service db8eaa
information of the given plugin.
Packit Service db8eaa
Packit Service db8eaa
The init callback is called when the PCM is at prepare state or any
Packit Service db8eaa
initialization is issued.  Use this callback to reset the PCM instance
Packit Service db8eaa
to a sane initial state.
Packit Service db8eaa
Packit Service db8eaa
The hw_params constraints can be defined via either
Packit Service db8eaa
#snd_pcm_extplug_set_param_minmax() and #snd_pcm_extplug_set_param_list()
Packit Service db8eaa
functions after calling #snd_pcm_extplug_create().
Packit Service db8eaa
The former defines the minimal and maximal acceptable values for the
Packit Service db8eaa
given hw_params parameter (SND_PCM_EXTPLUG_HW_XXX).
Packit Service db8eaa
This function can't be used for the format parameter.  The latter
Packit Service db8eaa
function specifies the available parameter values as the list.
Packit Service db8eaa
As mentioned above, the rate can't be changed.  Only changeable
Packit Service db8eaa
parameters are sample format and channels.
Packit Service db8eaa
Packit Service db8eaa
To define the constraints of the slave PCM configuration, use
Packit Service db8eaa
either #snd_pcm_extplug_set_slave_param_minmax() and
Packit Service db8eaa
#snd_pcm_extplug_set_slave_param_list().  The arguments are as same
Packit Service db8eaa
as former functions.
Packit Service db8eaa
Packit Service db8eaa
To clear the parameter constraints, call #snd_pcm_extplug_params_reset()
Packit Service db8eaa
function. 
Packit Service db8eaa
Packit Service db8eaa
When using snd_pcm_extplug_set_param_*() or snd_pcm_extplug_set_slave_param_*()
Packit Service db8eaa
for any parameter. This parameter is no longer linked between the client and
Packit Service db8eaa
slave PCM. Therefore it could differ and the extplug has to support conversion
Packit Service db8eaa
between all valid parameter configurations. To keep the client and slave
Packit Service db8eaa
parameter linked #snd_pcm_extplug_set_param_link() can be used for the
Packit Service db8eaa
corresponding parameter. For example if the extplug does not support channel nor
Packit Service db8eaa
format conversion the supported client parameters can be limited with
Packit Service db8eaa
snd_pcm_extplug_set_param_*() and afterwards
Packit Service db8eaa
#snd_pcm_extplug_set_param_link(ext, SND_PCM_EXTPLUG_HW_FORMAT, 1) and
Packit Service db8eaa
#snd_pcm_extplug_set_param_link(ext, SND_PCM_EXTPLUG_HW_CHANNELS, 1) should be
Packit Service db8eaa
called to keep the client and slave parameters the same.
Packit Service db8eaa
*/
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Create an extplug instance
Packit Service db8eaa
 * \param extplug the extplug handle
Packit Service db8eaa
 * \param name name of the PCM
Packit Service db8eaa
 * \param root configuration tree root
Packit Service db8eaa
 * \param slave_conf slave configuration root
Packit Service db8eaa
 * \param stream stream direction
Packit Service db8eaa
 * \param mode PCM open mode
Packit Service db8eaa
 * \return 0 if successful, or a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Creates the extplug instance based on the given handle.
Packit Service db8eaa
 * The slave_conf argument is mandatory, and usually taken from the config tree of the
Packit Service db8eaa
 * PCM plugin as "slave" config value.
Packit Service db8eaa
 * name, root, stream and mode arguments are the values used for opening the PCM.
Packit Service db8eaa
 *
Packit Service db8eaa
 * The callback is the mandatory field of extplug handle.  At least, start, stop and
Packit Service db8eaa
 * pointer callbacks must be set before calling this function.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_create(snd_pcm_extplug_t *extplug, const char *name,
Packit Service db8eaa
			   snd_config_t *root, snd_config_t *slave_conf,
Packit Service db8eaa
			   snd_pcm_stream_t stream, int mode)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext;
Packit Service db8eaa
	int err;
Packit Service db8eaa
	snd_pcm_t *spcm, *pcm;
Packit Service db8eaa
	snd_config_t *sconf;
Packit Service db8eaa
Packit Service db8eaa
	assert(root);
Packit Service db8eaa
	assert(extplug && extplug->callback);
Packit Service db8eaa
	assert(extplug->callback->transfer);
Packit Service db8eaa
	assert(slave_conf);
Packit Service db8eaa
Packit Service db8eaa
	/* We support 1.0.0 to current */
Packit Service db8eaa
	if (extplug->version < 0x010000 ||
Packit Service db8eaa
	    extplug->version > SND_PCM_EXTPLUG_VERSION) {
Packit Service db8eaa
		SNDERR("extplug: Plugin version mismatch: 0x%x\n",
Packit Service db8eaa
		       extplug->version);
Packit Service db8eaa
		return -ENXIO;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	err = snd_pcm_slave_conf(root, slave_conf, &sconf, 0);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, NULL);
Packit Service db8eaa
	snd_config_delete(sconf);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
Packit Service db8eaa
	ext = calloc(1, sizeof(*ext));
Packit Service db8eaa
	if (! ext)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
Packit Service db8eaa
	ext->data = extplug;
Packit Service db8eaa
	extplug->stream = stream;
Packit Service db8eaa
Packit Service db8eaa
	snd_pcm_plugin_init(&ext->plug);
Packit Service db8eaa
	ext->plug.read = snd_pcm_extplug_read_areas;
Packit Service db8eaa
	ext->plug.write = snd_pcm_extplug_write_areas;
Packit Service db8eaa
	ext->plug.undo_read = snd_pcm_plugin_undo_read_generic;
Packit Service db8eaa
	ext->plug.undo_write = snd_pcm_plugin_undo_write_generic;
Packit Service db8eaa
	ext->plug.gen.slave = spcm;
Packit Service db8eaa
	ext->plug.gen.close_slave = 1;
Packit Service db8eaa
	if (extplug->version >= 0x010001 && extplug->callback->init)
Packit Service db8eaa
		ext->plug.init = snd_pcm_extplug_init;
Packit Service db8eaa
Packit Service db8eaa
	err = snd_pcm_new(&pcm, SND_PCM_TYPE_EXTPLUG, name, stream, mode);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		free(ext);
Packit Service db8eaa
		return err;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	extplug->pcm = pcm;
Packit Service db8eaa
	pcm->ops = &snd_pcm_extplug_ops;
Packit Service db8eaa
	pcm->fast_ops = &snd_pcm_plugin_fast_ops;
Packit Service db8eaa
	pcm->private_data = ext;
Packit Service db8eaa
	pcm->poll_fd = spcm->poll_fd;
Packit Service db8eaa
	pcm->poll_events = spcm->poll_events;
Packit Service db8eaa
	pcm->tstamp_type = spcm->tstamp_type;
Packit Service db8eaa
	snd_pcm_set_hw_ptr(pcm, &ext->plug.hw_ptr, -1, 0);
Packit Service db8eaa
	snd_pcm_set_appl_ptr(pcm, &ext->plug.appl_ptr, -1, 0);
Packit Service db8eaa
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Delete the extplug instance
Packit Service db8eaa
 * \param extplug the extplug handle to delete
Packit Service db8eaa
 * \return 0 if successful, or a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * The destructor of extplug instance.
Packit Service db8eaa
 * Closes the PCM and deletes the associated resources.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_delete(snd_pcm_extplug_t *extplug)
Packit Service db8eaa
{
Packit Service db8eaa
	return snd_pcm_close(extplug->pcm);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Reset extplug parameters
Packit Service db8eaa
 * \param extplug the extplug handle
Packit Service db8eaa
 *
Packit Service db8eaa
 * Resets the all parameters for the given extplug handle.
Packit Service db8eaa
 */
Packit Service db8eaa
void snd_pcm_extplug_params_reset(snd_pcm_extplug_t *extplug)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = extplug->pcm->private_data;
Packit Service db8eaa
	clear_ext_params(ext);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set slave parameter as the list
Packit Service db8eaa
 * \param extplug the extplug handle
Packit Service db8eaa
 * \param type parameter type
Packit Service db8eaa
 * \param num_list number of available values
Packit Service db8eaa
 * \param list the list of available values
Packit Service db8eaa
 * \return 0 if successful, or a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Sets the slave parameter as the list.
Packit Service db8eaa
 * The available values of the given parameter type of the slave PCM is restricted
Packit Service db8eaa
 * to the ones of the given list.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_set_slave_param_list(snd_pcm_extplug_t *extplug, int type, unsigned int num_list, const unsigned int *list)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = extplug->pcm->private_data;
Packit Service db8eaa
	if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	return snd_ext_parm_set_list(&ext->sparams[type], num_list, list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set slave parameter as the min/max values
Packit Service db8eaa
 * \param extplug the extplug handle
Packit Service db8eaa
 * \param type parameter type
Packit Service db8eaa
 * \param min the minimum value
Packit Service db8eaa
 * \param max the maximum value
Packit Service db8eaa
 * \return 0 if successful, or a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Sets the slave parameter as the min/max values.
Packit Service db8eaa
 * The available values of the given parameter type of the slave PCM is restricted
Packit Service db8eaa
 * between the given minimum and maximum values.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_set_slave_param_minmax(snd_pcm_extplug_t *extplug, int type, unsigned int min, unsigned int max)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = extplug->pcm->private_data;
Packit Service db8eaa
	if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	if (is_mask_type(type)) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	return snd_ext_parm_set_minmax(&ext->sparams[type], min, max);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set master parameter as the list
Packit Service db8eaa
 * \param extplug the extplug handle
Packit Service db8eaa
 * \param type parameter type
Packit Service db8eaa
 * \param num_list number of available values
Packit Service db8eaa
 * \param list the list of available values
Packit Service db8eaa
 * \return 0 if successful, or a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Sets the master parameter as the list.
Packit Service db8eaa
 * The available values of the given parameter type of this PCM (as input) is restricted
Packit Service db8eaa
 * to the ones of the given list.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_set_param_list(snd_pcm_extplug_t *extplug, int type, unsigned int num_list, const unsigned int *list)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = extplug->pcm->private_data;
Packit Service db8eaa
	if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	return snd_ext_parm_set_list(&ext->params[type], num_list, list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * \brief Set master parameter as the min/max values
Packit Service db8eaa
 * \param extplug the extplug handle
Packit Service db8eaa
 * \param type parameter type
Packit Service db8eaa
 * \param min the minimum value
Packit Service db8eaa
 * \param max the maximum value
Packit Service db8eaa
 * \return 0 if successful, or a negative error code
Packit Service db8eaa
 *
Packit Service db8eaa
 * Sets the master parameter as the min/max values.
Packit Service db8eaa
 * The available values of the given parameter type of this PCM (as input) is restricted
Packit Service db8eaa
 * between the given minimum and maximum values.
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_set_param_minmax(snd_pcm_extplug_t *extplug, int type, unsigned int min, unsigned int max)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = extplug->pcm->private_data;
Packit Service db8eaa
	if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	if (is_mask_type(type)) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	return snd_ext_parm_set_minmax(&ext->params[type], min, max);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
/**
Packit Service db8eaa
 * @brief Keep the client and slave format/channels the same if requested. This
Packit Service db8eaa
 * is for example useful if this extplug does not support any channel
Packit Service db8eaa
 * conversion.
Packit Service db8eaa
 * @param extplug the extplug handle
Packit Service db8eaa
 * @param type parameter type
Packit Service db8eaa
 * @param keep_link if 1 the parameter identified by type will be kept the same
Packit Service db8eaa
 * for the client and slave PCM of this extplug
Packit Service db8eaa
 * @return 0 if successful, or a negative error code
Packit Service db8eaa
 */
Packit Service db8eaa
int snd_pcm_extplug_set_param_link(snd_pcm_extplug_t *extplug, int type,
Packit Service db8eaa
				   int keep_link)
Packit Service db8eaa
{
Packit Service db8eaa
	extplug_priv_t *ext = extplug->pcm->private_data;
Packit Service db8eaa
Packit Service db8eaa
	if (type < 0 || type >= SND_PCM_EXTPLUG_HW_PARAMS) {
Packit Service db8eaa
		SNDERR("EXTPLUG: invalid parameter type %d", type);
Packit Service db8eaa
		return -EINVAL;
Packit Service db8eaa
	}
Packit Service db8eaa
	ext->params[type].keep_link = keep_link ? 1 : 0;
Packit Service db8eaa
	ext->sparams[type].keep_link = keep_link ? 1 : 0;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}