mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-01 22:58:49 -04:00
Implemented snd_pcm_avail() function.
More documentation updates for snd_pcm_avail_update() and snd_pcm_delay(). Updated behaviour of read/write functions (wait when buffer is full) to follow kernel.
This commit is contained in:
parent
25e41cf1e8
commit
e859cf2644
11 changed files with 189 additions and 69 deletions
100
src/pcm/pcm.c
100
src/pcm/pcm.c
|
|
@ -359,9 +359,9 @@ network I/O etc.). If application wants to manage the ahead samples itself,
|
|||
the \link ::snd_pcm_rewind() \endlink function allows to forget the last
|
||||
samples in the stream.
|
||||
|
||||
\section pcm_status Obtaining device status
|
||||
\section pcm_status Obtaining stream status
|
||||
|
||||
The device status is stored in \link ::snd_pcm_status_t \endlink structure.
|
||||
The stream status is stored in \link ::snd_pcm_status_t \endlink structure.
|
||||
These parameters can be obtained: the current stream state -
|
||||
\link ::snd_pcm_status_get_state \endlink, timestamp of trigger -
|
||||
\link ::snd_pcm_status_get_trigger_tstamp \endlink, timestamp of last
|
||||
|
|
@ -373,21 +373,33 @@ samples - \link ::snd_pcm_status_get_overrange \endlink. The last two
|
|||
parameters - avail_max and overrange are reset to zero after the status
|
||||
call.
|
||||
|
||||
\subsection pcm_status_fast Obtaining device status fast
|
||||
\subsection pcm_status_fast Obtaining stream state fast and update r/w pointer
|
||||
|
||||
The function \link ::snd_pcm_avail_update \endlink updates the current
|
||||
available count of samples for writing (playback) or filled samples for
|
||||
reading (capture). It is a light version of
|
||||
\link ::snd_pcm_status_get_avail \endlink, because it does not require
|
||||
the user <-> kernel context switch, but the value is less accurate,
|
||||
because ring buffer pointers are updated in kernel drivers only when
|
||||
an interrupt occurs.
|
||||
reading (capture). This call is mandatory for updating actual r/w pointer.
|
||||
Using standalone, it is a light method to obtain current stream position,
|
||||
because it does not require the user <-> kernel context switch, but the value
|
||||
is less accurate, because ring buffer pointers are updated in kernel drivers
|
||||
only when an interrupt occurs. If you want to get accurate stream state,
|
||||
use functions \link ::snd_pcm_avail \endlink or \link ::snd_pcm_delay \endlink.
|
||||
Note that both of these functions do not update the current r/w pointer
|
||||
for applications, so the function \link ::snd_pcm_avail_update \endlink must
|
||||
be called afterwards before any read/write begin+commit operations.
|
||||
<p>
|
||||
The function \link ::snd_pcm_avail \endlink returns current available space
|
||||
in the ring buffer. Note that this function does not update the current r/w
|
||||
pointer for applications, so the function \link ::snd_pcm_avail_update \endlink
|
||||
must be called afterwards before any read/write/begin+commit operations.
|
||||
<p>
|
||||
The function \link ::snd_pcm_delay \endlink returns the delay in samples.
|
||||
For playback, it means count of samples in the ring buffer before
|
||||
the next sample will be sent to DAC. For capture, it means count of samples
|
||||
in the ring buffer before the next sample will be captured from ADC. It works
|
||||
only when the stream is in the running or draining state.
|
||||
only when the stream is in the running or draining (playback only) state.
|
||||
Note that this function does not update the current r/w pointer for applications,
|
||||
so the function \link ::snd_pcm_avail_update \endlink must be called afterwards
|
||||
before any read/write begin+commit operations.
|
||||
|
||||
\section pcm_action Managing the stream state
|
||||
|
||||
|
|
@ -811,6 +823,30 @@ snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm)
|
|||
return pcm->fast_ops->state(pcm->fast_op_arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Obtain available frames for a running PCM handle
|
||||
* \param pcm PCM handle
|
||||
* \param availp Returned available frames
|
||||
* \return 0 on success otherwise a negative error code
|
||||
*
|
||||
* Returns available frames to be filled inside ring buffer.
|
||||
* This value might be greater than buffer size when
|
||||
* underrun (playback) or overrun (capture) occurs.
|
||||
*
|
||||
* This function returns accurate value, because it updates
|
||||
* stream position from hardware.
|
||||
*
|
||||
* Note this function does not update the actual r/w pointer
|
||||
* for applications. The function \link ::snd_pcm_avail_update \endlink
|
||||
* have to be called before any read/write/begin+commit operation.
|
||||
*/
|
||||
int snd_pcm_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
assert(pcm);
|
||||
assert(pcm->setup);
|
||||
return pcm->fast_ops->avail(pcm->fast_op_arg, availp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Obtain delay for a running PCM handle
|
||||
* \param pcm PCM handle
|
||||
|
|
@ -822,6 +858,10 @@ snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm)
|
|||
* It's positive and less than buffer size in normal situation,
|
||||
* negative on playback underrun and greater than buffer size on
|
||||
* capture overrun.
|
||||
*
|
||||
* Note this function does not update the actual r/w pointer
|
||||
* for applications. The function \link ::snd_pcm_avail_update \endlink
|
||||
* have to be called before any read/write/begin+commit operation.
|
||||
*/
|
||||
int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
|
|
@ -5728,6 +5768,8 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
|
|||
break;
|
||||
case SND_PCM_STATE_XRUN:
|
||||
return -EPIPE;
|
||||
case SND_PCM_STATE_SUSPENDED:
|
||||
return -ESTRPIPE;
|
||||
default:
|
||||
return -EBADFD;
|
||||
}
|
||||
|
|
@ -5736,19 +5778,21 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
|
|||
snd_pcm_uframes_t frames;
|
||||
snd_pcm_sframes_t avail;
|
||||
_again:
|
||||
if (pcm->sleep_min == 0 && state == SND_PCM_STATE_RUNNING) {
|
||||
snd_pcm_sframes_t delay;
|
||||
/* update hw_ptr */
|
||||
err = snd_pcm_delay(pcm, &delay);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
}
|
||||
avail = snd_pcm_avail_update(pcm);
|
||||
if (avail < 0) {
|
||||
err = avail;
|
||||
goto _end;
|
||||
}
|
||||
if ((state == SND_PCM_STATE_PAUSED) ||
|
||||
(state == SND_PCM_STATE_DRAINING)) {
|
||||
if ((snd_pcm_uframes_t)avail < pcm->xfer_align) {
|
||||
err = -EPIPE;
|
||||
goto _end;
|
||||
}
|
||||
} else if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) ||
|
||||
if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) ||
|
||||
(size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) {
|
||||
|
||||
if (pcm->mode & SND_PCM_NONBLOCK) {
|
||||
err = -EAGAIN;
|
||||
goto _end;
|
||||
|
|
@ -5774,13 +5818,6 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
|
|||
offset += frames;
|
||||
size -= frames;
|
||||
xfer += frames;
|
||||
#if 0
|
||||
state = snd_pcm_state(pcm);
|
||||
if (state == SND_PCM_STATE_XRUN) {
|
||||
err = -EPIPE;
|
||||
goto _end;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
_end:
|
||||
return xfer > 0 ? (snd_pcm_sframes_t) xfer : err;
|
||||
|
|
@ -5805,6 +5842,8 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
|
|||
break;
|
||||
case SND_PCM_STATE_XRUN:
|
||||
return -EPIPE;
|
||||
case SND_PCM_STATE_SUSPENDED:
|
||||
return -ESTRPIPE;
|
||||
default:
|
||||
return -EBADFD;
|
||||
}
|
||||
|
|
@ -5824,15 +5863,9 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
|
|||
if (avail < 0) {
|
||||
err = avail;
|
||||
goto _end;
|
||||
}
|
||||
if (state == SND_PCM_STATE_PAUSED ||
|
||||
state == SND_PCM_STATE_PREPARED) {
|
||||
if ((snd_pcm_uframes_t)avail < pcm->xfer_align) {
|
||||
err = -EPIPE;
|
||||
goto _end;
|
||||
}
|
||||
} else if (((snd_pcm_uframes_t)avail < pcm->avail_min && size > (snd_pcm_uframes_t)avail) ||
|
||||
(size >= pcm->xfer_align && (snd_pcm_uframes_t)avail < pcm->xfer_align)) {
|
||||
|
||||
if (pcm->mode & SND_PCM_NONBLOCK) {
|
||||
err = -EAGAIN;
|
||||
goto _end;
|
||||
|
|
@ -5858,13 +5891,6 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
|
|||
offset += frames;
|
||||
size -= frames;
|
||||
xfer += frames;
|
||||
#if 0
|
||||
state = snd_pcm_state(pcm);
|
||||
if (state == SND_PCM_STATE_XRUN) {
|
||||
err = -EPIPE;
|
||||
goto _end;
|
||||
}
|
||||
#endif
|
||||
if (state == SND_PCM_STATE_PREPARED) {
|
||||
snd_pcm_sframes_t hw_avail = pcm->buffer_size - avail;
|
||||
hw_avail += frames;
|
||||
|
|
|
|||
|
|
@ -162,6 +162,12 @@ static snd_pcm_state_t snd_pcm_file_state(snd_pcm_t *pcm)
|
|||
return snd_pcm_state(file->slave);
|
||||
}
|
||||
|
||||
static int snd_pcm_file_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_file_t *file = pcm->private_data;
|
||||
return snd_pcm_avail(file->slave, availp);
|
||||
}
|
||||
|
||||
static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_file_t *file = pcm->private_data;
|
||||
|
|
@ -406,6 +412,7 @@ static snd_pcm_ops_t snd_pcm_file_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
||||
status: snd_pcm_file_status,
|
||||
state: snd_pcm_file_state,
|
||||
avail: snd_pcm_file_avail,
|
||||
delay: snd_pcm_file_delay,
|
||||
prepare: snd_pcm_file_prepare,
|
||||
reset: snd_pcm_file_reset,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,12 @@ static snd_pcm_state_t snd_pcm_hooks_state(snd_pcm_t *pcm)
|
|||
return snd_pcm_state(h->slave);
|
||||
}
|
||||
|
||||
static int snd_pcm_hooks_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_hooks_t *h = pcm->private_data;
|
||||
return snd_pcm_avail(h->slave, availp);
|
||||
}
|
||||
|
||||
static int snd_pcm_hooks_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_hooks_t *h = pcm->private_data;
|
||||
|
|
@ -292,6 +298,7 @@ static snd_pcm_ops_t snd_pcm_hooks_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
|
||||
status: snd_pcm_hooks_status,
|
||||
state: snd_pcm_hooks_state,
|
||||
avail: snd_pcm_hooks_avail,
|
||||
delay: snd_pcm_hooks_delay,
|
||||
prepare: snd_pcm_hooks_prepare,
|
||||
reset: snd_pcm_hooks_reset,
|
||||
|
|
|
|||
|
|
@ -77,9 +77,11 @@ struct sndrv_pcm_hw_params_old {
|
|||
#define SND_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old)
|
||||
#define SND_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old)
|
||||
|
||||
#define SND_PCM_IOCTL_XRUN _IO('A', 0x48)
|
||||
#define SND_PCM_IOCTL_AVAIL _IOR('A', 0x22, sndrv_pcm_uframes_t)
|
||||
#define SND_PCM_IOCTL_XRUN _IO ('A', 0x48)
|
||||
|
||||
static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params);
|
||||
static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm);
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -101,7 +103,7 @@ typedef struct {
|
|||
|
||||
#define SNDRV_FILE_PCM_STREAM_PLAYBACK "/dev/snd/pcmC%iD%ip"
|
||||
#define SNDRV_FILE_PCM_STREAM_CAPTURE "/dev/snd/pcmC%iD%ic"
|
||||
#define SNDRV_PCM_VERSION_MAX SNDRV_PROTOCOL_VERSION(2, 0, 2)
|
||||
#define SNDRV_PCM_VERSION_MAX SNDRV_PROTOCOL_VERSION(2, 0, 3)
|
||||
|
||||
/* update appl_ptr with driver */
|
||||
#define UPDATE_SHADOW_PTR(hw) \
|
||||
|
|
@ -393,6 +395,33 @@ static int snd_pcm_hw_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_hw_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_hw_t *hw = pcm->private_data;
|
||||
int fd = hw->fd;
|
||||
if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) {
|
||||
if (ioctl(fd, SND_PCM_IOCTL_AVAIL, availp) < 0) {
|
||||
// SYSERR("SND_PCM_IOCTL_AVAIL failed");
|
||||
return -errno;
|
||||
}
|
||||
} else {
|
||||
snd_pcm_sframes_t delay;
|
||||
int err = snd_pcm_hw_delay(pcm, &delay);
|
||||
if (err < 0) {
|
||||
delay = snd_pcm_hw_avail_update(pcm);
|
||||
if (delay < 0)
|
||||
return delay;
|
||||
*availp = delay;
|
||||
} else {
|
||||
delay = pcm->stream == SND_PCM_STREAM_PLAYBACK ? pcm->buffer_size - delay : delay;
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
*availp = delay;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_hw_t *hw = pcm->private_data;
|
||||
|
|
@ -757,6 +786,7 @@ static snd_pcm_ops_t snd_pcm_hw_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
|
||||
status: snd_pcm_hw_status,
|
||||
state: snd_pcm_hw_state,
|
||||
avail: snd_pcm_hw_avail,
|
||||
delay: snd_pcm_hw_delay,
|
||||
prepare: snd_pcm_hw_prepare,
|
||||
reset: snd_pcm_hw_reset,
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ typedef struct {
|
|||
int (*drain)(snd_pcm_t *pcm);
|
||||
int (*pause)(snd_pcm_t *pcm, int enable);
|
||||
snd_pcm_state_t (*state)(snd_pcm_t *pcm);
|
||||
int (*avail)(snd_pcm_t *pcm, snd_pcm_uframes_t *availp);
|
||||
int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
||||
int (*resume)(snd_pcm_t *pcm);
|
||||
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||
|
|
@ -323,31 +324,12 @@ static inline snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm)
|
|||
|
||||
static inline snd_pcm_uframes_t snd_pcm_mmap_playback_delay(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_state_t state = snd_pcm_state(pcm);
|
||||
|
||||
switch (state) {
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
case SND_PCM_STATE_DRAINING:
|
||||
return snd_pcm_mmap_playback_hw_avail(pcm);
|
||||
case SND_PCM_STATE_XRUN:
|
||||
return -EPIPE;
|
||||
default:
|
||||
return -EBADFD;
|
||||
}
|
||||
}
|
||||
|
||||
static inline snd_pcm_uframes_t snd_pcm_mmap_capture_delay(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_state_t state = snd_pcm_state(pcm);
|
||||
|
||||
switch (state) {
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
return snd_pcm_mmap_capture_hw_avail(pcm);
|
||||
case SND_PCM_STATE_XRUN:
|
||||
return -EPIPE;
|
||||
default:
|
||||
return -EBADFD;
|
||||
}
|
||||
}
|
||||
|
||||
static inline snd_pcm_sframes_t snd_pcm_mmap_delay(snd_pcm_t *pcm)
|
||||
|
|
|
|||
|
|
@ -319,6 +319,12 @@ static snd_pcm_state_t snd_pcm_meter_state(snd_pcm_t *pcm)
|
|||
return snd_pcm_state(meter->slave);
|
||||
}
|
||||
|
||||
static int snd_pcm_meter_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_meter_t *meter = pcm->private_data;
|
||||
return snd_pcm_avail(meter->slave, availp);
|
||||
}
|
||||
|
||||
static int snd_pcm_meter_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_meter_t *meter = pcm->private_data;
|
||||
|
|
@ -593,6 +599,7 @@ static snd_pcm_ops_t snd_pcm_meter_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
|
||||
status: snd_pcm_meter_status,
|
||||
state: snd_pcm_meter_state,
|
||||
avail: snd_pcm_meter_avail,
|
||||
delay: snd_pcm_meter_delay,
|
||||
prepare: snd_pcm_meter_prepare,
|
||||
reset: snd_pcm_meter_reset,
|
||||
|
|
|
|||
|
|
@ -351,6 +351,13 @@ static snd_pcm_state_t snd_pcm_multi_state(snd_pcm_t *pcm)
|
|||
return snd_pcm_state(slave);
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
snd_pcm_t *slave = multi->slaves[0].pcm;
|
||||
return snd_pcm_avail(slave, availp);
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
|
|
@ -594,6 +601,7 @@ static snd_pcm_ops_t snd_pcm_multi_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
|
||||
status: snd_pcm_multi_status,
|
||||
state: snd_pcm_multi_state,
|
||||
avail: snd_pcm_multi_avail,
|
||||
delay: snd_pcm_multi_delay,
|
||||
prepare: snd_pcm_multi_prepare,
|
||||
reset: snd_pcm_multi_reset,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,12 @@ static snd_pcm_state_t snd_pcm_null_state(snd_pcm_t *pcm)
|
|||
return null->state;
|
||||
}
|
||||
|
||||
static int snd_pcm_null_avail(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
*availp = pcm->buffer_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
*delayp = 0;
|
||||
|
|
@ -320,6 +326,7 @@ static snd_pcm_ops_t snd_pcm_null_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
|
||||
status: snd_pcm_null_status,
|
||||
state: snd_pcm_null_state,
|
||||
avail: snd_pcm_null_avail,
|
||||
delay: snd_pcm_null_delay,
|
||||
prepare: snd_pcm_null_prepare,
|
||||
reset: snd_pcm_null_reset,
|
||||
|
|
|
|||
|
|
@ -188,6 +188,19 @@ snd_pcm_state_t snd_pcm_plugin_state(snd_pcm_t *pcm)
|
|||
return snd_pcm_state(plugin->slave);
|
||||
}
|
||||
|
||||
int snd_pcm_plugin_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
snd_pcm_uframes_t sd;
|
||||
int err = snd_pcm_avail(plugin->slave, &sd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (plugin->client_frames)
|
||||
sd = plugin->client_frames(pcm, sd);
|
||||
*availp = sd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
|
|
@ -197,7 +210,7 @@ int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
|||
return err;
|
||||
if (plugin->client_frames)
|
||||
sd = plugin->client_frames(pcm, sd);
|
||||
*delayp = sd + snd_pcm_mmap_delay(pcm);
|
||||
*delayp = sd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -627,6 +640,7 @@ int snd_pcm_plugin_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|||
snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
|
||||
status: snd_pcm_plugin_status,
|
||||
state: snd_pcm_plugin_state,
|
||||
avail: snd_pcm_plugin_avail,
|
||||
delay: snd_pcm_plugin_delay,
|
||||
prepare: snd_pcm_plugin_prepare,
|
||||
reset: snd_pcm_plugin_reset,
|
||||
|
|
|
|||
|
|
@ -713,12 +713,34 @@ static snd_pcm_state_t snd_pcm_share_state(snd_pcm_t *pcm)
|
|||
return share->state;
|
||||
}
|
||||
|
||||
static int _snd_pcm_share_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
switch (share->state) {
|
||||
case SND_PCM_STATE_XRUN:
|
||||
return -EPIPE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return snd_pcm_avail(slave->pcm, availp);
|
||||
}
|
||||
|
||||
static int snd_pcm_share_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
int err;
|
||||
Pthread_mutex_lock(&slave->mutex);
|
||||
err = _snd_pcm_share_avail(pcm, availp);
|
||||
Pthread_mutex_unlock(&slave->mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
int err = 0;
|
||||
snd_pcm_sframes_t sd;
|
||||
switch (share->state) {
|
||||
case SND_PCM_STATE_XRUN:
|
||||
return -EPIPE;
|
||||
|
|
@ -731,11 +753,7 @@ static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
|||
default:
|
||||
return -EBADFD;
|
||||
}
|
||||
err = snd_pcm_delay(slave->pcm, &sd);
|
||||
if (err < 0)
|
||||
return err;
|
||||
*delayp = sd + snd_pcm_mmap_delay(pcm);
|
||||
return 0;
|
||||
return snd_pcm_delay(slave->pcm, delayp);
|
||||
}
|
||||
|
||||
static int snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
|
|
@ -1215,6 +1233,7 @@ static snd_pcm_ops_t snd_pcm_share_ops = {
|
|||
static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
|
||||
status: snd_pcm_share_status,
|
||||
state: snd_pcm_share_state,
|
||||
avail: snd_pcm_share_avail,
|
||||
delay: snd_pcm_share_delay,
|
||||
prepare: snd_pcm_share_prepare,
|
||||
reset: snd_pcm_share_reset,
|
||||
|
|
|
|||
|
|
@ -443,6 +443,19 @@ static snd_pcm_state_t snd_pcm_shm_state(snd_pcm_t *pcm)
|
|||
return snd_pcm_shm_action(pcm);
|
||||
}
|
||||
|
||||
static int snd_pcm_shm_avail(snd_pcm_t *pcm, snd_pcm_uframes_t *availp)
|
||||
{
|
||||
snd_pcm_shm_t *shm = pcm->private_data;
|
||||
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
||||
int err;
|
||||
ctrl->cmd = SND_PCM_IOCTL_AVAIL;
|
||||
err = snd_pcm_shm_action(pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
*availp = ctrl->u.avail.frames;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||
{
|
||||
snd_pcm_shm_t *shm = pcm->private_data;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue