mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Improved automatic start/stop
This commit is contained in:
parent
667f008cd4
commit
301a62f90a
8 changed files with 229 additions and 91 deletions
|
|
@ -53,4 +53,49 @@ typedef enum _snd_set_mode {
|
|||
size_t page_align(size_t size);
|
||||
size_t page_size(void);
|
||||
|
||||
#define HAVE_GNU_LD
|
||||
#define HAVE_ELF
|
||||
#define HAVE_ASM_PREVIOUS_DIRECTIVE
|
||||
|
||||
/* Stolen from libc-symbols.h in GNU glibc */
|
||||
|
||||
/* When a reference to SYMBOL is encountered, the linker will emit a
|
||||
warning message MSG. */
|
||||
#ifdef HAVE_GNU_LD
|
||||
# ifdef HAVE_ELF
|
||||
|
||||
/* We want the .gnu.warning.SYMBOL section to be unallocated. */
|
||||
# ifdef HAVE_ASM_PREVIOUS_DIRECTIVE
|
||||
# define __make_section_unallocated(section_string) \
|
||||
asm (".section " section_string "\n\t.previous");
|
||||
# elif defined HAVE_ASM_POPSECTION_DIRECTIVE
|
||||
# define __make_section_unallocated(section_string) \
|
||||
asm (".pushsection " section_string "\n\t.popsection");
|
||||
# else
|
||||
# define __make_section_unallocated(section_string)
|
||||
# endif
|
||||
|
||||
/* Tacking on "\n\t#" to the section name makes gcc put it's bogus
|
||||
section attributes on what looks like a comment to the assembler. */
|
||||
# ifdef HAVE_SECTION_QUOTES
|
||||
# define link_warning(symbol, msg) \
|
||||
__make_section_unallocated (".gnu.warning." #symbol) \
|
||||
static const char __evoke_link_warning_##symbol[] \
|
||||
__attribute__ ((section (".gnu.warning." #symbol "\"\n\t#\""))) = msg;
|
||||
# else
|
||||
# define link_warning(symbol, msg) \
|
||||
__make_section_unallocated (".gnu.warning." #symbol) \
|
||||
static const char __evoke_link_warning_##symbol[] \
|
||||
__attribute__ ((section (".gnu.warning." #symbol "\n\t#"))) = msg;
|
||||
# endif
|
||||
# else
|
||||
# define link_warning(symbol, msg) \
|
||||
asm (".stabs \"" msg "\",30,0,0,0\n\t" \
|
||||
".stabs \"" __SYMBOL_PREFIX #symbol "\",1,0,0,0\n");
|
||||
# endif
|
||||
#else
|
||||
/* We will never be heard; they will all die horribly. */
|
||||
# define link_warning(symbol, msg)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -172,19 +172,19 @@ typedef enum _snd_pcm_state {
|
|||
/** PCM start mode */
|
||||
typedef enum _snd_pcm_start {
|
||||
/** Automatic start on data read/write */
|
||||
SND_PCM_START_DATA = SNDRV_PCM_START_DATA,
|
||||
SND_PCM_START_DATA,
|
||||
/** Explicit start */
|
||||
SND_PCM_START_EXPLICIT = SNDRV_PCM_START_EXPLICIT,
|
||||
SND_PCM_START_LAST = SNDRV_PCM_START_LAST,
|
||||
SND_PCM_START_EXPLICIT,
|
||||
SND_PCM_START_LAST,
|
||||
} snd_pcm_start_t;
|
||||
|
||||
/** PCM xrun mode */
|
||||
typedef enum _snd_pcm_xrun {
|
||||
/** Xrun detection disabled */
|
||||
SND_PCM_XRUN_NONE = SNDRV_PCM_XRUN_NONE,
|
||||
SND_PCM_XRUN_NONE,
|
||||
/** Stop on xrun detection */
|
||||
SND_PCM_XRUN_STOP = SNDRV_PCM_XRUN_STOP,
|
||||
SND_PCM_XRUN_LAST = SNDRV_PCM_XRUN_LAST,
|
||||
SND_PCM_XRUN_STOP,
|
||||
SND_PCM_XRUN_LAST,
|
||||
} snd_pcm_xrun_t;
|
||||
|
||||
/** PCM timestamp mode */
|
||||
|
|
@ -695,6 +695,12 @@ snd_pcm_uframes_t snd_pcm_sw_params_get_avail_min(const snd_pcm_sw_params_t *par
|
|||
int snd_pcm_sw_params_set_xfer_align(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
|
||||
snd_pcm_uframes_t snd_pcm_sw_params_get_xfer_align(const snd_pcm_sw_params_t *params);
|
||||
|
||||
int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
|
||||
snd_pcm_uframes_t snd_pcm_sw_params_get_start_threshold(const snd_pcm_sw_params_t *params);
|
||||
|
||||
int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
|
||||
snd_pcm_uframes_t snd_pcm_sw_params_get_stop_threshold(const snd_pcm_sw_params_t *params);
|
||||
|
||||
int snd_pcm_sw_params_set_silence_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
|
||||
snd_pcm_uframes_t snd_pcm_sw_params_get_silence_threshold(const snd_pcm_sw_params_t *params);
|
||||
|
||||
|
|
|
|||
160
src/pcm/pcm.c
160
src/pcm/pcm.c
|
|
@ -225,13 +225,13 @@ int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
|
|||
err = pcm->ops->sw_params(pcm->op_arg, params);
|
||||
if (err < 0)
|
||||
return err;
|
||||
pcm->start_mode = snd_pcm_sw_params_get_start_mode(params);
|
||||
pcm->xrun_mode = snd_pcm_sw_params_get_xrun_mode(params);
|
||||
pcm->tstamp_mode = snd_pcm_sw_params_get_tstamp_mode(params);
|
||||
pcm->period_step = params->period_step;
|
||||
pcm->sleep_min = params->sleep_min;
|
||||
pcm->avail_min = params->avail_min;
|
||||
pcm->xfer_align = params->xfer_align;
|
||||
pcm->start_threshold = params->start_threshold;
|
||||
pcm->stop_threshold = params->stop_threshold;
|
||||
pcm->silence_threshold = params->silence_threshold;
|
||||
pcm->silence_size = params->silence_size;
|
||||
pcm->boundary = params->boundary;
|
||||
|
|
@ -713,7 +713,7 @@ const char *snd_pcm_subformat_description(snd_pcm_subformat_t subformat)
|
|||
}
|
||||
|
||||
/**
|
||||
* \brief get name of PCM start mode setting
|
||||
* \brief (DEPRECATED) get name of PCM start mode setting
|
||||
* \param mode PCM start mode
|
||||
* \return ascii name of PCM start mode setting
|
||||
*/
|
||||
|
|
@ -723,8 +723,10 @@ const char *snd_pcm_start_mode_name(snd_pcm_start_t mode)
|
|||
return snd_pcm_start_mode_names[snd_enum_to_int(mode)];
|
||||
}
|
||||
|
||||
link_warning(snd_pcm_start_mode_name, "Warning: start_mode is deprecated, consider to use start_threshold");
|
||||
|
||||
/**
|
||||
* \brief get name of PCM xrun mode setting
|
||||
* \brief (DEPRECATED) get name of PCM xrun mode setting
|
||||
* \param mode PCM xrun mode
|
||||
* \return ascii name of PCM xrun mode setting
|
||||
*/
|
||||
|
|
@ -734,6 +736,8 @@ const char *snd_pcm_xrun_mode_name(snd_pcm_xrun_t mode)
|
|||
return snd_pcm_xrun_mode_names[snd_enum_to_int(mode)];
|
||||
}
|
||||
|
||||
link_warning(snd_pcm_xrun_mode_name, "Warning: xrun_mode is deprecated, consider to use stop_threshold");
|
||||
|
||||
/**
|
||||
* \brief get name of PCM tstamp mode setting
|
||||
* \param mode PCM tstamp mode
|
||||
|
|
@ -793,16 +797,16 @@ int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, snd_output_t *out)
|
|||
assert(pcm);
|
||||
assert(out);
|
||||
assert(pcm->setup);
|
||||
snd_output_printf(out, "start_mode : %s\n", snd_pcm_start_mode_name(pcm->start_mode));
|
||||
snd_output_printf(out, "xrun_mode : %s\n", snd_pcm_xrun_mode_name(pcm->xrun_mode));
|
||||
snd_output_printf(out, "tstamp_mode : %s\n", snd_pcm_tstamp_mode_name(pcm->tstamp_mode));
|
||||
snd_output_printf(out, "period_step : %ld\n", (long)pcm->period_step);
|
||||
snd_output_printf(out, "sleep_min : %ld\n", (long)pcm->sleep_min);
|
||||
snd_output_printf(out, "avail_min : %ld\n", (long)pcm->avail_min);
|
||||
snd_output_printf(out, "xfer_align : %ld\n", (long)pcm->xfer_align);
|
||||
snd_output_printf(out, "silence_threshold: %ld\n", (long)pcm->silence_threshold);
|
||||
snd_output_printf(out, "silence_size : %ld\n", (long)pcm->silence_size);
|
||||
snd_output_printf(out, "boundary : %ld\n", (long)pcm->boundary);
|
||||
snd_output_printf(out, "period_step : %d\n", pcm->period_step);
|
||||
snd_output_printf(out, "sleep_min : %d\n", pcm->sleep_min);
|
||||
snd_output_printf(out, "avail_min : %ld\n", pcm->avail_min);
|
||||
snd_output_printf(out, "xfer_align : %ld\n", pcm->xfer_align);
|
||||
snd_output_printf(out, "start_threshold : %ld\n", pcm->start_threshold);
|
||||
snd_output_printf(out, "stop_threshold : %ld\n", pcm->stop_threshold);
|
||||
snd_output_printf(out, "silence_threshold: %ld\n", pcm->silence_threshold);
|
||||
snd_output_printf(out, "silence_size : %ld\n", pcm->silence_size);
|
||||
snd_output_printf(out, "boundary : %ld\n", pcm->boundary);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3287,13 +3291,13 @@ int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
|
|||
{
|
||||
assert(pcm && params);
|
||||
assert(pcm->setup);
|
||||
params->start_mode = snd_enum_to_int(pcm->start_mode);
|
||||
params->xrun_mode = snd_enum_to_int(pcm->xrun_mode);
|
||||
params->tstamp_mode = snd_enum_to_int(pcm->tstamp_mode);
|
||||
params->period_step = pcm->period_step;
|
||||
params->sleep_min = pcm->sleep_min;
|
||||
params->avail_min = pcm->avail_min;
|
||||
params->xfer_align = pcm->xfer_align;
|
||||
params->start_threshold = pcm->start_threshold;
|
||||
params->stop_threshold = pcm->stop_threshold;
|
||||
params->silence_threshold = pcm->silence_threshold;
|
||||
params->silence_size = pcm->silence_size;
|
||||
params->boundary = pcm->boundary;
|
||||
|
|
@ -3365,34 +3369,48 @@ void snd_pcm_sw_params_copy(snd_pcm_sw_params_t *dst, const snd_pcm_sw_params_t
|
|||
}
|
||||
|
||||
/**
|
||||
* \brief Set start mode inside a software configuration container
|
||||
* \brief (DEPRECATED) Set start mode inside a software configuration container
|
||||
* \param pcm PCM handle
|
||||
* \param params Software configuration container
|
||||
* \param val Start mode
|
||||
* \return 0 otherwise a negative error code
|
||||
*/
|
||||
int snd_pcm_sw_params_set_start_mode(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_start_t val)
|
||||
int snd_pcm_sw_params_set_start_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_start_t val)
|
||||
{
|
||||
assert(pcm && params);
|
||||
assert(val <= SND_PCM_START_LAST);
|
||||
params->start_mode = snd_enum_to_int(val);
|
||||
switch (val) {
|
||||
case SND_PCM_START_DATA:
|
||||
params->start_threshold = 1;
|
||||
break;
|
||||
case SND_PCM_START_EXPLICIT:
|
||||
params->start_threshold = pcm->boundary;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
link_warning(snd_pcm_sw_params_set_start_mode, "Warning: start_mode is deprecated, consider to use start_threshold");
|
||||
|
||||
/**
|
||||
* \brief Get start mode from a software configuration container
|
||||
* \brief (DEPRECATED) Get start mode from a software configuration container
|
||||
* \param params Software configuration container
|
||||
* \return start mode
|
||||
*/
|
||||
snd_pcm_start_t snd_pcm_sw_params_get_start_mode(const snd_pcm_sw_params_t *params)
|
||||
{
|
||||
assert(params);
|
||||
return snd_int_to_enum(params->start_mode);
|
||||
/* FIXME: Ugly */
|
||||
return params->start_threshold > 1024 * 1024 ? SND_PCM_START_EXPLICIT : SND_PCM_START_DATA;
|
||||
}
|
||||
|
||||
link_warning(snd_pcm_sw_params_get_start_mode, "Warning: start_mode is deprecated, consider to use start_threshold");
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set xrun mode inside a software configuration container
|
||||
* \brief (DEPRECATED) Set xrun mode inside a software configuration container
|
||||
* \param pcm PCM handle
|
||||
* \param params Software configuration container
|
||||
* \param val Xrun mode
|
||||
|
|
@ -3401,22 +3419,35 @@ snd_pcm_start_t snd_pcm_sw_params_get_start_mode(const snd_pcm_sw_params_t *para
|
|||
int snd_pcm_sw_params_set_xrun_mode(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_xrun_t val)
|
||||
{
|
||||
assert(pcm && params);
|
||||
assert(val <= SND_PCM_XRUN_LAST);
|
||||
params->xrun_mode = snd_enum_to_int(val);
|
||||
switch (val) {
|
||||
case SND_PCM_XRUN_STOP:
|
||||
params->stop_threshold = pcm->buffer_size;
|
||||
break;
|
||||
case SND_PCM_XRUN_NONE:
|
||||
params->stop_threshold = pcm->boundary;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
link_warning(snd_pcm_sw_params_set_xrun_mode, "Warning: xrun_mode is deprecated, consider to use stop_threshold");
|
||||
|
||||
/**
|
||||
* \brief Get xrun mode from a software configuration container
|
||||
* \brief (DEPRECATED) Get xrun mode from a software configuration container
|
||||
* \param params Software configuration container
|
||||
* \return xrun mode
|
||||
*/
|
||||
snd_pcm_xrun_t snd_pcm_sw_params_get_xrun_mode(const snd_pcm_sw_params_t *params)
|
||||
{
|
||||
assert(params);
|
||||
return snd_int_to_enum(params->xrun_mode);
|
||||
/* FIXME: Ugly */
|
||||
return params->stop_threshold > 1024 * 1024 ? SND_PCM_XRUN_NONE : SND_PCM_XRUN_STOP;
|
||||
}
|
||||
|
||||
link_warning(snd_pcm_sw_params_get_xrun_mode, "Warning: xrun_mode is deprecated, consider to use stop_threshold");
|
||||
|
||||
/**
|
||||
* \brief Set timestamp mode inside a software configuration container
|
||||
|
|
@ -3539,6 +3570,68 @@ snd_pcm_uframes_t snd_pcm_sw_params_get_xfer_align(const snd_pcm_sw_params_t *pa
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set start threshold inside a software configuration container
|
||||
* \param pcm PCM handle
|
||||
* \param params Software configuration container
|
||||
* \param val Start threshold in frames
|
||||
* \return 0 otherwise a negative error code
|
||||
*
|
||||
* PCM is automatically started when playback frames available to PCM
|
||||
* are >= threshold or when requested capture frames are >= threshold
|
||||
*/
|
||||
int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
|
||||
{
|
||||
assert(pcm && params);
|
||||
params->start_threshold = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get start threshold from a software configuration container
|
||||
* \param params Software configuration container
|
||||
* \return Start threshold in frames
|
||||
*
|
||||
* PCM is automatically started when playback frames available to PCM
|
||||
* are >= threshold or when requested capture frames are >= threshold
|
||||
*/
|
||||
snd_pcm_uframes_t snd_pcm_sw_params_get_start_threshold(const snd_pcm_sw_params_t *params)
|
||||
{
|
||||
assert(params);
|
||||
return params->start_threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set stop threshold inside a software configuration container
|
||||
* \param pcm PCM handle
|
||||
* \param params Software configuration container
|
||||
* \param val Stop threshold in frames
|
||||
* \return 0 otherwise a negative error code
|
||||
*
|
||||
* PCM is automatically stopped in #SND_PCM_STATE_XRUN state when available
|
||||
* frames is >= threshold
|
||||
*/
|
||||
int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
|
||||
{
|
||||
assert(pcm && params);
|
||||
params->stop_threshold = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get stop threshold from a software configuration container
|
||||
* \param params Software configuration container
|
||||
* \return Stop threshold in frames
|
||||
*
|
||||
* PCM is automatically stopped in #SND_PCM_STATE_XRUN state when available
|
||||
* frames is >= threshold
|
||||
*/
|
||||
snd_pcm_uframes_t snd_pcm_sw_params_get_stop_threshold(const snd_pcm_sw_params_t *params)
|
||||
{
|
||||
assert(params);
|
||||
return params->stop_threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set silence threshold inside a software configuration container
|
||||
* \param pcm PCM handle
|
||||
|
|
@ -4015,7 +4108,7 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
|
|||
|
||||
switch (snd_enum_to_int(state)) {
|
||||
case SND_PCM_STATE_PREPARED:
|
||||
if (pcm->start_mode == SND_PCM_START_DATA) {
|
||||
if (size >= pcm->start_threshold) {
|
||||
err = snd_pcm_start(pcm);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
|
|
@ -4156,11 +4249,14 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
|
|||
goto _end;
|
||||
}
|
||||
#endif
|
||||
if (state == SND_PCM_STATE_PREPARED &&
|
||||
pcm->start_mode == SND_PCM_START_DATA) {
|
||||
err = snd_pcm_start(pcm);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
if (state == SND_PCM_STATE_PREPARED) {
|
||||
snd_pcm_sframes_t hw_avail = pcm->buffer_size - avail;
|
||||
hw_avail += frames;
|
||||
if (hw_avail >= (snd_pcm_sframes_t) pcm->start_threshold) {
|
||||
err = snd_pcm_start(pcm);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
}
|
||||
_end:
|
||||
|
|
|
|||
|
|
@ -151,12 +151,12 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
|
|||
{
|
||||
snd_pcm_hw_t *hw = pcm->private_data;
|
||||
int fd = hw->fd;
|
||||
if ((snd_pcm_start_t) params->start_mode == pcm->start_mode &&
|
||||
(snd_pcm_xrun_t) params->xrun_mode == pcm->xrun_mode &&
|
||||
(snd_pcm_tstamp_t) params->tstamp_mode == pcm->tstamp_mode &&
|
||||
if ((snd_pcm_tstamp_t) params->tstamp_mode == pcm->tstamp_mode &&
|
||||
params->period_step == pcm->period_step &&
|
||||
params->sleep_min == pcm->sleep_min &&
|
||||
params->xfer_align == pcm->xfer_align &&
|
||||
params->start_threshold == pcm->start_threshold &&
|
||||
params->stop_threshold == pcm->stop_threshold &&
|
||||
params->silence_threshold == pcm->silence_threshold &&
|
||||
params->silence_size == pcm->silence_size) {
|
||||
hw->mmap_control->avail_min = params->avail_min;
|
||||
|
|
|
|||
|
|
@ -132,12 +132,12 @@ struct _snd_pcm {
|
|||
snd_pcm_uframes_t period_size;
|
||||
unsigned int period_time; /* period duration */
|
||||
unsigned int tick_time;
|
||||
snd_pcm_start_t start_mode; /* start mode */
|
||||
snd_pcm_xrun_t xrun_mode; /* xrun detection mode */
|
||||
snd_pcm_tstamp_t tstamp_mode; /* timestamp mode */
|
||||
unsigned int period_step;
|
||||
unsigned int sleep_min;
|
||||
snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
|
||||
snd_pcm_uframes_t start_threshold;
|
||||
snd_pcm_uframes_t stop_threshold;
|
||||
snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
|
||||
noise is nearest than this */
|
||||
snd_pcm_uframes_t silence_size; /* Silence filling size */
|
||||
|
|
|
|||
|
|
@ -117,7 +117,9 @@ static int snd_pcm_null_start(snd_pcm_t *pcm)
|
|||
assert(null->state == SND_PCM_STATE_PREPARED);
|
||||
null->state = SND_PCM_STATE_RUNNING;
|
||||
if (pcm->stream == SND_PCM_STREAM_CAPTURE)
|
||||
snd_pcm_mmap_appl_forward(pcm, pcm->buffer_size);
|
||||
*pcm->hw_ptr = *pcm->appl_ptr + pcm->buffer_size;
|
||||
else
|
||||
*pcm->hw_ptr = *pcm->appl_ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -153,10 +155,11 @@ static snd_pcm_sframes_t snd_pcm_null_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
|
|||
{
|
||||
snd_pcm_null_t *null = pcm->private_data;
|
||||
switch (snd_enum_to_int(null->state)) {
|
||||
case SND_PCM_STATE_PREPARED:
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
snd_pcm_mmap_appl_backward(pcm, frames);
|
||||
snd_pcm_mmap_hw_backward(pcm, frames);
|
||||
/* Fall through */
|
||||
case SND_PCM_STATE_PREPARED:
|
||||
snd_pcm_mmap_appl_backward(pcm, frames);
|
||||
return frames;
|
||||
default:
|
||||
return -EBADFD;
|
||||
|
|
@ -167,56 +170,45 @@ static snd_pcm_sframes_t snd_pcm_null_fwd(snd_pcm_t *pcm, snd_pcm_uframes_t size
|
|||
{
|
||||
snd_pcm_null_t *null = pcm->private_data;
|
||||
switch (snd_enum_to_int(null->state)) {
|
||||
case SND_PCM_STATE_PREPARED:
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
snd_pcm_mmap_appl_forward(pcm, size);
|
||||
snd_pcm_mmap_hw_forward(pcm, size);
|
||||
/* Fall through */
|
||||
case SND_PCM_STATE_PREPARED:
|
||||
snd_pcm_mmap_appl_forward(pcm, size);
|
||||
return size;
|
||||
default:
|
||||
return -EBADFD;
|
||||
}
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t snd_pcm_null_xfer_areas(snd_pcm_t *pcm,
|
||||
const snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_mmap_appl_forward(pcm, size);
|
||||
snd_pcm_mmap_hw_forward(pcm, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_null_writei(snd_pcm_t *pcm, const void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_null_t *null = pcm->private_data;
|
||||
if (null->state == SND_PCM_STATE_PREPARED &&
|
||||
pcm->start_mode != SND_PCM_START_EXPLICIT) {
|
||||
null->state = SND_PCM_STATE_RUNNING;
|
||||
}
|
||||
return snd_pcm_null_fwd(pcm, size);
|
||||
return snd_pcm_write_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_null_writen(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_null_t *null = pcm->private_data;
|
||||
if (null->state == SND_PCM_STATE_PREPARED &&
|
||||
pcm->start_mode != SND_PCM_START_EXPLICIT) {
|
||||
null->state = SND_PCM_STATE_RUNNING;
|
||||
}
|
||||
return snd_pcm_null_fwd(pcm, size);
|
||||
return snd_pcm_write_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_null_readi(snd_pcm_t *pcm, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_null_t *null = pcm->private_data;
|
||||
if (null->state == SND_PCM_STATE_PREPARED &&
|
||||
pcm->start_mode != SND_PCM_START_EXPLICIT) {
|
||||
null->state = SND_PCM_STATE_RUNNING;
|
||||
snd_pcm_mmap_hw_forward(pcm, pcm->buffer_size);
|
||||
}
|
||||
return snd_pcm_null_fwd(pcm, size);
|
||||
return snd_pcm_read_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUTE_UNUSED, snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_null_t *null = pcm->private_data;
|
||||
if (null->state == SND_PCM_STATE_PREPARED &&
|
||||
pcm->start_mode != SND_PCM_START_EXPLICIT) {
|
||||
null->state = SND_PCM_STATE_RUNNING;
|
||||
snd_pcm_mmap_hw_forward(pcm, pcm->buffer_size);
|
||||
}
|
||||
return snd_pcm_null_fwd(pcm, size);
|
||||
return snd_pcm_read_areas(pcm, NULL, 0, size, snd_pcm_null_xfer_areas);
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_null_mmap_commit(snd_pcm_t *pcm,
|
||||
|
|
|
|||
|
|
@ -2022,13 +2022,13 @@ static int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params
|
|||
{
|
||||
assert(pcm && params);
|
||||
assert(pcm->setup);
|
||||
params->start_mode = snd_enum_to_int(SND_PCM_START_DATA);
|
||||
params->xrun_mode = snd_enum_to_int(SND_PCM_XRUN_STOP);
|
||||
params->tstamp_mode = snd_enum_to_int(SND_PCM_TSTAMP_NONE);
|
||||
params->period_step = 1;
|
||||
params->sleep_min = 0;
|
||||
params->avail_min = pcm->period_size;
|
||||
params->xfer_align = pcm->period_size;
|
||||
params->start_threshold = 1;
|
||||
params->stop_threshold = pcm->buffer_size;
|
||||
params->silence_threshold = 0;
|
||||
params->silence_size = 0;
|
||||
params->boundary = pcm->buffer_size;
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *sla
|
|||
- draining silencing
|
||||
- return distance in frames to next event
|
||||
*/
|
||||
static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun)
|
||||
static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
|
|
@ -204,12 +204,12 @@ static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun)
|
|||
default:
|
||||
return INT_MAX;
|
||||
}
|
||||
if (slave_xrun && pcm->xrun_mode != SND_PCM_XRUN_NONE) {
|
||||
share->hw_ptr = slave->hw_ptr;
|
||||
avail = snd_pcm_mmap_avail(pcm);
|
||||
if (avail >= pcm->stop_threshold) {
|
||||
_snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
|
||||
goto update_poll;
|
||||
}
|
||||
share->hw_ptr = slave->hw_ptr;
|
||||
avail = snd_pcm_mmap_avail(pcm);
|
||||
hw_avail = buffer_size - avail;
|
||||
slave_avail = snd_pcm_share_slave_avail(slave);
|
||||
if (avail < slave_avail) {
|
||||
|
|
@ -247,18 +247,18 @@ static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun)
|
|||
}
|
||||
break;
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
if (pcm->xrun_mode != SND_PCM_XRUN_NONE) {
|
||||
if (hw_avail <= 0) {
|
||||
_snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
|
||||
break;
|
||||
}
|
||||
if ((snd_pcm_uframes_t)hw_avail < missing)
|
||||
missing = hw_avail;
|
||||
if (avail >= pcm->stop_threshold) {
|
||||
_snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
|
||||
break;
|
||||
} else {
|
||||
snd_pcm_uframes_t xrun_missing = pcm->stop_threshold - avail;
|
||||
if (missing > xrun_missing)
|
||||
missing = xrun_missing;
|
||||
}
|
||||
ready_missing = pcm->avail_min - avail;
|
||||
if (ready_missing > 0) {
|
||||
ready = 0;
|
||||
if ((snd_pcm_uframes_t)ready_missing < missing)
|
||||
if (missing > (snd_pcm_uframes_t)ready_missing)
|
||||
missing = ready_missing;
|
||||
}
|
||||
running = 1;
|
||||
|
|
@ -322,12 +322,11 @@ static snd_pcm_uframes_t _snd_pcm_share_slave_missing(snd_pcm_share_slave_t *sla
|
|||
snd_pcm_uframes_t missing = INT_MAX;
|
||||
struct list_head *i;
|
||||
snd_pcm_sframes_t avail = snd_pcm_avail_update(slave->pcm);
|
||||
int slave_xrun = (avail == -EPIPE);
|
||||
slave->hw_ptr = *slave->pcm->hw_ptr;
|
||||
list_for_each(i, &slave->clients) {
|
||||
snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
|
||||
snd_pcm_t *pcm = share->pcm;
|
||||
snd_pcm_uframes_t m = _snd_pcm_share_missing(pcm, slave_xrun);
|
||||
snd_pcm_uframes_t m = _snd_pcm_share_missing(pcm);
|
||||
if (m < missing)
|
||||
missing = m;
|
||||
}
|
||||
|
|
@ -396,7 +395,7 @@ static void _snd_pcm_share_update(snd_pcm_t *pcm)
|
|||
snd_pcm_uframes_t missing;
|
||||
snd_pcm_sframes_t avail = snd_pcm_avail_update(spcm);
|
||||
slave->hw_ptr = *slave->pcm->hw_ptr;
|
||||
missing = _snd_pcm_share_missing(pcm, avail == -EPIPE);
|
||||
missing = _snd_pcm_share_missing(pcm);
|
||||
if (!slave->polling) {
|
||||
pthread_cond_signal(&slave->poll_cond);
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue