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
/** 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 */
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);
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;
}
/**
- * \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
*/
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
*/
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
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;
}
{
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;
}
/**
- * \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
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
}
+/**
+ * \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
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;
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:
{
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;
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 */
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;
}
{
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;
{
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,
{
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;
- 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;
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) {
}
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;
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;
}
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;