mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-12-16 08:56:42 -05:00
Added snd_pcm_hwptr() and enhanced snd_pcm_mmap_begin() for no xrun mode.
This commit is contained in:
parent
a91efc0fe6
commit
fbd99fdec0
17 changed files with 231 additions and 13 deletions
|
|
@ -471,6 +471,9 @@ static int pcm_shm_cmd(client_t *client)
|
||||||
case SND_PCM_IOCTL_HWSYNC:
|
case SND_PCM_IOCTL_HWSYNC:
|
||||||
ctrl->result = snd_pcm_hwsync(pcm);
|
ctrl->result = snd_pcm_hwsync(pcm);
|
||||||
break;
|
break;
|
||||||
|
case SND_PCM_IOCTL_HWPTR:
|
||||||
|
ctrl->result = snd_pcm_hwptr(pcm, (snd_pcm_uframes_t *) &ctrl->u.hwptr.frames);
|
||||||
|
break;
|
||||||
case SNDRV_PCM_IOCTL_DELAY:
|
case SNDRV_PCM_IOCTL_DELAY:
|
||||||
ctrl->result = snd_pcm_delay(pcm, (snd_pcm_sframes_t *) &ctrl->u.delay.frames);
|
ctrl->result = snd_pcm_delay(pcm, (snd_pcm_sframes_t *) &ctrl->u.delay.frames);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ typedef enum _snd_transport_type {
|
||||||
#define SND_PCM_IOCTL_POLL_DESCRIPTOR _IO ('A', 0xf8)
|
#define SND_PCM_IOCTL_POLL_DESCRIPTOR _IO ('A', 0xf8)
|
||||||
#define SND_PCM_IOCTL_HW_PTR_FD _IO ('A', 0xf9)
|
#define SND_PCM_IOCTL_HW_PTR_FD _IO ('A', 0xf9)
|
||||||
#define SND_PCM_IOCTL_APPL_PTR_FD _IO ('A', 0xfa)
|
#define SND_PCM_IOCTL_APPL_PTR_FD _IO ('A', 0xfa)
|
||||||
|
#define SND_PCM_IOCTL_HWPTR _IO ('A', 0xfb)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
snd_pcm_uframes_t ptr;
|
snd_pcm_uframes_t ptr;
|
||||||
|
|
@ -73,6 +74,9 @@ typedef struct {
|
||||||
snd_pcm_hw_params_t hw_params;
|
snd_pcm_hw_params_t hw_params;
|
||||||
snd_pcm_sw_params_t sw_params;
|
snd_pcm_sw_params_t sw_params;
|
||||||
snd_pcm_status_t status;
|
snd_pcm_status_t status;
|
||||||
|
struct {
|
||||||
|
snd_pcm_uframes_t frames;
|
||||||
|
} hwptr;
|
||||||
struct {
|
struct {
|
||||||
snd_pcm_uframes_t frames;
|
snd_pcm_uframes_t frames;
|
||||||
} avail;
|
} avail;
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@ int snd_pcm_drain(snd_pcm_t *pcm);
|
||||||
int snd_pcm_pause(snd_pcm_t *pcm, int enable);
|
int snd_pcm_pause(snd_pcm_t *pcm, int enable);
|
||||||
snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm);
|
snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm);
|
||||||
int snd_pcm_hwsync(snd_pcm_t *pcm);
|
int snd_pcm_hwsync(snd_pcm_t *pcm);
|
||||||
|
int snd_pcm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *uframes);
|
||||||
int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
||||||
int snd_pcm_resume(snd_pcm_t *pcm);
|
int snd_pcm_resume(snd_pcm_t *pcm);
|
||||||
snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm);
|
snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm);
|
||||||
|
|
|
||||||
10
src/Versions
10
src/Versions
|
|
@ -6,6 +6,7 @@ ALSA_0.9 {
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
||||||
ALSA_0.9.0rc4 {
|
ALSA_0.9.0rc4 {
|
||||||
global:
|
global:
|
||||||
|
|
||||||
|
|
@ -77,4 +78,11 @@ ALSA_0.9.0rc4 {
|
||||||
snd_pcm_hw_params_set_tick_time_first;
|
snd_pcm_hw_params_set_tick_time_first;
|
||||||
snd_pcm_hw_params_set_tick_time_last;
|
snd_pcm_hw_params_set_tick_time_last;
|
||||||
|
|
||||||
}ALSA_0.9;
|
} ALSA_0.9;
|
||||||
|
|
||||||
|
ALSA_0.9.0rc8 {
|
||||||
|
global:
|
||||||
|
|
||||||
|
snd_pcm_hwptr;
|
||||||
|
|
||||||
|
} ALSA_0.9.0rc4;
|
||||||
|
|
|
||||||
|
|
@ -868,6 +868,30 @@ int snd_pcm_hwsync(snd_pcm_t *pcm)
|
||||||
return pcm->fast_ops->hwsync(pcm->fast_op_arg);
|
return pcm->fast_ops->hwsync(pcm->fast_op_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return hardware pointer
|
||||||
|
* \param pcm PCM handle
|
||||||
|
* \return 0 on success otherwise a negative error code
|
||||||
|
*
|
||||||
|
* The hardware pointer is in range 0 ... (boundary - 1). It contains
|
||||||
|
* count_of_ring_buffer_crosses * buffer_size + offset in the ring buffer.
|
||||||
|
*
|
||||||
|
* Note this function does not return the real hardware pointer.
|
||||||
|
* The function \link ::snd_pcm_hwsync \endlink have to be called
|
||||||
|
* before to obtain the real hardware position.
|
||||||
|
*/
|
||||||
|
#ifndef DOXYGEN
|
||||||
|
int INTERNAL(snd_pcm_hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
#else
|
||||||
|
int snd_pcm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
assert(pcm);
|
||||||
|
assert(pcm->setup);
|
||||||
|
return pcm->fast_ops->hwptr(pcm->fast_op_arg, hwptr);
|
||||||
|
}
|
||||||
|
default_symbol_version(__snd_pcm_hwptr, snd_pcm_hwptr, ALSA_0.9.0rc8);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Obtain delay for a running PCM handle
|
* \brief Obtain delay for a running PCM handle
|
||||||
* \param pcm PCM handle
|
* \param pcm PCM handle
|
||||||
|
|
@ -5792,7 +5816,7 @@ void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val)
|
||||||
* \brief Application request to access a portion of direct (mmap) area
|
* \brief Application request to access a portion of direct (mmap) area
|
||||||
* \param pcm PCM handle
|
* \param pcm PCM handle
|
||||||
* \param areas Returned mmap channel areas
|
* \param areas Returned mmap channel areas
|
||||||
* \param offset Returned mmap area offset in area steps (== frames)
|
* \param offset mmap area offset in area steps (== frames) (wanted on entry (see note), returned on exit)
|
||||||
* \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit)
|
* \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit)
|
||||||
* \return 0 on success otherwise a negative error code
|
* \return 0 on success otherwise a negative error code
|
||||||
*
|
*
|
||||||
|
|
@ -5805,6 +5829,9 @@ void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val)
|
||||||
*
|
*
|
||||||
* See the snd_pcm_mmap_commit() function to finish the frame processing in
|
* See the snd_pcm_mmap_commit() function to finish the frame processing in
|
||||||
* the direct areas.
|
* the direct areas.
|
||||||
|
*
|
||||||
|
* Note: The offset value is always overriden when stop_threshold < boundary.
|
||||||
|
* Otherwise, the application must specify it's own offset value.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int snd_pcm_mmap_begin(snd_pcm_t *pcm,
|
int snd_pcm_mmap_begin(snd_pcm_t *pcm,
|
||||||
|
|
@ -5817,12 +5844,18 @@ int snd_pcm_mmap_begin(snd_pcm_t *pcm,
|
||||||
snd_pcm_uframes_t avail;
|
snd_pcm_uframes_t avail;
|
||||||
assert(pcm && areas && offset && frames);
|
assert(pcm && areas && offset && frames);
|
||||||
*areas = snd_pcm_mmap_areas(pcm);
|
*areas = snd_pcm_mmap_areas(pcm);
|
||||||
*offset = *pcm->appl.ptr % pcm->buffer_size;
|
if (pcm->stop_threshold < pcm->boundary) {
|
||||||
|
*offset = *pcm->appl.ptr % pcm->buffer_size;
|
||||||
|
avail = snd_pcm_mmap_avail(pcm);
|
||||||
|
if (avail > pcm->buffer_size)
|
||||||
|
avail = pcm->buffer_size;
|
||||||
|
} else {
|
||||||
|
if (*offset >= pcm->buffer_size)
|
||||||
|
return -EINVAL;
|
||||||
|
avail = pcm->buffer_size;
|
||||||
|
}
|
||||||
cont = pcm->buffer_size - *offset;
|
cont = pcm->buffer_size - *offset;
|
||||||
f = *frames;
|
f = *frames;
|
||||||
avail = snd_pcm_mmap_avail(pcm);
|
|
||||||
if (avail > pcm->buffer_size)
|
|
||||||
avail = pcm->buffer_size;
|
|
||||||
if (f > avail)
|
if (f > avail)
|
||||||
f = avail;
|
f = avail;
|
||||||
if (f > cont)
|
if (f > cont)
|
||||||
|
|
|
||||||
|
|
@ -954,7 +954,6 @@ static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
snd_pcm_dmix_t *dmix = pcm->private_data;
|
snd_pcm_dmix_t *dmix = pcm->private_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
assert(pcm && delayp);
|
|
||||||
switch(dmix->state) {
|
switch(dmix->state) {
|
||||||
case SNDRV_PCM_STATE_DRAINING:
|
case SNDRV_PCM_STATE_DRAINING:
|
||||||
case SNDRV_PCM_STATE_RUNNING:
|
case SNDRV_PCM_STATE_RUNNING:
|
||||||
|
|
@ -990,6 +989,25 @@ static int snd_pcm_dmix_hwsync(snd_pcm_t *pcm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_dmix_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_dmix_t *dmix = pcm->private_data;
|
||||||
|
|
||||||
|
switch(dmix->state) {
|
||||||
|
case SNDRV_PCM_STATE_DRAINING:
|
||||||
|
case SNDRV_PCM_STATE_RUNNING:
|
||||||
|
case SNDRV_PCM_STATE_PREPARED:
|
||||||
|
case SNDRV_PCM_STATE_PAUSED:
|
||||||
|
case SNDRV_PCM_STATE_SUSPENDED:
|
||||||
|
*hwptr = *pcm->hw.ptr;
|
||||||
|
return 0;
|
||||||
|
case SNDRV_PCM_STATE_XRUN:
|
||||||
|
return -EPIPE;
|
||||||
|
default:
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
|
static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_dmix_t *dmix = pcm->private_data;
|
snd_pcm_dmix_t *dmix = pcm->private_data;
|
||||||
|
|
@ -1206,6 +1224,7 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
|
||||||
status: snd_pcm_dmix_status,
|
status: snd_pcm_dmix_status,
|
||||||
state: snd_pcm_dmix_state,
|
state: snd_pcm_dmix_state,
|
||||||
hwsync: snd_pcm_dmix_hwsync,
|
hwsync: snd_pcm_dmix_hwsync,
|
||||||
|
hwptr: snd_pcm_dmix_hwptr,
|
||||||
delay: snd_pcm_dmix_delay,
|
delay: snd_pcm_dmix_delay,
|
||||||
prepare: snd_pcm_dmix_prepare,
|
prepare: snd_pcm_dmix_prepare,
|
||||||
reset: snd_pcm_dmix_reset,
|
reset: snd_pcm_dmix_reset,
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,12 @@ static int snd_pcm_file_hwsync(snd_pcm_t *pcm)
|
||||||
return snd_pcm_hwsync(file->slave);
|
return snd_pcm_hwsync(file->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_file_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_file_t *file = pcm->private_data;
|
||||||
|
return INTERNAL(snd_pcm_hwptr)(file->slave, hwptr);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_file_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
snd_pcm_file_t *file = pcm->private_data;
|
snd_pcm_file_t *file = pcm->private_data;
|
||||||
|
|
@ -366,6 +372,9 @@ static int snd_pcm_file_hw_free(snd_pcm_t *pcm)
|
||||||
static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
|
static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
|
||||||
{
|
{
|
||||||
snd_pcm_file_t *file = pcm->private_data;
|
snd_pcm_file_t *file = pcm->private_data;
|
||||||
|
/* we don't support mode without xrun detection */
|
||||||
|
if (params->stop_threshold >= params->boundary)
|
||||||
|
return -EINVAL;
|
||||||
return snd_pcm_sw_params(file->slave, params);
|
return snd_pcm_sw_params(file->slave, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -413,6 +422,7 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
||||||
status: snd_pcm_file_status,
|
status: snd_pcm_file_status,
|
||||||
state: snd_pcm_file_state,
|
state: snd_pcm_file_state,
|
||||||
hwsync: snd_pcm_file_hwsync,
|
hwsync: snd_pcm_file_hwsync,
|
||||||
|
hwptr: snd_pcm_file_hwptr,
|
||||||
delay: snd_pcm_file_delay,
|
delay: snd_pcm_file_delay,
|
||||||
prepare: snd_pcm_file_prepare,
|
prepare: snd_pcm_file_prepare,
|
||||||
reset: snd_pcm_file_reset,
|
reset: snd_pcm_file_reset,
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,12 @@ static int snd_pcm_hooks_hwsync(snd_pcm_t *pcm)
|
||||||
return snd_pcm_hwsync(h->slave);
|
return snd_pcm_hwsync(h->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_hooks_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_hooks_t *h = pcm->private_data;
|
||||||
|
return INTERNAL(snd_pcm_hwptr)(h->slave, hwptr);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_hooks_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_hooks_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
snd_pcm_hooks_t *h = pcm->private_data;
|
snd_pcm_hooks_t *h = pcm->private_data;
|
||||||
|
|
@ -299,6 +305,7 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
|
||||||
status: snd_pcm_hooks_status,
|
status: snd_pcm_hooks_status,
|
||||||
state: snd_pcm_hooks_state,
|
state: snd_pcm_hooks_state,
|
||||||
hwsync: snd_pcm_hooks_hwsync,
|
hwsync: snd_pcm_hooks_hwsync,
|
||||||
|
hwptr: snd_pcm_hooks_hwptr,
|
||||||
delay: snd_pcm_hooks_delay,
|
delay: snd_pcm_hooks_delay,
|
||||||
prepare: snd_pcm_hooks_prepare,
|
prepare: snd_pcm_hooks_prepare,
|
||||||
reset: snd_pcm_hooks_reset,
|
reset: snd_pcm_hooks_reset,
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,9 @@ static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
|
||||||
hw->mmap_control->avail_min = params->avail_min;
|
hw->mmap_control->avail_min = params->avail_min;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* FIXME */
|
||||||
|
if (hw->mmap_shm && params->stop_threshold >= params->boundary)
|
||||||
|
return -EINVAL;
|
||||||
if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
|
if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
|
||||||
SYSERR("SNDRV_PCM_IOCTL_SW_PARAMS failed");
|
SYSERR("SNDRV_PCM_IOCTL_SW_PARAMS failed");
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
@ -428,6 +431,23 @@ static int snd_pcm_hw_hwsync(snd_pcm_t *pcm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_hw_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
switch (snd_pcm_state(pcm)) {
|
||||||
|
case SND_PCM_STATE_RUNNING:
|
||||||
|
case SND_PCM_STATE_DRAINING:
|
||||||
|
case SND_PCM_STATE_PREPARED:
|
||||||
|
case SND_PCM_STATE_PAUSED:
|
||||||
|
case SND_PCM_STATE_SUSPENDED:
|
||||||
|
*hwptr = *pcm->hw.ptr;
|
||||||
|
return 0;
|
||||||
|
case SND_PCM_STATE_XRUN:
|
||||||
|
return -EPIPE;
|
||||||
|
default:
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
|
static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
snd_pcm_hw_t *hw = pcm->private_data;
|
||||||
|
|
@ -690,7 +710,7 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm)
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
|
static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
|
||||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
snd_pcm_uframes_t offset,
|
||||||
snd_pcm_uframes_t size)
|
snd_pcm_uframes_t size)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
snd_pcm_hw_t *hw = pcm->private_data;
|
||||||
|
|
@ -698,6 +718,12 @@ static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
|
||||||
if (hw->mmap_shm) {
|
if (hw->mmap_shm) {
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
snd_pcm_sframes_t result = 0, res;
|
snd_pcm_sframes_t result = 0, res;
|
||||||
|
snd_pcm_uframes_t last_offset;
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
last_offset = *pcm->appl.ptr - offset;
|
||||||
|
if (last_offset != offset)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
res = snd_pcm_write_mmap(pcm, size);
|
res = snd_pcm_write_mmap(pcm, size);
|
||||||
|
|
@ -793,6 +819,7 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
|
||||||
status: snd_pcm_hw_status,
|
status: snd_pcm_hw_status,
|
||||||
state: snd_pcm_hw_state,
|
state: snd_pcm_hw_state,
|
||||||
hwsync: snd_pcm_hw_hwsync,
|
hwsync: snd_pcm_hw_hwsync,
|
||||||
|
hwptr: snd_pcm_hw_hwptr,
|
||||||
delay: snd_pcm_hw_delay,
|
delay: snd_pcm_hw_delay,
|
||||||
prepare: snd_pcm_hw_prepare,
|
prepare: snd_pcm_hw_prepare,
|
||||||
reset: snd_pcm_hw_reset,
|
reset: snd_pcm_hw_reset,
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,24 @@ static int snd_pcm_jack_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_jack_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
#ifdef PCM_JACK_DEBUG
|
||||||
|
printf("snd_pcm_jack_hwptr\n"); fflush(stdout);
|
||||||
|
#endif
|
||||||
|
switch (snd_pcm_state(pcm)) {
|
||||||
|
case SND_PCM_STATE_RUNNING:
|
||||||
|
case SND_PCM_STATE_DRAINING:
|
||||||
|
case SND_PCM_STATE_PREPARED:
|
||||||
|
case SND_PCM_STATE_PAUSED:
|
||||||
|
case SND_PCM_STATE_SUSPENDED:
|
||||||
|
*hwptr = *pcm->hw.ptr;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_jack_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_jack_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
#ifdef PCM_JACK_DEBUG
|
#ifdef PCM_JACK_DEBUG
|
||||||
|
|
@ -593,6 +611,7 @@ static snd_pcm_fast_ops_t snd_pcm_jack_fast_ops = {
|
||||||
status: snd_pcm_jack_status,
|
status: snd_pcm_jack_status,
|
||||||
state: snd_pcm_jack_state,
|
state: snd_pcm_jack_state,
|
||||||
hwsync: snd_pcm_jack_hwsync,
|
hwsync: snd_pcm_jack_hwsync,
|
||||||
|
hwptr: snd_pcm_jack_hwptr,
|
||||||
delay: snd_pcm_jack_delay,
|
delay: snd_pcm_jack_delay,
|
||||||
prepare: snd_pcm_jack_prepare,
|
prepare: snd_pcm_jack_prepare,
|
||||||
reset: snd_pcm_jack_reset,
|
reset: snd_pcm_jack_reset,
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ typedef struct {
|
||||||
int (*pause)(snd_pcm_t *pcm, int enable);
|
int (*pause)(snd_pcm_t *pcm, int enable);
|
||||||
snd_pcm_state_t (*state)(snd_pcm_t *pcm);
|
snd_pcm_state_t (*state)(snd_pcm_t *pcm);
|
||||||
int (*hwsync)(snd_pcm_t *pcm);
|
int (*hwsync)(snd_pcm_t *pcm);
|
||||||
|
int (*hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr);
|
||||||
int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
||||||
int (*resume)(snd_pcm_t *pcm);
|
int (*resume)(snd_pcm_t *pcm);
|
||||||
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||||
|
|
@ -549,6 +550,8 @@ int snd_pcm_hw_param_get_max(const snd_pcm_hw_params_t *params,
|
||||||
unsigned int *val, int *dir);
|
unsigned int *val, int *dir);
|
||||||
|
|
||||||
#ifdef INTERNAL
|
#ifdef INTERNAL
|
||||||
|
int INTERNAL(snd_pcm_hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr);
|
||||||
|
|
||||||
int INTERNAL(snd_pcm_hw_params_get_access)(const snd_pcm_hw_params_t *params, snd_pcm_access_t *access);
|
int INTERNAL(snd_pcm_hw_params_get_access)(const snd_pcm_hw_params_t *params, snd_pcm_access_t *access);
|
||||||
int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
|
int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
|
||||||
int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
|
int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,12 @@ static int snd_pcm_meter_hwsync(snd_pcm_t *pcm)
|
||||||
return snd_pcm_hwsync(meter->slave);
|
return snd_pcm_hwsync(meter->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_meter_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_meter_t *meter = pcm->private_data;
|
||||||
|
return INTERNAL(snd_pcm_hwptr)(meter->slave, hwptr);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_meter_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_meter_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
snd_pcm_meter_t *meter = pcm->private_data;
|
snd_pcm_meter_t *meter = pcm->private_data;
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock
|
||||||
static int snd_pcm_multi_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
static int snd_pcm_multi_async(snd_pcm_t *pcm, int sig, pid_t pid)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
snd_pcm_t *slave_0 = multi->slaves[0].pcm;
|
snd_pcm_t *slave_0 = multi->slaves[multi->master_slave].pcm;
|
||||||
return snd_pcm_async(slave_0, sig, pid);
|
return snd_pcm_async(slave_0, sig, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,28 +340,35 @@ static int snd_pcm_multi_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
|
||||||
static int snd_pcm_multi_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
|
static int snd_pcm_multi_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
snd_pcm_t *slave = multi->slaves[0].pcm;
|
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
||||||
return snd_pcm_status(slave, status);
|
return snd_pcm_status(slave, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_state_t snd_pcm_multi_state(snd_pcm_t *pcm)
|
static snd_pcm_state_t snd_pcm_multi_state(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
snd_pcm_t *slave = multi->slaves[0].pcm;
|
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
||||||
return snd_pcm_state(slave);
|
return snd_pcm_state(slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_hwsync(snd_pcm_t *pcm)
|
static int snd_pcm_multi_hwsync(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
snd_pcm_t *slave = multi->slaves[0].pcm;
|
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
||||||
return snd_pcm_hwsync(slave);
|
return snd_pcm_hwsync(slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_multi_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
|
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
||||||
|
return INTERNAL(snd_pcm_hwptr)(slave, hwptr);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
snd_pcm_t *slave = multi->slaves[0].pcm;
|
snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
|
||||||
return snd_pcm_delay(slave, delayp);
|
return snd_pcm_delay(slave, delayp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -602,6 +609,7 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
|
||||||
status: snd_pcm_multi_status,
|
status: snd_pcm_multi_status,
|
||||||
state: snd_pcm_multi_state,
|
state: snd_pcm_multi_state,
|
||||||
hwsync: snd_pcm_multi_hwsync,
|
hwsync: snd_pcm_multi_hwsync,
|
||||||
|
hwptr: snd_pcm_multi_hwptr,
|
||||||
delay: snd_pcm_multi_delay,
|
delay: snd_pcm_multi_delay,
|
||||||
prepare: snd_pcm_multi_prepare,
|
prepare: snd_pcm_multi_prepare,
|
||||||
reset: snd_pcm_multi_reset,
|
reset: snd_pcm_multi_reset,
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,23 @@ static int snd_pcm_null_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_null_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
switch (snd_pcm_state(pcm)) {
|
||||||
|
case SND_PCM_STATE_RUNNING:
|
||||||
|
case SND_PCM_STATE_DRAINING:
|
||||||
|
case SND_PCM_STATE_PREPARED:
|
||||||
|
case SND_PCM_STATE_PAUSED:
|
||||||
|
case SND_PCM_STATE_SUSPENDED:
|
||||||
|
*hwptr = *pcm->hw.ptr;
|
||||||
|
return 0;
|
||||||
|
case SND_PCM_STATE_XRUN:
|
||||||
|
return -EPIPE;
|
||||||
|
default:
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_null_delay(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
*delayp = 0;
|
*delayp = 0;
|
||||||
|
|
@ -312,6 +329,7 @@ static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
|
||||||
status: snd_pcm_null_status,
|
status: snd_pcm_null_status,
|
||||||
state: snd_pcm_null_state,
|
state: snd_pcm_null_state,
|
||||||
hwsync: snd_pcm_null_hwsync,
|
hwsync: snd_pcm_null_hwsync,
|
||||||
|
hwptr: snd_pcm_null_hwptr,
|
||||||
delay: snd_pcm_null_delay,
|
delay: snd_pcm_null_delay,
|
||||||
prepare: snd_pcm_null_prepare,
|
prepare: snd_pcm_null_prepare,
|
||||||
reset: snd_pcm_null_reset,
|
reset: snd_pcm_null_reset,
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,12 @@ int snd_pcm_plugin_hwsync(snd_pcm_t *pcm)
|
||||||
return snd_pcm_hwsync(plugin->slave);
|
return snd_pcm_hwsync(plugin->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snd_pcm_plugin_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||||
|
return INTERNAL(snd_pcm_hwptr)(plugin->slave, hwptr);
|
||||||
|
}
|
||||||
|
|
||||||
int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||||
|
|
@ -626,6 +632,7 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
|
||||||
status: snd_pcm_plugin_status,
|
status: snd_pcm_plugin_status,
|
||||||
state: snd_pcm_plugin_state,
|
state: snd_pcm_plugin_state,
|
||||||
hwsync: snd_pcm_plugin_hwsync,
|
hwsync: snd_pcm_plugin_hwsync,
|
||||||
|
hwptr: snd_pcm_plugin_hwptr,
|
||||||
delay: snd_pcm_plugin_delay,
|
delay: snd_pcm_plugin_delay,
|
||||||
prepare: snd_pcm_plugin_prepare,
|
prepare: snd_pcm_plugin_prepare,
|
||||||
reset: snd_pcm_plugin_reset,
|
reset: snd_pcm_plugin_reset,
|
||||||
|
|
|
||||||
|
|
@ -737,6 +737,36 @@ static int snd_pcm_share_hwsync(snd_pcm_t *pcm)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _snd_pcm_share_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
snd_pcm_share_t *share = pcm->private_data;
|
||||||
|
snd_pcm_share_slave_t *slave = share->slave;
|
||||||
|
switch (share->state) {
|
||||||
|
case SND_PCM_STATE_RUNNING:
|
||||||
|
case SND_PCM_STATE_DRAINING:
|
||||||
|
case SND_PCM_STATE_PREPARED:
|
||||||
|
case SND_PCM_STATE_PAUSED:
|
||||||
|
case SND_PCM_STATE_SUSPENDED:
|
||||||
|
*hwptr = *pcm->hw.ptr;
|
||||||
|
return 0;
|
||||||
|
case SND_PCM_STATE_XRUN:
|
||||||
|
return -EPIPE;
|
||||||
|
default:
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
|
||||||
|
{
|
||||||
|
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_hwptr(pcm, hwptr);
|
||||||
|
Pthread_mutex_unlock(&slave->mutex);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
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_t *share = pcm->private_data;
|
||||||
|
|
@ -1234,6 +1264,7 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
|
||||||
status: snd_pcm_share_status,
|
status: snd_pcm_share_status,
|
||||||
state: snd_pcm_share_state,
|
state: snd_pcm_share_state,
|
||||||
hwsync: snd_pcm_share_hwsync,
|
hwsync: snd_pcm_share_hwsync,
|
||||||
|
hwptr: snd_pcm_share_hwptr,
|
||||||
delay: snd_pcm_share_delay,
|
delay: snd_pcm_share_delay,
|
||||||
prepare: snd_pcm_share_prepare,
|
prepare: snd_pcm_share_prepare,
|
||||||
reset: snd_pcm_share_reset,
|
reset: snd_pcm_share_reset,
|
||||||
|
|
|
||||||
|
|
@ -451,6 +451,19 @@ static int snd_pcm_shm_hwsync(snd_pcm_t *pcm)
|
||||||
return snd_pcm_shm_action(pcm);
|
return snd_pcm_shm_action(pcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_shm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *uframes)
|
||||||
|
{
|
||||||
|
snd_pcm_shm_t *shm = pcm->private_data;
|
||||||
|
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
||||||
|
int err;
|
||||||
|
ctrl->cmd = SND_PCM_IOCTL_HWPTR;
|
||||||
|
return snd_pcm_shm_action(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
*uframes = ctrl->u.hwptr.frames;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
snd_pcm_shm_t *shm = pcm->private_data;
|
snd_pcm_shm_t *shm = pcm->private_data;
|
||||||
|
|
@ -619,6 +632,7 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
|
||||||
status: snd_pcm_shm_status,
|
status: snd_pcm_shm_status,
|
||||||
state: snd_pcm_shm_state,
|
state: snd_pcm_shm_state,
|
||||||
hwsync: snd_pcm_shm_hwsync,
|
hwsync: snd_pcm_shm_hwsync,
|
||||||
|
hwptr: snd_pcm_shm_hwptr,
|
||||||
delay: snd_pcm_shm_delay,
|
delay: snd_pcm_shm_delay,
|
||||||
prepare: snd_pcm_shm_prepare,
|
prepare: snd_pcm_shm_prepare,
|
||||||
reset: snd_pcm_shm_reset,
|
reset: snd_pcm_shm_reset,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue