|
Packit Service |
db8eaa |
/*
|
|
Packit Service |
db8eaa |
* PCM - Params functions
|
|
Packit Service |
db8eaa |
* Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
|
|
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 |
|
|
Packit Service |
db8eaa |
#ifndef NDEBUG
|
|
Packit Service |
db8eaa |
/*
|
|
Packit Service |
db8eaa |
* dump hw_params when $LIBASOUND_DEBUG is set to >= 1
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
static void dump_hw_params(snd_pcm_hw_params_t *params, const char *type,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int val, int err)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const char *verbose = getenv("LIBASOUND_DEBUG");
|
|
Packit Service |
db8eaa |
snd_output_t *out;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if (! verbose || ! *verbose || atoi(verbose) < 1)
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
if (snd_output_stdio_attach(&out, stderr, 0) < 0)
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
fprintf(stderr, "ALSA ERROR hw_params: %s (%s)\n",
|
|
Packit Service |
db8eaa |
type, snd_pcm_hw_param_name(var));
|
|
Packit Service |
db8eaa |
fprintf(stderr, " value = ");
|
|
Packit Service |
db8eaa |
switch (var) {
|
|
Packit Service |
db8eaa |
case SND_PCM_HW_PARAM_ACCESS:
|
|
Packit Service |
db8eaa |
fprintf(stderr, "%s", snd_pcm_access_name(val));
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_PCM_HW_PARAM_FORMAT:
|
|
Packit Service |
db8eaa |
fprintf(stderr, "%s", snd_pcm_format_name(val));
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_PCM_HW_PARAM_SUBFORMAT:
|
|
Packit Service |
db8eaa |
fprintf(stderr, "%s", snd_pcm_subformat_name(val));
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
fprintf(stderr, "%u", val);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
fprintf(stderr, " : %s\n", snd_strerror(err));
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, out);
|
|
Packit Service |
db8eaa |
snd_output_close(out);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#else
|
|
Packit Service |
db8eaa |
static inline void dump_hw_params(snd_pcm_hw_params_t *params, const char *type,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int val, int err)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static inline int hw_is_mask(snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
#if SND_PCM_HW_PARAM_FIRST_MASK == 0
|
|
Packit Service |
db8eaa |
return var <= SND_PCM_HW_PARAM_LAST_MASK;
|
|
Packit Service |
db8eaa |
#else
|
|
Packit Service |
db8eaa |
return var >= SND_PCM_HW_PARAM_FIRST_MASK &&
|
|
Packit Service |
db8eaa |
var <= SND_PCM_HW_PARAM_LAST_MASK;
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static inline int hw_is_interval(snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
return var >= SND_PCM_HW_PARAM_FIRST_INTERVAL &&
|
|
Packit Service |
db8eaa |
var <= SND_PCM_HW_PARAM_LAST_INTERVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#define hw_param_mask(params,var) \
|
|
Packit Service |
db8eaa |
&((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#define hw_param_interval(params,var) \
|
|
Packit Service |
db8eaa |
&((params)->intervals[(var) - SND_PCM_HW_PARAM_FIRST_INTERVAL])
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#define hw_param_mask_c hw_param_mask
|
|
Packit Service |
db8eaa |
#define hw_param_interval_c hw_param_interval
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
snd_mask_any(hw_param_mask(params, var));
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_any(hw_param_interval(params, var));
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
_snd_pcm_hw_param_any(params, var);
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
unsigned int k;
|
|
Packit Service |
db8eaa |
memset(params, 0, sizeof(*params));
|
|
Packit Service |
db8eaa |
for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++)
|
|
Packit Service |
db8eaa |
_snd_pcm_hw_param_any(params, k);
|
|
Packit Service |
db8eaa |
for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
|
|
Packit Service |
db8eaa |
_snd_pcm_hw_param_any(params, k);
|
|
Packit Service |
db8eaa |
params->rmask = ~0U;
|
|
Packit Service |
db8eaa |
params->cmask = 0;
|
|
Packit Service |
db8eaa |
params->info = ~0U;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Return the value for field PAR if it's fixed in configuration space
|
|
Packit Service |
db8eaa |
defined by PARAMS. Return -EINVAL otherwise
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_get(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
const snd_mask_t *mask = hw_param_mask_c(params, var);
|
|
Packit Service |
db8eaa |
if (snd_mask_empty(mask) || !snd_mask_single(mask))
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
if (dir)
|
|
Packit Service |
db8eaa |
*dir = 0;
|
|
Packit Service |
db8eaa |
if (val)
|
|
Packit Service |
db8eaa |
*val = snd_mask_value(mask);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
const snd_interval_t *i = hw_param_interval_c(params, var);
|
|
Packit Service |
db8eaa |
if (snd_interval_empty(i) || !snd_interval_single(i))
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
if (dir)
|
|
Packit Service |
db8eaa |
*dir = i->openmin;
|
|
Packit Service |
db8eaa |
if (val)
|
|
Packit Service |
db8eaa |
*val = snd_interval_value(i);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Return the minimum value for field PAR. */
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_get_min(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
const snd_mask_t *m = hw_param_mask_c(params, var);
|
|
Packit Service |
db8eaa |
assert(!snd_mask_empty(m));
|
|
Packit Service |
db8eaa |
if (dir)
|
|
Packit Service |
db8eaa |
*dir = 0;
|
|
Packit Service |
db8eaa |
if (val)
|
|
Packit Service |
db8eaa |
*val = snd_mask_min(m);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
const snd_interval_t *i = hw_param_interval_c(params, var);
|
|
Packit Service |
db8eaa |
assert(!snd_interval_empty(i));
|
|
Packit Service |
db8eaa |
if (dir)
|
|
Packit Service |
db8eaa |
*dir = i->openmin;
|
|
Packit Service |
db8eaa |
if (val)
|
|
Packit Service |
db8eaa |
*val = snd_interval_min(i);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Return the maximum value for field PAR. */
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_get_max(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
const snd_mask_t *m = hw_param_mask_c(params, var);
|
|
Packit Service |
db8eaa |
assert(!snd_mask_empty(m));
|
|
Packit Service |
db8eaa |
if (dir)
|
|
Packit Service |
db8eaa |
*dir = 0;
|
|
Packit Service |
db8eaa |
if (val)
|
|
Packit Service |
db8eaa |
*val = snd_mask_max(m);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
const snd_interval_t *i = hw_param_interval_c(params, var);
|
|
Packit Service |
db8eaa |
assert(!snd_interval_empty(i));
|
|
Packit Service |
db8eaa |
if (dir)
|
|
Packit Service |
db8eaa |
*dir = - (int) i->openmax;
|
|
Packit Service |
db8eaa |
if (val)
|
|
Packit Service |
db8eaa |
*val = snd_interval_max(i);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Return the mask for field PAR.
|
|
Packit Service |
db8eaa |
This function can be called only for SND_PCM_HW_PARAM_ACCESS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */
|
|
Packit Service |
db8eaa |
const snd_mask_t *snd_pcm_hw_param_get_mask(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
assert(hw_is_mask(var));
|
|
Packit Service |
db8eaa |
return hw_param_mask_c(params, var);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Return the interval for field PAR.
|
|
Packit Service |
db8eaa |
This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */
|
|
Packit Service |
db8eaa |
const snd_interval_t *snd_pcm_hw_param_get_interval(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
assert(hw_is_interval(var));
|
|
Packit Service |
db8eaa |
return hw_param_interval_c(params, var);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* --- Refinement functions --- */
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_set_interval(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_interval_t *val)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
assert(hw_is_interval(var));
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine(hw_param_interval(params, var), val);
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void _snd_pcm_hw_param_set_empty(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
snd_mask_none(hw_param_mask(params, var));
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_none(hw_param_interval(params, var));
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int _snd_pcm_hw_param_set_integer(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
assert(hw_is_interval(var));
|
|
Packit Service |
db8eaa |
changed = snd_interval_setinteger(hw_param_interval(params, var));
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
non integer values. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return -EINVAL if the configuration space is empty
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_integer(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_set_mode_t mode,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
switch (mode) {
|
|
Packit Service |
db8eaa |
case SND_CHANGE:
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TRY:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TEST:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
params = &sav;;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_integer(params, var);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if (params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
_fail:
|
|
Packit Service |
db8eaa |
if (mode == SND_TRY)
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int _snd_pcm_hw_param_set_first(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var))
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine_first(hw_param_mask(params, var));
|
|
Packit Service |
db8eaa |
else if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine_first(hw_param_interval(params, var));
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed > 0) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
values > minimum. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return the minimum.
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_first(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *rval, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_first(params, var);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
if (params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_get(params, var, rval, dir);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int _snd_pcm_hw_param_set_last(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var))
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine_last(hw_param_mask(params, var));
|
|
Packit Service |
db8eaa |
else if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine_last(hw_param_interval(params, var));
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed > 0) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
values < maximum. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return the maximum.
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_last(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *rval, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_last(params, var);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
if (params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_get(params, var, rval, dir);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_set_min(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int val, int dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
int openmin = 0;
|
|
Packit Service |
db8eaa |
if (dir) {
|
|
Packit Service |
db8eaa |
if (dir > 0) {
|
|
Packit Service |
db8eaa |
openmin = 1;
|
|
Packit Service |
db8eaa |
} else if (dir < 0) {
|
|
Packit Service |
db8eaa |
if (val > 0) {
|
|
Packit Service |
db8eaa |
openmin = 1;
|
|
Packit Service |
db8eaa |
val--;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var))
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!openmin);
|
|
Packit Service |
db8eaa |
else if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine_min(hw_param_interval(params, var), val, openmin);
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
values < VAL. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return new minimum or -EINVAL if the configuration space is empty
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_set_mode_t mode,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int *val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
switch (mode) {
|
|
Packit Service |
db8eaa |
case SND_CHANGE:
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TRY:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TEST:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
params = &sav;;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_min(params, var, *val, dir ? *dir : 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if (snd_pcm_hw_param_empty(params, var)) {
|
|
Packit Service |
db8eaa |
err = -ENOENT;
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_get_min(params, var, val, dir);
|
|
Packit Service |
db8eaa |
_fail:
|
|
Packit Service |
db8eaa |
if (mode == SND_TRY)
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
if (err < 0 && mode == SND_TRY)
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set_min", var, *val, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_set_max(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int val, int dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
int openmax = 0;
|
|
Packit Service |
db8eaa |
if (dir) {
|
|
Packit Service |
db8eaa |
if (dir < 0) {
|
|
Packit Service |
db8eaa |
openmax = 1;
|
|
Packit Service |
db8eaa |
} else if (dir > 0) {
|
|
Packit Service |
db8eaa |
openmax = 1;
|
|
Packit Service |
db8eaa |
val++;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
if (val == 0 && openmax) {
|
|
Packit Service |
db8eaa |
snd_mask_none(hw_param_mask(params, var));
|
|
Packit Service |
db8eaa |
changed = -EINVAL;
|
|
Packit Service |
db8eaa |
} else
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!openmax);
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine_max(hw_param_interval(params, var), val, openmax);
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
values >= VAL + 1. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return new maximum or -EINVAL if the configuration space is empty
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_set_mode_t mode,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int *val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
switch (mode) {
|
|
Packit Service |
db8eaa |
case SND_CHANGE:
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TRY:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TEST:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
params = &sav;;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_max(params, var, *val, dir ? *dir : 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if (snd_pcm_hw_param_empty(params, var)) {
|
|
Packit Service |
db8eaa |
err = -ENOENT;
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_get_max(params, var, val, dir);
|
|
Packit Service |
db8eaa |
_fail:
|
|
Packit Service |
db8eaa |
if (mode == SND_TRY)
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
if (err < 0 && mode == SND_TRY)
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set_max", var, *val, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_set_minmax(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int min, int mindir,
|
|
Packit Service |
db8eaa |
unsigned int max, int maxdir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed, c1, c2;
|
|
Packit Service |
db8eaa |
int openmin = 0, openmax = 0;
|
|
Packit Service |
db8eaa |
if (mindir) {
|
|
Packit Service |
db8eaa |
if (mindir > 0) {
|
|
Packit Service |
db8eaa |
openmin = 1;
|
|
Packit Service |
db8eaa |
} else if (mindir < 0) {
|
|
Packit Service |
db8eaa |
if (min > 0) {
|
|
Packit Service |
db8eaa |
openmin = 1;
|
|
Packit Service |
db8eaa |
min--;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (maxdir) {
|
|
Packit Service |
db8eaa |
if (maxdir < 0) {
|
|
Packit Service |
db8eaa |
openmax = 1;
|
|
Packit Service |
db8eaa |
} else if (maxdir > 0) {
|
|
Packit Service |
db8eaa |
openmax = 1;
|
|
Packit Service |
db8eaa |
max++;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
snd_mask_t *mask = hw_param_mask(params, var);
|
|
Packit Service |
db8eaa |
if (max == 0 && openmax) {
|
|
Packit Service |
db8eaa |
snd_mask_none(mask);
|
|
Packit Service |
db8eaa |
changed = -EINVAL;
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
c1 = snd_mask_refine_min(mask, min + !!openmin);
|
|
Packit Service |
db8eaa |
if (c1 < 0)
|
|
Packit Service |
db8eaa |
changed = c1;
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
c2 = snd_mask_refine_max(mask, max - !!openmax);
|
|
Packit Service |
db8eaa |
if (c2 < 0)
|
|
Packit Service |
db8eaa |
changed = c2;
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
changed = (c1 || c2);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_t *i = hw_param_interval(params, var);
|
|
Packit Service |
db8eaa |
c1 = snd_interval_refine_min(i, min, openmin);
|
|
Packit Service |
db8eaa |
if (c1 < 0)
|
|
Packit Service |
db8eaa |
changed = c1;
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
c2 = snd_interval_refine_max(i, max, openmax);
|
|
Packit Service |
db8eaa |
if (c2 < 0)
|
|
Packit Service |
db8eaa |
changed = c2;
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
changed = (c1 || c2);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
values < MIN and all values > MAX. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return 0 or -EINVAL if the configuration space is empty
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_set_mode_t mode,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *min, int *mindir,
|
|
Packit Service |
db8eaa |
unsigned int *max, int *maxdir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
switch (mode) {
|
|
Packit Service |
db8eaa |
case SND_CHANGE:
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TRY:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TEST:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
params = &sav;;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_minmax(params, var,
|
|
Packit Service |
db8eaa |
*min, mindir ? *mindir : 0,
|
|
Packit Service |
db8eaa |
*max, maxdir ? *maxdir : 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_get_min(params, var, min, mindir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_get_max(params, var, max, maxdir);
|
|
Packit Service |
db8eaa |
_fail:
|
|
Packit Service |
db8eaa |
if (mode == SND_TRY)
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set_minmax", var, *min, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int val, int dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
snd_mask_t *m = hw_param_mask(params, var);
|
|
Packit Service |
db8eaa |
if (val == 0 && dir < 0) {
|
|
Packit Service |
db8eaa |
changed = -EINVAL;
|
|
Packit Service |
db8eaa |
snd_mask_none(m);
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
if (dir > 0)
|
|
Packit Service |
db8eaa |
val++;
|
|
Packit Service |
db8eaa |
else if (dir < 0)
|
|
Packit Service |
db8eaa |
val--;
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine_set(hw_param_mask(params, var), val);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_t *i = hw_param_interval(params, var);
|
|
Packit Service |
db8eaa |
if (val == 0 && dir < 0) {
|
|
Packit Service |
db8eaa |
changed = -EINVAL;
|
|
Packit Service |
db8eaa |
snd_interval_none(i);
|
|
Packit Service |
db8eaa |
} else if (dir == 0)
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine_set(i, val);
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
snd_interval_t t;
|
|
Packit Service |
db8eaa |
t.openmin = 1;
|
|
Packit Service |
db8eaa |
t.openmax = 1;
|
|
Packit Service |
db8eaa |
t.empty = 0;
|
|
Packit Service |
db8eaa |
t.integer = 0;
|
|
Packit Service |
db8eaa |
if (dir < 0) {
|
|
Packit Service |
db8eaa |
t.min = val - 1;
|
|
Packit Service |
db8eaa |
t.max = val;
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
t.min = val;
|
|
Packit Service |
db8eaa |
t.max = val+1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine(i, &t);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all
|
|
Packit Service |
db8eaa |
values != VAL. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
Return -EINVAL if the configuration space is empty
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_set_mode_t mode,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, unsigned int val, int dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
switch (mode) {
|
|
Packit Service |
db8eaa |
case SND_CHANGE:
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TRY:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TEST:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
params = &sav;;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set(params, var, val, dir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
_fail:
|
|
Packit Service |
db8eaa |
if (mode == SND_TRY)
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
if (err < 0 && mode == SND_TRY)
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set", var, val, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_set_mask(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, const snd_mask_t *val)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed;
|
|
Packit Service |
db8eaa |
assert(hw_is_mask(var));
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine(hw_param_mask(params, var), val);
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS remove from PAR all values
|
|
Packit Service |
db8eaa |
not contained in MASK. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
This function can be called only for SND_PCM_HW_PARAM_ACCESS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
|
|
Packit Service |
db8eaa |
Return 0 on success or -EINVAL
|
|
Packit Service |
db8eaa |
if the configuration space is empty
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_set_mode_t mode,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, const snd_mask_t *val)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
switch (mode) {
|
|
Packit Service |
db8eaa |
case SND_CHANGE:
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TRY:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_TEST:
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
params = &sav;;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = _snd_pcm_hw_param_set_mask(params, var, val);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
if (mode != SND_TEST && params->rmask) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _fail;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
_fail:
|
|
Packit Service |
db8eaa |
if (mode == SND_TRY)
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS set PAR to the available value
|
|
Packit Service |
db8eaa |
nearest to VAL. Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
|
|
Packit Service |
db8eaa |
Return the value found.
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int *val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
unsigned int best = *val, saved_min;
|
|
Packit Service |
db8eaa |
int last = 0;
|
|
Packit Service |
db8eaa |
unsigned int min, max;
|
|
Packit Service |
db8eaa |
int mindir, maxdir;
|
|
Packit Service |
db8eaa |
int valdir = dir ? *dir : 0;
|
|
Packit Service |
db8eaa |
snd_interval_t *i;
|
|
Packit Service |
db8eaa |
/* FIXME */
|
|
Packit Service |
db8eaa |
if (best > INT_MAX)
|
|
Packit Service |
db8eaa |
best = INT_MAX;
|
|
Packit Service |
db8eaa |
min = max = best;
|
|
Packit Service |
db8eaa |
mindir = maxdir = valdir;
|
|
Packit Service |
db8eaa |
if (maxdir > 0)
|
|
Packit Service |
db8eaa |
maxdir = 0;
|
|
Packit Service |
db8eaa |
else if (maxdir == 0)
|
|
Packit Service |
db8eaa |
maxdir = -1;
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
maxdir = 1;
|
|
Packit Service |
db8eaa |
max--;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
saved_min = min;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, var, &min, &mindir);
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
i = hw_param_interval(params, var);
|
|
Packit Service |
db8eaa |
if (!snd_interval_empty(i) && snd_interval_single(i)) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_get_min(params, var, val, dir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set_near", var, *val, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if (err >= 0) {
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t params1;
|
|
Packit Service |
db8eaa |
if (min == saved_min && mindir == valdir)
|
|
Packit Service |
db8eaa |
goto _end;
|
|
Packit Service |
db8eaa |
params1 = save;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_max(pcm, ¶ms1, SND_CHANGE, var, &max, &maxdir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _end;
|
|
Packit Service |
db8eaa |
if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
|
|
Packit Service |
db8eaa |
*params = params1;
|
|
Packit Service |
db8eaa |
last = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_max(pcm, params, SND_CHANGE, var, &max, &maxdir);
|
|
Packit Service |
db8eaa |
if (err < 0) {
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set_near", var, *val, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
last = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
_end:
|
|
Packit Service |
db8eaa |
if (last)
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_last(pcm, params, var, val, dir);
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, var, val, dir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
dump_hw_params(params, "set_near", var, *val, err);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
/* Inside configuration space defined by PARAMS set PAR to the available value
|
|
Packit Service |
db8eaa |
nearest to BEST after VAL (on equal difference values less than BEST are
|
|
Packit Service |
db8eaa |
returned first).
|
|
Packit Service |
db8eaa |
Reduce configuration space accordingly.
|
|
Packit Service |
db8eaa |
This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
|
|
Packit Service |
db8eaa |
Return the value found.
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_set_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int best, int bestdir,
|
|
Packit Service |
db8eaa |
unsigned int val, int *dir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t save;
|
|
Packit Service |
db8eaa |
int v, err;
|
|
Packit Service |
db8eaa |
int last = 0;
|
|
Packit Service |
db8eaa |
int min, max;
|
|
Packit Service |
db8eaa |
int mindir, maxdir;
|
|
Packit Service |
db8eaa |
int diff, diffdir;
|
|
Packit Service |
db8eaa |
int valdir = dir ? *dir : 0;
|
|
Packit Service |
db8eaa |
/* FIXME */
|
|
Packit Service |
db8eaa |
if (best > INT_MAX)
|
|
Packit Service |
db8eaa |
best = INT_MAX;
|
|
Packit Service |
db8eaa |
boundary_sub(val, valdir, best, bestdir, &diff, &diffdir);
|
|
Packit Service |
db8eaa |
if (diff < 0 || (diff == 0 && diffdir < 0)) {
|
|
Packit Service |
db8eaa |
min = best - diff;
|
|
Packit Service |
db8eaa |
mindir = bestdir - diffdir;
|
|
Packit Service |
db8eaa |
max = val;
|
|
Packit Service |
db8eaa |
maxdir = bestdir - 1;
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
min = val;
|
|
Packit Service |
db8eaa |
mindir = bestdir + 1;
|
|
Packit Service |
db8eaa |
max = best + diff;
|
|
Packit Service |
db8eaa |
maxdir = bestdir + diffdir + 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
min += mindir / 2;
|
|
Packit Service |
db8eaa |
mindir %= 2;
|
|
Packit Service |
db8eaa |
max += maxdir / 2;
|
|
Packit Service |
db8eaa |
maxdir %= 2;
|
|
Packit Service |
db8eaa |
save = *params;
|
|
Packit Service |
db8eaa |
if (min >= 0 &&
|
|
Packit Service |
db8eaa |
(err = snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, var, &min, &mindir)) >= 0) {
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t params1;
|
|
Packit Service |
db8eaa |
if (max < 0)
|
|
Packit Service |
db8eaa |
goto _end;
|
|
Packit Service |
db8eaa |
params1 = save;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_max(pcm, ¶ms1, SND_CHANGE, var, &max, &maxdir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
goto _end;
|
|
Packit Service |
db8eaa |
if (boundary_nearer(max, maxdir, best, bestdir, min, mindir)) {
|
|
Packit Service |
db8eaa |
*params = params1;
|
|
Packit Service |
db8eaa |
last = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
if (max < 0)
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
*params = save;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_max(pcm, params, SND_CHANGE, var, &max, &maxdir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return max;
|
|
Packit Service |
db8eaa |
last = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
_end:
|
|
Packit Service |
db8eaa |
if (last)
|
|
Packit Service |
db8eaa |
v = snd_pcm_hw_param_set_last(pcm, params, var, dir);
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
v = snd_pcm_hw_param_set_first(pcm, params, var, dir);
|
|
Packit Service |
db8eaa |
assert(v >= 0);
|
|
Packit Service |
db8eaa |
return v;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_param_set_near_minmax(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int min, int *mindir,
|
|
Packit Service |
db8eaa |
unsigned int max, int *maxdir)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t tmp;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
if (!boundary_lt(min, *mindir, max, *maxdir))
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_set_near(pcm, params, var, &min, mindir);
|
|
Packit Service |
db8eaa |
tmp = *params;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &min, mindir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
if (boundary_lt(min, *mindir, max, *maxdir)) {
|
|
Packit Service |
db8eaa |
tmp = *params;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &max, maxdir);
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
max = min;
|
|
Packit Service |
db8eaa |
*maxdir = *mindir;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_minmax(pcm, params, SND_CHANGE, var, &min, mindir,
|
|
Packit Service |
db8eaa |
&max, maxdir);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_refine_near(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *src)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
unsigned int min, max;
|
|
Packit Service |
db8eaa |
int mindir, maxdir, err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if ((err = snd_pcm_hw_param_get_min(src, var, &min, &mindir)) < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
if ((err = snd_pcm_hw_param_get_max(src, var, &max, &maxdir)) < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
if ((err = snd_pcm_hw_param_set_near_minmax(pcm, params, var,
|
|
Packit Service |
db8eaa |
min, &mindir, max, &maxdir)) < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_refine_multiple(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *src)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const snd_interval_t *it = hw_param_interval_c(src, var);
|
|
Packit Service |
db8eaa |
const snd_interval_t *st = hw_param_interval_c(params, var);
|
|
Packit Service |
db8eaa |
if (snd_interval_single(it)) {
|
|
Packit Service |
db8eaa |
unsigned int best = snd_interval_min(it), cur, prev;
|
|
Packit Service |
db8eaa |
cur = best;
|
|
Packit Service |
db8eaa |
for (;;) {
|
|
Packit Service |
db8eaa |
if (st->max < cur || (st->max == cur && st->openmax))
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
if (it->min <= cur && ! (it->min == cur && st->openmin)) {
|
|
Packit Service |
db8eaa |
if (! snd_pcm_hw_param_set(pcm, params, SND_TRY, var, cur, 0))
|
|
Packit Service |
db8eaa |
return 0; /* ok */
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
prev = cur;
|
|
Packit Service |
db8eaa |
cur += best;
|
|
Packit Service |
db8eaa |
if (cur <= prev)
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_refine_near(pcm, params, var, src);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* ---- end of refinement functions ---- */
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_empty(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var))
|
|
Packit Service |
db8eaa |
return snd_mask_empty(hw_param_mask_c(params, var));
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
return snd_interval_empty(hw_param_interval_c(params, var));
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *params1)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var))
|
|
Packit Service |
db8eaa |
return snd_mask_always_eq(hw_param_mask_c(params, var),
|
|
Packit Service |
db8eaa |
hw_param_mask_c(params1, var));
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
return snd_interval_always_eq(hw_param_interval_c(params, var),
|
|
Packit Service |
db8eaa |
hw_param_interval_c(params1, var));
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *params1)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var))
|
|
Packit Service |
db8eaa |
return snd_mask_never_eq(hw_param_mask_c(params, var),
|
|
Packit Service |
db8eaa |
hw_param_mask_c(params1, var));
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var))
|
|
Packit Service |
db8eaa |
return snd_interval_never_eq(hw_param_interval_c(params, var),
|
|
Packit Service |
db8eaa |
hw_param_interval_c(params1, var));
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
#define CHOOSE_DEBUG
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Choose one configuration from configuration space defined by PARAMS
|
|
Packit Service |
db8eaa |
The configuration chosen is that obtained fixing in this order:
|
|
Packit Service |
db8eaa |
first access
|
|
Packit Service |
db8eaa |
first format
|
|
Packit Service |
db8eaa |
first subformat
|
|
Packit Service |
db8eaa |
min channels
|
|
Packit Service |
db8eaa |
min rate
|
|
Packit Service |
db8eaa |
min period time
|
|
Packit Service |
db8eaa |
max buffer size
|
|
Packit Service |
db8eaa |
min tick time
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
#ifdef CHOOSE_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_t *log;
|
|
Packit Service |
db8eaa |
snd_output_stdio_attach(&log, stderr, 0);
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "CHOOSE called:\n");
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_RATE, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
if (pcm->minperiodtime > 0) {
|
|
Packit Service |
db8eaa |
unsigned int min, max;
|
|
Packit Service |
db8eaa |
int dir = 1;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir;;
|
|
Packit Service |
db8eaa |
if (err >= 0)
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIOD_TIME, &max, &dir;;
|
|
Packit Service |
db8eaa |
if (err >= 0 && (long)min < pcm->minperiodtime &&
|
|
Packit Service |
db8eaa |
(long)max > pcm->minperiodtime) {
|
|
Packit Service |
db8eaa |
min = pcm->minperiodtime; dir = 1;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir;;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (pcm->compat) {
|
|
Packit Service |
db8eaa |
/* old mode */
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
/* determine buffer size first */
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, NULL, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
#ifdef CHOOSE_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "choose done\n");
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_close(log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
static unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
const snd_mask_t *mask = hw_param_mask_c(params, var);
|
|
Packit Service |
db8eaa |
return snd_mask_count(mask);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
const snd_interval_t *i = hw_param_interval_c(params, var);
|
|
Packit Service |
db8eaa |
return snd_interval_max(i) - snd_interval_min(i) + 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *src)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed = 0;
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
snd_mask_t *d = hw_param_mask(params, var);
|
|
Packit Service |
db8eaa |
const snd_mask_t *s = hw_param_mask_c(src, var);
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine(d, s);
|
|
Packit Service |
db8eaa |
} else if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_t *d = hw_param_interval(params, var);
|
|
Packit Service |
db8eaa |
const snd_interval_t *s = hw_param_interval_c(src, var);
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine(d, s);
|
|
Packit Service |
db8eaa |
} else
|
|
Packit Service |
db8eaa |
return 0; /* NOP / reserved */
|
|
Packit Service |
db8eaa |
if (changed) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
static void _snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *src)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
snd_mask_t *d = hw_param_mask(params, var);
|
|
Packit Service |
db8eaa |
const snd_mask_t *s = hw_param_mask_c(src, var);
|
|
Packit Service |
db8eaa |
snd_mask_copy(d, s);
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_t *d = hw_param_interval(params, var);
|
|
Packit Service |
db8eaa |
const snd_interval_t *s = hw_param_interval_c(src, var);
|
|
Packit Service |
db8eaa |
snd_interval_copy(d, s);
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << var;
|
|
Packit Service |
db8eaa |
params->rmask |= 1 << var;
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var, snd_output_t *out)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (hw_is_mask(var)) {
|
|
Packit Service |
db8eaa |
const snd_mask_t *mask = hw_param_mask_c(params, var);
|
|
Packit Service |
db8eaa |
if (snd_mask_empty(mask))
|
|
Packit Service |
db8eaa |
snd_output_puts(out, " NONE");
|
|
Packit Service |
db8eaa |
else if (snd_mask_full(mask))
|
|
Packit Service |
db8eaa |
snd_output_puts(out, " ALL");
|
|
Packit Service |
db8eaa |
else {
|
|
Packit Service |
db8eaa |
unsigned int k;
|
|
Packit Service |
db8eaa |
for (k = 0; k <= SND_MASK_MAX; ++k) {
|
|
Packit Service |
db8eaa |
if (snd_mask_test(mask, k)) {
|
|
Packit Service |
db8eaa |
const char *s;
|
|
Packit Service |
db8eaa |
switch (var) {
|
|
Packit Service |
db8eaa |
case SND_PCM_HW_PARAM_ACCESS:
|
|
Packit Service |
db8eaa |
s = snd_pcm_access_name(k);
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_PCM_HW_PARAM_FORMAT:
|
|
Packit Service |
db8eaa |
s = snd_pcm_format_name(k);
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
case SND_PCM_HW_PARAM_SUBFORMAT:
|
|
Packit Service |
db8eaa |
s = snd_pcm_subformat_name(k);
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
default:
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
s = NULL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (s) {
|
|
Packit Service |
db8eaa |
snd_output_putc(out, ' ');
|
|
Packit Service |
db8eaa |
snd_output_puts(out, s);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (hw_is_interval(var)) {
|
|
Packit Service |
db8eaa |
snd_interval_print(hw_param_interval_c(params, var), out);
|
|
Packit Service |
db8eaa |
return;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static const char *const snd_pcm_hw_param_names[] = {
|
|
Packit Service |
db8eaa |
HW_PARAM(ACCESS),
|
|
Packit Service |
db8eaa |
HW_PARAM(FORMAT),
|
|
Packit Service |
db8eaa |
HW_PARAM(SUBFORMAT),
|
|
Packit Service |
db8eaa |
HW_PARAM(SAMPLE_BITS),
|
|
Packit Service |
db8eaa |
HW_PARAM(FRAME_BITS),
|
|
Packit Service |
db8eaa |
HW_PARAM(CHANNELS),
|
|
Packit Service |
db8eaa |
HW_PARAM(RATE),
|
|
Packit Service |
db8eaa |
HW_PARAM(PERIOD_TIME),
|
|
Packit Service |
db8eaa |
HW_PARAM(PERIOD_SIZE),
|
|
Packit Service |
db8eaa |
HW_PARAM(PERIOD_BYTES),
|
|
Packit Service |
db8eaa |
HW_PARAM(PERIODS),
|
|
Packit Service |
db8eaa |
HW_PARAM(BUFFER_TIME),
|
|
Packit Service |
db8eaa |
HW_PARAM(BUFFER_SIZE),
|
|
Packit Service |
db8eaa |
HW_PARAM(BUFFER_BYTES),
|
|
Packit Service |
db8eaa |
HW_PARAM(TICK_TIME),
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
const char *snd_pcm_hw_param_name(snd_pcm_hw_param_t param)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
assert(param <= SND_PCM_HW_PARAM_LAST_INTERVAL);
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_names[param];
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
/* Strategies */
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
struct _snd_pcm_hw_strategy {
|
|
Packit Service |
db8eaa |
unsigned int badness_min, badness_max;
|
|
Packit Service |
db8eaa |
int (*choose_param)(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy);
|
|
Packit Service |
db8eaa |
int (*next_value)(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
unsigned int param,
|
|
Packit Service |
db8eaa |
int value, int *dir,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy);
|
|
Packit Service |
db8eaa |
int (*min_badness)(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
unsigned int max_badness,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy);
|
|
Packit Service |
db8eaa |
void *private_data;
|
|
Packit Service |
db8eaa |
void (*free)(snd_pcm_hw_strategy_t *strategy);
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Independent badness */
|
|
Packit Service |
db8eaa |
typedef struct _snd_pcm_hw_strategy_simple snd_pcm_hw_strategy_simple_t;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
struct _snd_pcm_hw_strategy_simple {
|
|
Packit Service |
db8eaa |
int valid;
|
|
Packit Service |
db8eaa |
unsigned int order;
|
|
Packit Service |
db8eaa |
int (*next_value)(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
unsigned int param,
|
|
Packit Service |
db8eaa |
int value, int *dir,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *par);
|
|
Packit Service |
db8eaa |
unsigned int (*min_badness)(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
unsigned int param,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *par);
|
|
Packit Service |
db8eaa |
void *private_data;
|
|
Packit Service |
db8eaa |
void (*free)(snd_pcm_hw_strategy_simple_t *strategy);
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
typedef struct _snd_pcm_hw_strategy_simple_near {
|
|
Packit Service |
db8eaa |
int best;
|
|
Packit Service |
db8eaa |
unsigned int mul;
|
|
Packit Service |
db8eaa |
} snd_pcm_hw_strategy_simple_near_t;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
typedef struct _snd_pcm_hw_strategy_simple_choices {
|
|
Packit Service |
db8eaa |
unsigned int count;
|
|
Packit Service |
db8eaa |
/* choices need to be sorted on ascending badness */
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_choices_list_t *choices;
|
|
Packit Service |
db8eaa |
} snd_pcm_hw_strategy_simple_choices_t;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy,
|
|
Packit Service |
db8eaa |
unsigned int badness_min,
|
|
Packit Service |
db8eaa |
unsigned int badness_max)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t best_params;
|
|
Packit Service |
db8eaa |
int var;
|
|
Packit Service |
db8eaa |
int value, dir;
|
|
Packit Service |
db8eaa |
unsigned int best_badness;
|
|
Packit Service |
db8eaa |
int badness = strategy->min_badness(params, badness_max, pcm, strategy);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t params1;
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
printf("\nBadness: %d\n", badness);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, stdout);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
if (badness < 0)
|
|
Packit Service |
db8eaa |
return badness;
|
|
Packit Service |
db8eaa |
if ((unsigned int)badness > badness_min)
|
|
Packit Service |
db8eaa |
badness_min = badness_min;
|
|
Packit Service |
db8eaa |
var = strategy->choose_param(params, pcm, strategy);
|
|
Packit Service |
db8eaa |
if (var < 0)
|
|
Packit Service |
db8eaa |
return badness;
|
|
Packit Service |
db8eaa |
best_badness = UINT_MAX;
|
|
Packit Service |
db8eaa |
value = -1;
|
|
Packit Service |
db8eaa |
while (1) {
|
|
Packit Service |
db8eaa |
params1 = *params;
|
|
Packit Service |
db8eaa |
value = strategy->next_value(¶ms1, var, value, &dir, pcm, strategy);
|
|
Packit Service |
db8eaa |
if (value < 0)
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
badness = snd_pcm_hw_params_strategy(pcm, ¶ms1, strategy, badness_min, badness_max);
|
|
Packit Service |
db8eaa |
if (badness >= 0) {
|
|
Packit Service |
db8eaa |
if ((unsigned int) badness <= badness_min) {
|
|
Packit Service |
db8eaa |
*params = params1;
|
|
Packit Service |
db8eaa |
return badness;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
best_badness = badness;
|
|
Packit Service |
db8eaa |
best_params = params1;
|
|
Packit Service |
db8eaa |
badness_max = badness - 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (best_badness == UINT_MAX) {
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
*params = best_params;
|
|
Packit Service |
db8eaa |
return best_badness;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void snd_pcm_hw_strategy_simple_free(snd_pcm_hw_strategy_t *strategy)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
|
|
Packit Service |
db8eaa |
int k;
|
|
Packit Service |
db8eaa |
for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++k) {
|
|
Packit Service |
db8eaa |
if (pars[k].valid && pars[k].free)
|
|
Packit Service |
db8eaa |
pars[k].free(&pars[k]);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
free(pars);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_choose_param(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var;
|
|
Packit Service |
db8eaa |
int best_var = -1;
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
|
|
Packit Service |
db8eaa |
unsigned int min_choices = UINT_MAX;
|
|
Packit Service |
db8eaa |
unsigned int min_order = UINT_MAX;
|
|
Packit Service |
db8eaa |
for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++var) {
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *p = &pars[var];
|
|
Packit Service |
db8eaa |
unsigned int choices;
|
|
Packit Service |
db8eaa |
if (!p->valid)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
choices = snd_pcm_hw_param_count(params, var);
|
|
Packit Service |
db8eaa |
if (choices == 1)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
assert(choices != 0);
|
|
Packit Service |
db8eaa |
if (p->order < min_order ||
|
|
Packit Service |
db8eaa |
(p->order == min_order &&
|
|
Packit Service |
db8eaa |
choices < min_choices)) {
|
|
Packit Service |
db8eaa |
min_order = p->order;
|
|
Packit Service |
db8eaa |
min_choices = choices;
|
|
Packit Service |
db8eaa |
best_var = var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return best_var;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_next_value(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
int value, int *dir,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
|
|
Packit Service |
db8eaa |
assert(pars[var].valid);
|
|
Packit Service |
db8eaa |
return pars[var].next_value(params, var, value, dir, pcm, &pars[var]);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_min_badness(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
unsigned int max_badness,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_t *strategy)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var;
|
|
Packit Service |
db8eaa |
unsigned int badness = 0;
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
|
|
Packit Service |
db8eaa |
for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++var) {
|
|
Packit Service |
db8eaa |
unsigned int b;
|
|
Packit Service |
db8eaa |
if (!pars[var].valid)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
b = pars[var].min_badness(params, var, pcm, &pars[var]);
|
|
Packit Service |
db8eaa |
if (b > max_badness || max_badness - b < badness)
|
|
Packit Service |
db8eaa |
return -E2BIG;
|
|
Packit Service |
db8eaa |
badness += b;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return badness;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void snd_pcm_hw_strategy_simple_near_free(snd_pcm_hw_strategy_simple_t *par)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
|
|
Packit Service |
db8eaa |
free(p);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
unsigned int snd_pcm_hw_strategy_simple_near_min_badness(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *par)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t params1 = *params;
|
|
Packit Service |
db8eaa |
int value = snd_pcm_hw_param_set_near(pcm, ¶ms1, var, p->best, 0);
|
|
Packit Service |
db8eaa |
int diff;
|
|
Packit Service |
db8eaa |
assert(value >= 0);
|
|
Packit Service |
db8eaa |
diff = p->best - value;
|
|
Packit Service |
db8eaa |
if (diff < 0)
|
|
Packit Service |
db8eaa |
diff = -diff;
|
|
Packit Service |
db8eaa |
return diff * p->mul;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_near_next_value(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
int value, int *dir,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *par)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
|
|
Packit Service |
db8eaa |
if (value < 0) {
|
|
Packit Service |
db8eaa |
*dir = 0;
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_set_near(pcm, params, var, p->best, dir);
|
|
Packit Service |
db8eaa |
} else
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_param_set_next(pcm, params, var, p->best, 0, value, dir);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void snd_pcm_hw_strategy_simple_choices_free(snd_pcm_hw_strategy_simple_t *par)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
|
|
Packit Service |
db8eaa |
// free(p->choices);
|
|
Packit Service |
db8eaa |
free(p);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
unsigned int snd_pcm_hw_strategy_simple_choices_min_badness(const snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *par)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
|
|
Packit Service |
db8eaa |
unsigned int k;
|
|
Packit Service |
db8eaa |
for (k = 0; k < p->count; ++k) {
|
|
Packit Service |
db8eaa |
if (snd_pcm_hw_param_set(pcm, (snd_pcm_hw_params_t *) params, SND_TEST, var, p->choices[k].value, 0))
|
|
Packit Service |
db8eaa |
return p->choices[k].badness;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
assert(0);
|
|
Packit Service |
db8eaa |
return UINT_MAX;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
int value, int *dir,
|
|
Packit Service |
db8eaa |
snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_t *par)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
|
|
Packit Service |
db8eaa |
unsigned int k = 0;
|
|
Packit Service |
db8eaa |
if (value >= 0) {
|
|
Packit Service |
db8eaa |
for (; k < p->count; ++k) {
|
|
Packit Service |
db8eaa |
if (p->choices[k].value == (unsigned int) value) {
|
|
Packit Service |
db8eaa |
k++;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
for (; k < p->count; ++k) {
|
|
Packit Service |
db8eaa |
unsigned int v = p->choices[k].value;
|
|
Packit Service |
db8eaa |
int err = snd_pcm_hw_param_set(pcm, params, SND_TRY, var, v, 0);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
*dir = 0;
|
|
Packit Service |
db8eaa |
return v;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return -1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
void snd_pcm_hw_strategy_free(snd_pcm_hw_strategy_t *strategy)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
if (strategy->free)
|
|
Packit Service |
db8eaa |
strategy->free(strategy);
|
|
Packit Service |
db8eaa |
free(strategy);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple(snd_pcm_hw_strategy_t **strategyp,
|
|
Packit Service |
db8eaa |
unsigned int badness_min,
|
|
Packit Service |
db8eaa |
unsigned int badness_max)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_t *data;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_t *s;
|
|
Packit Service |
db8eaa |
assert(strategyp);
|
|
Packit Service |
db8eaa |
data = calloc(SND_PCM_HW_PARAM_LAST_INTERVAL + 1, sizeof(*data));
|
|
Packit Service |
db8eaa |
if (!data)
|
|
Packit Service |
db8eaa |
return -ENOMEM;
|
|
Packit Service |
db8eaa |
s = calloc(1, sizeof(*s));
|
|
Packit Service |
db8eaa |
if (!s) {
|
|
Packit Service |
db8eaa |
free(data);
|
|
Packit Service |
db8eaa |
return -ENOMEM;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
s->choose_param = snd_pcm_hw_strategy_simple_choose_param;
|
|
Packit Service |
db8eaa |
s->next_value = snd_pcm_hw_strategy_simple_next_value;
|
|
Packit Service |
db8eaa |
s->min_badness = snd_pcm_hw_strategy_simple_min_badness;
|
|
Packit Service |
db8eaa |
s->badness_min = badness_min;
|
|
Packit Service |
db8eaa |
s->badness_max = badness_max;
|
|
Packit Service |
db8eaa |
s->private_data = data;
|
|
Packit Service |
db8eaa |
s->free = snd_pcm_hw_strategy_simple_free;
|
|
Packit Service |
db8eaa |
*strategyp = s;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy,
|
|
Packit Service |
db8eaa |
int order,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int best,
|
|
Packit Service |
db8eaa |
unsigned int mul)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_t *s = strategy->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_near_t *data;
|
|
Packit Service |
db8eaa |
assert(strategy);
|
|
Packit Service |
db8eaa |
assert(var <= SND_PCM_HW_PARAM_LAST_INTERVAL);
|
|
Packit Service |
db8eaa |
assert(!s->valid);
|
|
Packit Service |
db8eaa |
data = calloc(1, sizeof(*data));
|
|
Packit Service |
db8eaa |
if (!data)
|
|
Packit Service |
db8eaa |
return -ENOMEM;
|
|
Packit Service |
db8eaa |
data->best = best;
|
|
Packit Service |
db8eaa |
data->mul = mul;
|
|
Packit Service |
db8eaa |
s += var;
|
|
Packit Service |
db8eaa |
s->order = order;
|
|
Packit Service |
db8eaa |
s->valid = 1;
|
|
Packit Service |
db8eaa |
s->next_value = snd_pcm_hw_strategy_simple_near_next_value;
|
|
Packit Service |
db8eaa |
s->min_badness = snd_pcm_hw_strategy_simple_near_min_badness;
|
|
Packit Service |
db8eaa |
s->private_data = data;
|
|
Packit Service |
db8eaa |
s->free = snd_pcm_hw_strategy_simple_near_free;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy,
|
|
Packit Service |
db8eaa |
int order,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var,
|
|
Packit Service |
db8eaa |
unsigned int count,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_choices_list_t *choices)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_t *s = strategy->private_data;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_strategy_simple_choices_t *data;
|
|
Packit Service |
db8eaa |
assert(strategy);
|
|
Packit Service |
db8eaa |
assert(var <= SND_PCM_HW_PARAM_LAST_INTERVAL);
|
|
Packit Service |
db8eaa |
assert(!s->valid);
|
|
Packit Service |
db8eaa |
data = calloc(1, sizeof(*data));
|
|
Packit Service |
db8eaa |
if (!data)
|
|
Packit Service |
db8eaa |
return -ENOMEM;
|
|
Packit Service |
db8eaa |
data->count = count;
|
|
Packit Service |
db8eaa |
data->choices = choices;
|
|
Packit Service |
db8eaa |
s += var;
|
|
Packit Service |
db8eaa |
s->valid = 1;
|
|
Packit Service |
db8eaa |
s->order = order;
|
|
Packit Service |
db8eaa |
s->next_value = snd_pcm_hw_strategy_simple_choices_next_value;
|
|
Packit Service |
db8eaa |
s->min_badness = snd_pcm_hw_strategy_simple_choices_min_badness;
|
|
Packit Service |
db8eaa |
s->private_data = data;
|
|
Packit Service |
db8eaa |
s->free = snd_pcm_hw_strategy_simple_choices_free;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_params_try_explain_failure1(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *fail,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *success,
|
|
Packit Service |
db8eaa |
unsigned int depth,
|
|
Packit Service |
db8eaa |
snd_output_t *out)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t i;
|
|
Packit Service |
db8eaa |
if (depth < 1)
|
|
Packit Service |
db8eaa |
return -ENOENT;
|
|
Packit Service |
db8eaa |
for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; var++) {
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
i = *success;
|
|
Packit Service |
db8eaa |
_snd_pcm_hw_param_copy(&i, var, fail);
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, &i);
|
|
Packit Service |
db8eaa |
if (err == 0 &&
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, out) < 0)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
snd_output_printf(out, "%s: ", snd_pcm_hw_param_name(var));
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_dump(fail, var, out);
|
|
Packit Service |
db8eaa |
snd_output_putc(out, '\n');
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return -ENOENT;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *fail,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *success,
|
|
Packit Service |
db8eaa |
unsigned int depth,
|
|
Packit Service |
db8eaa |
snd_output_t *out)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t i, any;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_t var;
|
|
Packit Service |
db8eaa |
int done = 0;
|
|
Packit Service |
db8eaa |
assert(pcm && fail);
|
|
Packit Service |
db8eaa |
for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; var++) {
|
|
Packit Service |
db8eaa |
if (!snd_pcm_hw_param_empty(fail, var))
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
snd_output_printf(out, "%s is empty\n", snd_pcm_hw_param_name(var));
|
|
Packit Service |
db8eaa |
done = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (done)
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
i = *fail;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, &i);
|
|
Packit Service |
db8eaa |
if (err == 0) {
|
|
Packit Service |
db8eaa |
snd_output_printf(out, "Configuration is virtually correct\n");
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (!success) {
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_any(pcm, &any;;
|
|
Packit Service |
db8eaa |
success = &any;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return snd_pcm_hw_params_try_explain_failure1(pcm, fail, success, depth, out);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
typedef struct _snd_pcm_hw_rule snd_pcm_hw_rule_t;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
typedef int (*snd_pcm_hw_rule_func_t)(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule);
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
struct _snd_pcm_hw_rule {
|
|
Packit Service |
db8eaa |
int var;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_rule_func_t func;
|
|
Packit Service |
db8eaa |
int deps[4];
|
|
Packit Service |
db8eaa |
void *private_data;
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_interval_t t;
|
|
Packit Service |
db8eaa |
snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
|
|
Packit Service |
db8eaa |
hw_param_interval_c(params, rule->deps[1]), &t);
|
|
Packit Service |
db8eaa |
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_interval_t t;
|
|
Packit Service |
db8eaa |
snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
|
|
Packit Service |
db8eaa |
hw_param_interval_c(params, rule->deps[1]), &t);
|
|
Packit Service |
db8eaa |
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_interval_t t;
|
|
Packit Service |
db8eaa |
snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
|
|
Packit Service |
db8eaa |
hw_param_interval_c(params, rule->deps[1]),
|
|
Packit Service |
db8eaa |
(unsigned long) rule->private_data, &t);
|
|
Packit Service |
db8eaa |
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_interval_t t;
|
|
Packit Service |
db8eaa |
snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
|
|
Packit Service |
db8eaa |
(unsigned long) rule->private_data,
|
|
Packit Service |
db8eaa |
hw_param_interval_c(params, rule->deps[1]), &t);
|
|
Packit Service |
db8eaa |
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed = 0;
|
|
Packit Service |
db8eaa |
snd_pcm_format_t k;
|
|
Packit Service |
db8eaa |
snd_mask_t *mask = hw_param_mask(params, rule->var);
|
|
Packit Service |
db8eaa |
snd_interval_t *i = hw_param_interval(params, rule->deps[0]);
|
|
Packit Service |
db8eaa |
for (k = 0; k <= SND_PCM_FORMAT_LAST; k++) {
|
|
Packit Service |
db8eaa |
int bits;
|
|
Packit Service |
db8eaa |
if (!snd_pcm_format_mask_test(mask, k))
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
bits = snd_pcm_format_physical_width(k);
|
|
Packit Service |
db8eaa |
if (bits < 0)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
if (!snd_interval_test(i, (unsigned int) bits)) {
|
|
Packit Service |
db8eaa |
snd_pcm_format_mask_reset(mask, k);
|
|
Packit Service |
db8eaa |
if (snd_mask_empty(mask))
|
|
Packit Service |
db8eaa |
return -EINVAL;
|
|
Packit Service |
db8eaa |
changed = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *rule)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
unsigned int min, max;
|
|
Packit Service |
db8eaa |
snd_pcm_format_t k;
|
|
Packit Service |
db8eaa |
snd_interval_t *i = hw_param_interval(params, rule->var);
|
|
Packit Service |
db8eaa |
snd_mask_t *mask = hw_param_mask(params, rule->deps[0]);
|
|
Packit Service |
db8eaa |
int c, changed = 0;
|
|
Packit Service |
db8eaa |
min = UINT_MAX;
|
|
Packit Service |
db8eaa |
max = 0;
|
|
Packit Service |
db8eaa |
for (k = 0; k <= SND_PCM_FORMAT_LAST; k++) {
|
|
Packit Service |
db8eaa |
int bits;
|
|
Packit Service |
db8eaa |
if (!snd_pcm_format_mask_test(mask, k))
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
bits = snd_pcm_format_physical_width(k);
|
|
Packit Service |
db8eaa |
if (bits < 0)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
if (min > (unsigned)bits)
|
|
Packit Service |
db8eaa |
min = bits;
|
|
Packit Service |
db8eaa |
if (max < (unsigned)bits)
|
|
Packit Service |
db8eaa |
max = bits;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
c = snd_interval_refine_min(i, min, 0);
|
|
Packit Service |
db8eaa |
if (c < 0)
|
|
Packit Service |
db8eaa |
return c;
|
|
Packit Service |
db8eaa |
if (c)
|
|
Packit Service |
db8eaa |
changed = 1;
|
|
Packit Service |
db8eaa |
c = snd_interval_refine_max(i, max, 0);
|
|
Packit Service |
db8eaa |
if (c < 0)
|
|
Packit Service |
db8eaa |
return c;
|
|
Packit Service |
db8eaa |
if (c)
|
|
Packit Service |
db8eaa |
changed = 1;
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static const snd_pcm_hw_rule_t refine_rules[] = {
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_FORMAT,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_format,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_SAMPLE_BITS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_sample_bits,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_FORMAT,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_SAMPLE_BITS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_div,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_FRAME_BITS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_CHANNELS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_FRAME_BITS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mul,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_SAMPLE_BITS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_CHANNELS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_FRAME_BITS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_BYTES,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_PERIOD_SIZE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 8,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_FRAME_BITS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_BYTES,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_BUFFER_SIZE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 8,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_CHANNELS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_div,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_FRAME_BITS,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_RATE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_PERIOD_TIME, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 1000000,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_RATE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_BUFFER_TIME, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 1000000,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_PERIODS,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_div,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_PERIOD_SIZE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_div,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_PERIODS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_BYTES,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FRAME_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 8,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_muldivk,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_TIME,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_RATE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 1000000,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mul,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_PERIODS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_BYTES,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FRAME_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 8,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_muldivk,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_TIME,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_RATE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 1000000,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_PERIOD_BYTES,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_muldivk,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FRAME_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 8,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_BUFFER_BYTES,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_muldivk,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_FRAME_BITS, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 8,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_PERIOD_TIME,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_RATE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 1000000,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
.var = SND_PCM_HW_PARAM_BUFFER_TIME,
|
|
Packit Service |
db8eaa |
.func = snd_pcm_hw_rule_mulkdiv,
|
|
Packit Service |
db8eaa |
.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
|
|
Packit Service |
db8eaa |
SND_PCM_HW_PARAM_RATE, -1 },
|
|
Packit Service |
db8eaa |
.private_data = (void*) 1000000,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#define RULES (sizeof(refine_rules) / sizeof(refine_rules[0]))
|
|
Packit Service |
db8eaa |
#define PCM_BIT(x) \
|
|
Packit Service |
db8eaa |
(1U << ((x) < 32 ? (x) : ((x) - 32)))
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static const snd_mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_MASK + 1] = {
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK] = {
|
|
Packit Service |
db8eaa |
.bits = {
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_ACCESS_MMAP_COMPLEX) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = {
|
|
Packit Service |
db8eaa |
.bits = {
|
|
Packit Service |
db8eaa |
/* first 32bits */
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S8) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U8) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S16_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S16_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U16_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U16_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S24_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S24_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U24_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U24_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S32_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S32_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U32_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U32_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_FLOAT_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_FLOAT_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_FLOAT64_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_FLOAT64_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_IEC958_SUBFRAME) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_IEC958_SUBFRAME) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_MU_LAW) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_A_LAW) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_IMA_ADPCM) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_MPEG) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_GSM) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S20_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S20_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U20_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U20_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_SPECIAL),
|
|
Packit Service |
db8eaa |
/* second 32bits */
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S24_3LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S24_3BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U24_3LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U24_3BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S20_3LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S20_3BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U20_3LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U20_3BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S18_3LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_S18_3BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U18_3LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_U18_3BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_G723_24) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_G723_24) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_G723_40) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_G723_40) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_DSD_U8) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_DSD_U16_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_DSD_U32_LE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_DSD_U16_BE) |
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_FORMAT_DSD_U32_BE)
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_SUBFORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = {
|
|
Packit Service |
db8eaa |
.bits = {
|
|
Packit Service |
db8eaa |
PCM_BIT(SNDRV_PCM_SUBFORMAT_STD)
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static const snd_interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_PARAM_FIRST_INTERVAL + 1] = {
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_SAMPLE_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_FRAME_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_CHANNELS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_PERIOD_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 0, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_PERIOD_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 0, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_PERIOD_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 0, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_PERIODS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 0, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_BUFFER_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_BUFFER_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_BUFFER_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 1, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
[SND_PCM_HW_PARAM_TICK_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
|
|
Packit Service |
db8eaa |
.min = 0, .max = UINT_MAX,
|
|
Packit Service |
db8eaa |
.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
|
|
Packit Service |
db8eaa |
},
|
|
Packit Service |
db8eaa |
};
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
#define RULES_DEBUG
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
unsigned int k;
|
|
Packit Service |
db8eaa |
snd_interval_t *i;
|
|
Packit Service |
db8eaa |
unsigned int rstamps[RULES];
|
|
Packit Service |
db8eaa |
unsigned int vstamps[SND_PCM_HW_PARAM_LAST_INTERVAL + 1];
|
|
Packit Service |
db8eaa |
unsigned int stamp = 2;
|
|
Packit Service |
db8eaa |
int changed, again;
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_t *log;
|
|
Packit Service |
db8eaa |
snd_output_stdio_attach(&log, stderr, 0);
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "refine_soft '%s' (begin)\n", pcm->name);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) {
|
|
Packit Service |
db8eaa |
if (!(params->rmask & (1 << k)))
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
changed = snd_mask_refine(hw_param_mask(params, k),
|
|
Packit Service |
db8eaa |
&refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]);
|
|
Packit Service |
db8eaa |
if (changed)
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << k;
|
|
Packit Service |
db8eaa |
if (changed < 0)
|
|
Packit Service |
db8eaa |
goto _err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) {
|
|
Packit Service |
db8eaa |
if (!(params->rmask & (1 << k)))
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
changed = snd_interval_refine(hw_param_interval(params, k),
|
|
Packit Service |
db8eaa |
&refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
|
|
Packit Service |
db8eaa |
if (changed)
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << k;
|
|
Packit Service |
db8eaa |
if (changed < 0)
|
|
Packit Service |
db8eaa |
goto _err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
for (k = 0; k < RULES; k++)
|
|
Packit Service |
db8eaa |
rstamps[k] = 0;
|
|
Packit Service |
db8eaa |
for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
|
|
Packit Service |
db8eaa |
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
|
|
Packit Service |
db8eaa |
do {
|
|
Packit Service |
db8eaa |
again = 0;
|
|
Packit Service |
db8eaa |
for (k = 0; k < RULES; k++) {
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_rule_t *r = &refine_rules[k];
|
|
Packit Service |
db8eaa |
unsigned int d;
|
|
Packit Service |
db8eaa |
int doit = 0;
|
|
Packit Service |
db8eaa |
for (d = 0; r->deps[d] >= 0; d++) {
|
|
Packit Service |
db8eaa |
if (vstamps[r->deps[d]] > rstamps[k]) {
|
|
Packit Service |
db8eaa |
doit = 1;
|
|
Packit Service |
db8eaa |
break;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (!doit)
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "Rule %d (%p): ", k, r->func);
|
|
Packit Service |
db8eaa |
if (r->var >= 0) {
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var));
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_dump(params, r->var, log);
|
|
Packit Service |
db8eaa |
snd_output_puts(log, " -> ");
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
changed = r->func(params, r);
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
if (r->var >= 0)
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_dump(params, r->var, log);
|
|
Packit Service |
db8eaa |
for (d = 0; r->deps[d] >= 0; d++) {
|
|
Packit Service |
db8eaa |
snd_output_printf(log, " %s=", snd_pcm_hw_param_name(r->deps[d]));
|
|
Packit Service |
db8eaa |
snd_pcm_hw_param_dump(params, r->deps[d], log);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
snd_output_putc(log, '\n');
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
rstamps[k] = stamp;
|
|
Packit Service |
db8eaa |
if (changed && r->var >= 0) {
|
|
Packit Service |
db8eaa |
params->cmask |= 1 << r->var;
|
|
Packit Service |
db8eaa |
vstamps[r->var] = stamp;
|
|
Packit Service |
db8eaa |
again = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (changed < 0)
|
|
Packit Service |
db8eaa |
goto _err;
|
|
Packit Service |
db8eaa |
stamp++;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} while (again);
|
|
Packit Service |
db8eaa |
if (!params->msbits) {
|
|
Packit Service |
db8eaa |
i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
|
|
Packit Service |
db8eaa |
if (snd_interval_single(i))
|
|
Packit Service |
db8eaa |
params->msbits = snd_interval_value(i);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if (!params->rate_den) {
|
|
Packit Service |
db8eaa |
i = hw_param_interval(params, SND_PCM_HW_PARAM_RATE);
|
|
Packit Service |
db8eaa |
if (snd_interval_single(i)) {
|
|
Packit Service |
db8eaa |
params->rate_num = snd_interval_value(i);
|
|
Packit Service |
db8eaa |
params->rate_den = 1;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
params->rmask = 0;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
_err:
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "refine_soft '%s' (end-%i)\n", pcm->name, changed);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_close(log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
return changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
unsigned int vars,
|
|
Packit Service |
db8eaa |
const snd_pcm_hw_params_t *src)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int changed, err = 0;
|
|
Packit Service |
db8eaa |
unsigned int k;
|
|
Packit Service |
db8eaa |
for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++k) {
|
|
Packit Service |
db8eaa |
if (!(vars & (1 << k)))
|
|
Packit Service |
db8eaa |
continue;
|
|
Packit Service |
db8eaa |
changed = _snd_pcm_hw_param_refine(params, k, src);
|
|
Packit Service |
db8eaa |
if (changed < 0)
|
|
Packit Service |
db8eaa |
err = changed;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
params->info &= src->info;
|
|
Packit Service |
db8eaa |
params->flags = src->flags; /* propagate all flags to slave */
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
int (*cprepare)(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params),
|
|
Packit Service |
db8eaa |
int (*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 |
int (*sprepare)(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params),
|
|
Packit Service |
db8eaa |
int (*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 |
int (*srefine)(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *sparams))
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_t *log;
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t sparams;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
unsigned int cmask, changed;
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_stdio_attach(&log, stderr, 0);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
err = cprepare(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = sprepare(pcm, &sparams);
|
|
Packit Service |
db8eaa |
if (err < 0) {
|
|
Packit Service |
db8eaa |
SNDERR("Slave PCM not usable");
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "hw_refine_slave - enter '%s'\n", pcm->name);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
do {
|
|
Packit Service |
db8eaa |
cmask = params->cmask;
|
|
Packit Service |
db8eaa |
params->cmask = 0;
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "schange '%s' (client)\n", pcm->name);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "schange '%s' (slave)\n", pcm->name);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(&sparams, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
err = schange(pcm, params, &sparams);
|
|
Packit Service |
db8eaa |
if (err >= 0) {
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "srefine '%s' (client)\n", pcm->name);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "srefine '%s' (slave)\n", pcm->name);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(&sparams, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
err = srefine(pcm, &sparams);
|
|
Packit Service |
db8eaa |
if (err < 0) {
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "srefine '%s', err < 0 (%i) (client)\n", pcm->name, err);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "srefine '%s', err < 0 (%i) (slave)\n", pcm->name, err);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(&sparams, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
cchange(pcm, params, &sparams);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
} else {
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "schange '%s', err < 0 (%i) (client)\n", pcm->name, err);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "schange '%s', err < 0 (%i) (slave)\n", pcm->name, err);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(&sparams, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
cchange(pcm, params, &sparams);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "cchange '%s'\n", pcm->name);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
err = cchange(pcm, params, &sparams);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "refine_soft '%s'\n", pcm->name);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine_soft(pcm, params);
|
|
Packit Service |
db8eaa |
changed = params->cmask;
|
|
Packit Service |
db8eaa |
params->cmask |= cmask;
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "refine_soft ok '%s'\n", pcm->name);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
} while (changed);
|
|
Packit Service |
db8eaa |
#ifdef RULES_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "refine_slave - leave '%s'\n", pcm->name);
|
|
Packit Service |
db8eaa |
snd_output_close(log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
Packit Service |
db8eaa |
int (*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 |
int (*sprepare)(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *params),
|
|
Packit Service |
db8eaa |
int (*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 |
int (*sparams)(snd_pcm_t *pcm,
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t *sparams))
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_t slave_params;
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
err = sprepare(pcm, &slave_params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = schange(pcm, params, &slave_params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
err = sparams(pcm, &slave_params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
cchange(pcm, params, &slave_params);
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
static int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
assert(pcm && params);
|
|
Packit Service |
db8eaa |
assert(pcm->setup);
|
|
Packit Service |
db8eaa |
params->proto = SNDRV_PCM_VERSION;
|
|
Packit Service |
db8eaa |
params->tstamp_mode = SND_PCM_TSTAMP_NONE;
|
|
Packit Service |
db8eaa |
params->tstamp_type = pcm->tstamp_type;
|
|
Packit Service |
db8eaa |
params->period_step = 1;
|
|
Packit Service |
db8eaa |
params->sleep_min = 0;
|
|
Packit Service |
db8eaa |
params->avail_min = pcm->period_size;
|
|
Packit Service |
db8eaa |
params->xfer_align = 1;
|
|
Packit Service |
db8eaa |
params->start_threshold = 1;
|
|
Packit Service |
db8eaa |
params->stop_threshold = pcm->buffer_size;
|
|
Packit Service |
db8eaa |
params->silence_threshold = 0;
|
|
Packit Service |
db8eaa |
params->silence_size = 0;
|
|
Packit Service |
db8eaa |
params->boundary = pcm->buffer_size;
|
|
Packit Service |
db8eaa |
while (params->boundary * 2 <= LONG_MAX - pcm->buffer_size)
|
|
Packit Service |
db8eaa |
params->boundary *= 2;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
#if 0
|
|
Packit Service |
db8eaa |
#define REFINE_DEBUG
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int res;
|
|
Packit Service |
db8eaa |
#ifdef REFINE_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_t *log;
|
|
Packit Service |
db8eaa |
snd_output_stdio_attach(&log, stderr, 0);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
assert(pcm && params);
|
|
Packit Service |
db8eaa |
#ifdef REFINE_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "REFINE called:\n");
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
if (pcm->ops->hw_refine)
|
|
Packit Service |
db8eaa |
res = pcm->ops->hw_refine(pcm->op_arg, params);
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
res = -ENOSYS;
|
|
Packit Service |
db8eaa |
#ifdef REFINE_DEBUG
|
|
Packit Service |
db8eaa |
snd_output_printf(log, "refine done - result = %i\n", res);
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_dump(params, log);
|
|
Packit Service |
db8eaa |
snd_output_close(log);
|
|
Packit Service |
db8eaa |
#endif
|
|
Packit Service |
db8eaa |
return res;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Install one of the configurations present in configuration
|
|
Packit Service |
db8eaa |
space defined by PARAMS.
|
|
Packit Service |
db8eaa |
The configuration chosen is that obtained fixing in this order:
|
|
Packit Service |
db8eaa |
first access
|
|
Packit Service |
db8eaa |
first format
|
|
Packit Service |
db8eaa |
first subformat
|
|
Packit Service |
db8eaa |
min channels
|
|
Packit Service |
db8eaa |
min rate
|
|
Packit Service |
db8eaa |
min period_size
|
|
Packit Service |
db8eaa |
max periods
|
|
Packit Service |
db8eaa |
Return 0 on success otherwise a negative error code
|
|
Packit Service |
db8eaa |
*/
|
|
Packit Service |
db8eaa |
int _snd_pcm_hw_params_internal(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
Packit Service |
db8eaa |
{
|
|
Packit Service |
db8eaa |
int err;
|
|
Packit Service |
db8eaa |
snd_pcm_sw_params_t sw;
|
|
Packit Service |
db8eaa |
int fb, min_align;
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_refine(pcm, params);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
snd_pcm_hw_params_choose(pcm, params);
|
|
Packit Service |
db8eaa |
if (pcm->setup) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_hw_free(pcm);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (pcm->ops->hw_params)
|
|
Packit Service |
db8eaa |
err = pcm->ops->hw_params(pcm->op_arg, params);
|
|
Packit Service |
db8eaa |
else
|
|
Packit Service |
db8eaa |
err = -ENOSYS;
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
pcm->setup = 1;
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_access)(params, &pcm->access);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_format)(params, &pcm->format);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_subformat)(params, &pcm->subformat);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_channels)(params, &pcm->channels);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_rate)(params, &pcm->rate, 0);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_period_time)(params, &pcm->period_time, 0);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_period_size)(params, &pcm->period_size, 0);
|
|
Packit Service |
db8eaa |
INTERNAL(snd_pcm_hw_params_get_buffer_size)(params, &pcm->buffer_size);
|
|
Packit Service |
db8eaa |
pcm->sample_bits = snd_pcm_format_physical_width(pcm->format);
|
|
Packit Service |
db8eaa |
pcm->frame_bits = pcm->sample_bits * pcm->channels;
|
|
Packit Service |
db8eaa |
fb = pcm->frame_bits;
|
|
Packit Service |
db8eaa |
min_align = 1;
|
|
Packit Service |
db8eaa |
while (fb % 8) {
|
|
Packit Service |
db8eaa |
fb *= 2;
|
|
Packit Service |
db8eaa |
min_align *= 2;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
pcm->min_align = min_align;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
pcm->hw_flags = params->flags;
|
|
Packit Service |
db8eaa |
pcm->info = params->info;
|
|
Packit Service |
db8eaa |
pcm->msbits = params->msbits;
|
|
Packit Service |
db8eaa |
pcm->rate_num = params->rate_num;
|
|
Packit Service |
db8eaa |
pcm->rate_den = params->rate_den;
|
|
Packit Service |
db8eaa |
pcm->fifo_size = params->fifo_size;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
/* Default sw params */
|
|
Packit Service |
db8eaa |
memset(&sw, 0, sizeof(sw));
|
|
Packit Service |
db8eaa |
snd_pcm_sw_params_default(pcm, &sw);
|
|
Packit Service |
db8eaa |
err = snd_pcm_sw_params(pcm, &sw);
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
|
|
Packit Service |
db8eaa |
if (pcm->mmap_rw ||
|
|
Packit Service |
db8eaa |
pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
|
|
Packit Service |
db8eaa |
pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED ||
|
|
Packit Service |
db8eaa |
pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX) {
|
|
Packit Service |
db8eaa |
err = snd_pcm_mmap(pcm);
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
if (err < 0)
|
|
Packit Service |
db8eaa |
return err;
|
|
Packit Service |
db8eaa |
return 0;
|
|
Packit Service |
db8eaa |
}
|
|
Packit Service |
db8eaa |
|