Removed snd_pcm_hwptr().

Added snd_pcm_hwdiff() and snd_pcm_forward().
Returned the behaviour for snd_pcm_mmap_begin().
This commit is contained in:
Jaroslav Kysela 2003-02-22 17:19:02 +00:00
parent fbd99fdec0
commit 2dab1dfbc3
17 changed files with 327 additions and 246 deletions

View file

@ -471,9 +471,6 @@ static int pcm_shm_cmd(client_t *client)
case SND_PCM_IOCTL_HWSYNC:
ctrl->result = snd_pcm_hwsync(pcm);
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:
ctrl->result = snd_pcm_delay(pcm, (snd_pcm_sframes_t *) &ctrl->u.delay.frames);
break;
@ -507,6 +504,9 @@ static int pcm_shm_cmd(client_t *client)
case SNDRV_PCM_IOCTL_REWIND:
ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind.frames);
break;
case SND_PCM_IOCTL_FORWARD:
ctrl->result = snd_pcm_forward(pcm, ctrl->u.forward.frames);
break;
case SNDRV_PCM_IOCTL_LINK:
{
/* FIXME */

View file

@ -50,7 +50,7 @@ typedef enum _snd_transport_type {
#define SND_PCM_IOCTL_POLL_DESCRIPTOR _IO ('A', 0xf8)
#define SND_PCM_IOCTL_HW_PTR_FD _IO ('A', 0xf9)
#define SND_PCM_IOCTL_APPL_PTR_FD _IO ('A', 0xfa)
#define SND_PCM_IOCTL_HWPTR _IO ('A', 0xfb)
#define SND_PCM_IOCTL_FORWARD _IO ('A', 0xfb)
typedef struct {
snd_pcm_uframes_t ptr;
@ -74,9 +74,6 @@ typedef struct {
snd_pcm_hw_params_t hw_params;
snd_pcm_sw_params_t sw_params;
snd_pcm_status_t status;
struct {
snd_pcm_uframes_t frames;
} hwptr;
struct {
snd_pcm_uframes_t frames;
} avail;
@ -90,6 +87,9 @@ typedef struct {
struct {
snd_pcm_uframes_t frames;
} rewind;
struct {
snd_pcm_uframes_t frames;
} forward;
struct {
int fd;
} link;

View file

@ -410,11 +410,12 @@ int snd_pcm_drain(snd_pcm_t *pcm);
int snd_pcm_pause(snd_pcm_t *pcm, int enable);
snd_pcm_state_t snd_pcm_state(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_hwdiff(snd_pcm_t *pcm, snd_pcm_uframes_t *diff, snd_pcm_uframes_t *old_pos);
int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
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_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t snd_pcm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);

View file

@ -83,6 +83,7 @@ ALSA_0.9.0rc4 {
ALSA_0.9.0rc8 {
global:
snd_pcm_hwptr;
snd_pcm_hwdiff;
snd_pcm_forward;
} ALSA_0.9.0rc4;

View file

@ -400,6 +400,12 @@ 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.
<p>
To determine the processed frames by hardware, the function \link ::snd_pcm_hwdiff \endlink
might be used. Note that this function returns cached value which is synchronized with
hardware using the \link ::snd_pcm_hwsync \endlink function. The application may
manage the right r/w pointer via \link ::snd_pcm_rewind \endlink and
\link ::snd_pcm_forward \endlink functions.
\section pcm_action Managing the stream state
@ -869,28 +875,42 @@ int snd_pcm_hwsync(snd_pcm_t *pcm)
}
/**
* \brief Return hardware pointer
* \brief Return count of processed frames by hardware from last call
* \param pcm PCM handle
* \param diff Difference between last position and current
* \param old_pos Old position on entry, actual position on exit
* \return 0 on success otherwise a negative error code
*
* The hardware pointer is in range 0 ... (boundary - 1). It contains
* The old_ptr parameter is in range 0 ... (boundary - 1). It contains
* count_of_ring_buffer_crosses * buffer_size + offset in the ring buffer.
* Using this value is not intented
*
* Note this function does not return the real hardware pointer.
* Note this function does not obtain the real position from hardware.
* 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)
int INTERNAL(snd_pcm_hwdiff)(snd_pcm_t *pcm, snd_pcm_uframes_t *diff, snd_pcm_uframes_t *old_pos)
#else
int snd_pcm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
int snd_pcm_hwdiff(snd_pcm_t *pcm, snd_pcm_uframes_t *diff, snd_pcm_uframes_t *old_pos)
#endif
{
assert(pcm);
snd_pcm_uframes_t d, hw_ptr;
assert(pcm && diff && old_pos);
assert(pcm->setup);
return pcm->fast_ops->hwptr(pcm->fast_op_arg, hwptr);
assert(*old_pos < pcm->boundary);
hw_ptr = *pcm->hw.ptr;
if (hw_ptr < *old_pos) {
d = (pcm->boundary - *old_pos) + hw_ptr;
} else {
d = hw_ptr - *old_pos;
}
default_symbol_version(__snd_pcm_hwptr, snd_pcm_hwptr, ALSA_0.9.0rc8);
*diff = d;
*old_pos = hw_ptr;
return 0;
}
default_symbol_version(__snd_pcm_hwdiff, snd_pcm_hwdiff, ALSA_0.9.0rc8);
/**
* \brief Obtain delay for a running PCM handle
@ -1029,6 +1049,25 @@ snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
return pcm->fast_ops->rewind(pcm->fast_op_arg, frames);
}
/**
* \brief Move application frame position forward
* \param pcm PCM handle
* \param frames wanted skip in frames
* \return a positive number for actual skip otherwise a negative error code
*/
#ifndef DOXYGEN
snd_pcm_sframes_t INTERNAL(snd_pcm_forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
#else
snd_pcm_sframes_t snd_pcm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
#endif
{
assert(pcm);
assert(pcm->setup);
assert(frames > 0);
return pcm->fast_ops->forward(pcm->fast_op_arg, frames);
}
default_symbol_version(__snd_pcm_forward, snd_pcm_forward, ALSA_0.9.0rc8);
/**
* \brief Write interleaved frames to a PCM
* \param pcm PCM handle
@ -5816,7 +5855,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
* \param pcm PCM handle
* \param areas Returned mmap channel areas
* \param offset mmap area offset in area steps (== frames) (wanted on entry (see note), returned on exit)
* \param offset Returned mmap area offset in area steps (== frames)
* \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit)
* \return 0 on success otherwise a negative error code
*
@ -5829,10 +5868,6 @@ 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
* 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,
const snd_pcm_channel_area_t **areas,
@ -5844,16 +5879,10 @@ int snd_pcm_mmap_begin(snd_pcm_t *pcm,
snd_pcm_uframes_t avail;
assert(pcm && areas && offset && frames);
*areas = snd_pcm_mmap_areas(pcm);
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;
f = *frames;
if (f > avail)

View file

@ -989,25 +989,6 @@ 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)
{
snd_pcm_dmix_t *dmix = pcm->private_data;
@ -1108,6 +1089,19 @@ static snd_pcm_sframes_t snd_pcm_dmix_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
return frames;
}
static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_sframes_t avail;
avail = snd_pcm_mmap_avail(pcm);
if (avail < 0)
return 0;
if (frames > avail)
frames = avail;
snd_pcm_mmap_appl_forward(pcm, frames);
return frames;
}
static int snd_pcm_dmix_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
{
// snd_pcm_dmix_t *dmix = pcm->private_data;
@ -1224,7 +1218,6 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
status: snd_pcm_dmix_status,
state: snd_pcm_dmix_state,
hwsync: snd_pcm_dmix_hwsync,
hwptr: snd_pcm_dmix_hwptr,
delay: snd_pcm_dmix_delay,
prepare: snd_pcm_dmix_prepare,
reset: snd_pcm_dmix_reset,
@ -1233,6 +1226,7 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
drain: snd_pcm_dmix_drain,
pause: snd_pcm_dmix_pause,
rewind: snd_pcm_dmix_rewind,
forward: snd_pcm_dmix_forward,
resume: snd_pcm_dmix_resume,
writei: snd_pcm_mmap_writei,
writen: snd_pcm_mmap_writen,

View file

@ -168,12 +168,6 @@ static int snd_pcm_file_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_file_t *file = pcm->private_data;
@ -236,19 +230,37 @@ static int snd_pcm_file_pause(snd_pcm_t *pcm, int enable)
static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_file_t *file = pcm->private_data;
snd_pcm_sframes_t err = snd_pcm_rewind(file->slave, frames);
snd_pcm_sframes_t err;
snd_pcm_uframes_t n;
n = snd_pcm_frames_to_bytes(pcm, frames);
if (n > file->wbuf_used_bytes)
frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_used_bytes);
err = snd_pcm_rewind(file->slave, frames);
if (err > 0) {
snd_pcm_uframes_t n = snd_pcm_frames_to_bytes(pcm, frames);
snd_pcm_sframes_t ptr;
assert(n >= file->wbuf_used_bytes);
ptr = file->appl_ptr - err;
if (ptr < 0)
ptr += file->wbuf_size;
n = snd_pcm_frames_to_bytes(pcm, err);
file->wbuf_used_bytes -= n;
}
return err;
}
static snd_pcm_sframes_t snd_pcm_file_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_file_t *file = pcm->private_data;
snd_pcm_sframes_t err;
snd_pcm_uframes_t n;
n = snd_pcm_frames_to_bytes(pcm, frames);
if (file->wbuf_used_bytes + n > file->wbuf_size_bytes)
frames = snd_pcm_bytes_to_frames(pcm, file->wbuf_size_bytes - file->wbuf_used_bytes);
err = snd_pcm_forward(file->slave, frames);
if (err > 0) {
snd_pcm_uframes_t n = snd_pcm_frames_to_bytes(pcm, err);
file->wbuf_used_bytes += n;
}
return err;
}
static int snd_pcm_file_resume(snd_pcm_t *pcm)
{
snd_pcm_file_t *file = pcm->private_data;
@ -372,9 +384,6 @@ 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)
{
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);
}
@ -422,7 +431,6 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
status: snd_pcm_file_status,
state: snd_pcm_file_state,
hwsync: snd_pcm_file_hwsync,
hwptr: snd_pcm_file_hwptr,
delay: snd_pcm_file_delay,
prepare: snd_pcm_file_prepare,
reset: snd_pcm_file_reset,
@ -431,6 +439,7 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
drain: snd_pcm_file_drain,
pause: snd_pcm_file_pause,
rewind: snd_pcm_file_rewind,
forward: snd_pcm_file_forward,
resume: snd_pcm_file_resume,
writei: snd_pcm_file_writei,
writen: snd_pcm_file_writen,

View file

@ -122,12 +122,6 @@ static int snd_pcm_hooks_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_hooks_t *h = pcm->private_data;
@ -176,6 +170,12 @@ static snd_pcm_sframes_t snd_pcm_hooks_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
return snd_pcm_rewind(h->slave, frames);
}
static snd_pcm_sframes_t snd_pcm_hooks_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_hooks_t *h = pcm->private_data;
return snd_pcm_forward(h->slave, frames);
}
static int snd_pcm_hooks_resume(snd_pcm_t *pcm)
{
snd_pcm_hooks_t *h = pcm->private_data;
@ -305,7 +305,6 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
status: snd_pcm_hooks_status,
state: snd_pcm_hooks_state,
hwsync: snd_pcm_hooks_hwsync,
hwptr: snd_pcm_hooks_hwptr,
delay: snd_pcm_hooks_delay,
prepare: snd_pcm_hooks_prepare,
reset: snd_pcm_hooks_reset,
@ -314,6 +313,7 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
drain: snd_pcm_hooks_drain,
pause: snd_pcm_hooks_pause,
rewind: snd_pcm_hooks_rewind,
forward: snd_pcm_hooks_forward,
resume: snd_pcm_hooks_resume,
writei: snd_pcm_hooks_writei,
writen: snd_pcm_hooks_writen,

View file

@ -345,9 +345,6 @@ 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;
return 0;
}
/* FIXME */
if (hw->mmap_shm && params->stop_threshold >= params->boundary)
return -EINVAL;
if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
SYSERR("SNDRV_PCM_IOCTL_SW_PARAMS failed");
return -errno;
@ -431,23 +428,6 @@ static int snd_pcm_hw_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_hw_t *hw = pcm->private_data;
@ -534,6 +514,31 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra
return frames;
}
static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_hw_t *hw = pcm->private_data;
snd_pcm_sframes_t avail;
switch (FAST_PCM_STATE(hw)) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
case SNDRV_PCM_STATE_PREPARED:
break;
case SNDRV_PCM_STATE_XRUN:
return -EPIPE;
default:
return -EBADFD;
}
avail = snd_pcm_mmap_avail(pcm);
if (avail < 0)
return 0;
if (frames > avail)
frames = avail;
snd_pcm_mmap_appl_forward(pcm, frames);
return frames;
}
static int snd_pcm_hw_resume(snd_pcm_t *pcm)
{
snd_pcm_hw_t *hw = pcm->private_data;
@ -718,12 +723,6 @@ static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
if (hw->mmap_shm) {
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
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 {
res = snd_pcm_write_mmap(pcm, size);
@ -819,7 +818,6 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
status: snd_pcm_hw_status,
state: snd_pcm_hw_state,
hwsync: snd_pcm_hw_hwsync,
hwptr: snd_pcm_hw_hwptr,
delay: snd_pcm_hw_delay,
prepare: snd_pcm_hw_prepare,
reset: snd_pcm_hw_reset,
@ -828,6 +826,7 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
drain: snd_pcm_hw_drain,
pause: snd_pcm_hw_pause,
rewind: snd_pcm_hw_rewind,
forward: snd_pcm_hw_forward,
resume: snd_pcm_hw_resume,
writei: snd_pcm_hw_writei,
writen: snd_pcm_hw_writen,

View file

@ -185,24 +185,6 @@ static int snd_pcm_jack_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
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)
{
#ifdef PCM_JACK_DEBUG
@ -460,6 +442,22 @@ static snd_pcm_sframes_t snd_pcm_jack_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
return frames;
}
static snd_pcm_sframes_t snd_pcm_jack_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_sframes_t avail;
#ifdef PCM_JACK_DEBUG
printf("snd_pcm_jack_forward\n"); fflush(stdout);
#endif
avail = snd_pcm_mmap_avail(pcm);
if (avail < 0)
return 0;
if (frames > (snd_pcm_uframes_t) avail)
frames = (snd_pcm_uframes_t) avail;
snd_pcm_mmap_appl_forward(pcm, frames);
return frames;
}
static int snd_pcm_jack_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
{
return 0;
@ -611,7 +609,6 @@ static snd_pcm_fast_ops_t snd_pcm_jack_fast_ops = {
status: snd_pcm_jack_status,
state: snd_pcm_jack_state,
hwsync: snd_pcm_jack_hwsync,
hwptr: snd_pcm_jack_hwptr,
delay: snd_pcm_jack_delay,
prepare: snd_pcm_jack_prepare,
reset: snd_pcm_jack_reset,
@ -620,6 +617,7 @@ static snd_pcm_fast_ops_t snd_pcm_jack_fast_ops = {
drain: snd_pcm_jack_drain,
pause: snd_pcm_jack_pause,
rewind: snd_pcm_jack_rewind,
forward: snd_pcm_jack_forward,
resume: snd_pcm_jack_resume,
writei: snd_pcm_mmap_writei,
writen: snd_pcm_mmap_writen,

View file

@ -147,10 +147,10 @@ typedef struct {
int (*pause)(snd_pcm_t *pcm, int enable);
snd_pcm_state_t (*state)(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 (*resume)(snd_pcm_t *pcm);
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
snd_pcm_sframes_t (*writen)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
snd_pcm_sframes_t (*readi)(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
@ -550,7 +550,8 @@ int snd_pcm_hw_param_get_max(const snd_pcm_hw_params_t *params,
unsigned int *val, int *dir);
#ifdef INTERNAL
int INTERNAL(snd_pcm_hwptr)(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr);
int INTERNAL(snd_pcm_hwdiff)(snd_pcm_t *pcm, snd_pcm_uframes_t *diff, snd_pcm_uframes_t *old_pos);
snd_pcm_sframes_t INTERNAL(snd_pcm_forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
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);

View file

@ -325,12 +325,6 @@ static int snd_pcm_meter_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_meter_t *meter = pcm->private_data;
@ -402,6 +396,15 @@ static snd_pcm_sframes_t snd_pcm_meter_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
return err;
}
static snd_pcm_sframes_t snd_pcm_meter_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_meter_t *meter = pcm->private_data;
snd_pcm_sframes_t err = snd_pcm_forward(meter->slave, frames);
if (err > 0 && pcm->stream == SND_PCM_STREAM_PLAYBACK)
meter->rptr = *pcm->appl.ptr;
return err;
}
static int snd_pcm_meter_resume(snd_pcm_t *pcm)
{
snd_pcm_meter_t *meter = pcm->private_data;
@ -614,6 +617,7 @@ static snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
drain: snd_pcm_meter_drain,
pause: snd_pcm_meter_pause,
rewind: snd_pcm_meter_rewind,
forward: snd_pcm_meter_forward,
resume: snd_pcm_meter_resume,
writei: snd_pcm_mmap_writei,
writen: snd_pcm_mmap_writen,

View file

@ -358,13 +358,6 @@ static int snd_pcm_multi_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_multi_t *multi = pcm->private_data;
@ -512,7 +505,37 @@ static snd_pcm_sframes_t snd_pcm_multi_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
snd_pcm_uframes_t f = pos[i] - frames;
snd_pcm_sframes_t result;
if (f > 0) {
result = snd_pcm_mmap_commit(slave_i, snd_pcm_mmap_offset(slave_i), f);
result = snd_pcm_forward(slave_i, f);
if (result < 0)
return result;
if ((snd_pcm_uframes_t)result != f)
return -EIO;
}
}
return frames;
}
static snd_pcm_sframes_t snd_pcm_multi_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_multi_t *multi = pcm->private_data;
unsigned int i;
snd_pcm_uframes_t pos[multi->slaves_count];
memset(pos, 0, sizeof(pos));
for (i = 0; i < multi->slaves_count; ++i) {
snd_pcm_t *slave_i = multi->slaves[i].pcm;
snd_pcm_sframes_t f = snd_pcm_forward(slave_i, frames);
if (f < 0)
return f;
pos[i] = f;
frames = f;
}
/* Realign the pointers */
for (i = 0; i < multi->slaves_count; ++i) {
snd_pcm_t *slave_i = multi->slaves[i].pcm;
snd_pcm_uframes_t f = pos[i] - frames;
snd_pcm_sframes_t result;
if (f > 0) {
result = snd_pcm_rewind(slave_i, f);
if (result < 0)
return result;
if ((snd_pcm_uframes_t)result != f)
@ -609,7 +632,6 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
status: snd_pcm_multi_status,
state: snd_pcm_multi_state,
hwsync: snd_pcm_multi_hwsync,
hwptr: snd_pcm_multi_hwptr,
delay: snd_pcm_multi_delay,
prepare: snd_pcm_multi_prepare,
reset: snd_pcm_multi_reset,
@ -622,6 +644,7 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
readi: snd_pcm_mmap_readi,
readn: snd_pcm_mmap_readn,
rewind: snd_pcm_multi_rewind,
forward: snd_pcm_multi_forward,
resume: snd_pcm_multi_resume,
avail_update: snd_pcm_multi_avail_update,
mmap_commit: snd_pcm_multi_mmap_commit,

View file

@ -105,23 +105,6 @@ static int snd_pcm_null_hwsync(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
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)
{
*delayp = 0;
@ -202,6 +185,21 @@ static snd_pcm_sframes_t snd_pcm_null_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
}
}
static snd_pcm_sframes_t snd_pcm_null_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_null_t *null = pcm->private_data;
switch (null->state) {
case SND_PCM_STATE_RUNNING:
snd_pcm_mmap_hw_forward(pcm, frames);
/* Fall through */
case SND_PCM_STATE_PREPARED:
snd_pcm_mmap_appl_forward(pcm, frames);
return frames;
default:
return -EBADFD;
}
}
static int snd_pcm_null_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
{
return 0;
@ -329,7 +327,6 @@ static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
status: snd_pcm_null_status,
state: snd_pcm_null_state,
hwsync: snd_pcm_null_hwsync,
hwptr: snd_pcm_null_hwptr,
delay: snd_pcm_null_delay,
prepare: snd_pcm_null_prepare,
reset: snd_pcm_null_reset,
@ -338,6 +335,7 @@ static snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
drain: snd_pcm_null_drain,
pause: snd_pcm_null_pause,
rewind: snd_pcm_null_rewind,
forward: snd_pcm_null_forward,
resume: snd_pcm_null_resume,
writei: snd_pcm_null_writei,
writen: snd_pcm_null_writen,

View file

@ -199,12 +199,6 @@ int snd_pcm_plugin_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_plugin_t *plugin = pcm->private_data;
@ -288,34 +282,56 @@ snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames
{
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_sframes_t n = snd_pcm_mmap_hw_avail(pcm);
assert(n >= 0);
if (n > 0) {
snd_pcm_sframes_t sframes;
if ((snd_pcm_uframes_t)n > frames)
n = frames;
frames -= n;
}
if (frames > 0) {
snd_pcm_sframes_t err;
frames = n;
if (frames == 0)
return 0;
/* FIXME: rate plugin */
if (plugin->slave_frames)
frames = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
sframes = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
else
sframes = frames;
snd_atomic_write_begin(&plugin->watom);
err = snd_pcm_rewind(plugin->slave, frames);
if (err < 0) {
if (n <= 0) {
sframes = snd_pcm_rewind(plugin->slave, sframes);
if (sframes < 0) {
snd_atomic_write_end(&plugin->watom);
return err;
}
goto _end;
return sframes;
}
if (plugin->client_frames)
err = plugin->client_frames(pcm, err);
snd_pcm_mmap_hw_backward(pcm, (snd_pcm_uframes_t) err);
n += err;
} else
frames = plugin->client_frames(pcm, sframes);
snd_pcm_mmap_appl_backward(pcm, (snd_pcm_uframes_t) frames);
snd_atomic_write_end(&plugin->watom);
return n;
}
snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_sframes_t n = snd_pcm_mmap_avail(pcm);
snd_pcm_uframes_t sframes;
if ((snd_pcm_uframes_t)n > frames)
frames = n;
if (frames == 0)
return 0;
/* FIXME: rate plugin */
if (plugin->slave_frames)
sframes = plugin->slave_frames(pcm, (snd_pcm_sframes_t) frames);
else
sframes = frames;
snd_atomic_write_begin(&plugin->watom);
_end:
snd_pcm_mmap_appl_backward(pcm, (snd_pcm_uframes_t) n);
sframes = snd_pcm_forward(plugin->slave, (snd_pcm_uframes_t) sframes);
if (sframes < 0) {
snd_atomic_write_end(&plugin->watom);
return sframes;
}
if (plugin->client_frames)
frames = plugin->client_frames(pcm, sframes);
snd_pcm_mmap_appl_forward(pcm, (snd_pcm_uframes_t) frames);
snd_atomic_write_end(&plugin->watom);
return n;
}
@ -632,7 +648,6 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
status: snd_pcm_plugin_status,
state: snd_pcm_plugin_state,
hwsync: snd_pcm_plugin_hwsync,
hwptr: snd_pcm_plugin_hwptr,
delay: snd_pcm_plugin_delay,
prepare: snd_pcm_plugin_prepare,
reset: snd_pcm_plugin_reset,
@ -641,6 +656,7 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
drain: snd_pcm_plugin_drain,
pause: snd_pcm_plugin_pause,
rewind: snd_pcm_plugin_rewind,
forward: snd_pcm_plugin_forward,
resume: snd_pcm_plugin_resume,
writei: snd_pcm_plugin_writei,
writen: snd_pcm_plugin_writen,

View file

@ -1,4 +1,4 @@
/**
/*
* \file pcm/pcm_share.c
* \ingroup PCM_Plugins
* \brief PCM Share Plugin Interface
@ -737,36 +737,6 @@ static int snd_pcm_share_hwsync(snd_pcm_t *pcm)
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)
{
snd_pcm_share_t *share = pcm->private_data;
@ -1027,19 +997,15 @@ static snd_pcm_sframes_t _snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
}
n = snd_pcm_mmap_hw_avail(pcm);
assert(n >= 0);
if (n > 0) {
if ((snd_pcm_uframes_t)n > frames)
n = frames;
frames -= n;
}
if (share->state == SND_PCM_STATE_RUNNING &&
frames > 0) {
int ret = snd_pcm_rewind(slave->pcm, frames);
frames = n;
if (share->state == SND_PCM_STATE_RUNNING && frames > 0) {
snd_pcm_sframes_t ret = snd_pcm_rewind(slave->pcm, frames);
if (ret < 0)
return ret;
n += ret;
frames = ret;
}
snd_pcm_mmap_appl_backward(pcm, n);
snd_pcm_mmap_appl_backward(pcm, frames);
_snd_pcm_share_update(pcm);
return n;
}
@ -1055,6 +1021,52 @@ static snd_pcm_sframes_t snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
return ret;
}
static snd_pcm_sframes_t _snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_share_t *share = pcm->private_data;
snd_pcm_share_slave_t *slave = share->slave;
snd_pcm_sframes_t n;
switch (share->state) {
case SND_PCM_STATE_RUNNING:
break;
case SND_PCM_STATE_PREPARED:
if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
return -EBADFD;
break;
case SND_PCM_STATE_DRAINING:
if (pcm->stream != SND_PCM_STREAM_CAPTURE)
return -EBADFD;
break;
case SND_PCM_STATE_XRUN:
return -EPIPE;
default:
return -EBADFD;
}
n = snd_pcm_mmap_avail(pcm);
if ((snd_pcm_uframes_t)n > frames)
frames = n;
if (share->state == SND_PCM_STATE_RUNNING && frames > 0) {
snd_pcm_sframes_t ret = snd_pcm_forward(slave->pcm, frames);
if (ret < 0)
return ret;
frames = ret;
}
snd_pcm_mmap_appl_forward(pcm, frames);
_snd_pcm_share_update(pcm);
return n;
}
static snd_pcm_sframes_t snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_share_t *share = pcm->private_data;
snd_pcm_share_slave_t *slave = share->slave;
snd_pcm_sframes_t ret;
Pthread_mutex_lock(&slave->mutex);
ret = _snd_pcm_share_forward(pcm, frames);
Pthread_mutex_unlock(&slave->mutex);
return ret;
}
/* Warning: take the mutex before to call this */
static void _snd_pcm_share_stop(snd_pcm_t *pcm, snd_pcm_state_t state)
{
@ -1264,7 +1276,6 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
status: snd_pcm_share_status,
state: snd_pcm_share_state,
hwsync: snd_pcm_share_hwsync,
hwptr: snd_pcm_share_hwptr,
delay: snd_pcm_share_delay,
prepare: snd_pcm_share_prepare,
reset: snd_pcm_share_reset,
@ -1277,6 +1288,7 @@ static snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
readi: snd_pcm_mmap_readi,
readn: snd_pcm_mmap_readn,
rewind: snd_pcm_share_rewind,
forward: snd_pcm_share_forward,
resume: snd_pcm_share_resume,
avail_update: snd_pcm_share_avail_update,
mmap_commit: snd_pcm_share_mmap_commit,

View file

@ -451,19 +451,6 @@ static int snd_pcm_shm_hwsync(snd_pcm_t *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)
{
snd_pcm_shm_t *shm = pcm->private_data;
@ -558,6 +545,15 @@ static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fr
return snd_pcm_shm_action(pcm);
}
static snd_pcm_sframes_t snd_pcm_shm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
{
snd_pcm_shm_t *shm = pcm->private_data;
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
ctrl->cmd = SND_PCM_IOCTL_FORWARD;
ctrl->u.forward.frames = frames;
return snd_pcm_shm_action(pcm);
}
static int snd_pcm_shm_resume(snd_pcm_t *pcm)
{
snd_pcm_shm_t *shm = pcm->private_data;
@ -632,7 +628,6 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
status: snd_pcm_shm_status,
state: snd_pcm_shm_state,
hwsync: snd_pcm_shm_hwsync,
hwptr: snd_pcm_shm_hwptr,
delay: snd_pcm_shm_delay,
prepare: snd_pcm_shm_prepare,
reset: snd_pcm_shm_reset,
@ -641,6 +636,7 @@ static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
drain: snd_pcm_shm_drain,
pause: snd_pcm_shm_pause,
rewind: snd_pcm_shm_rewind,
forward: snd_pcm_shm_forward,
resume: snd_pcm_shm_resume,
writei: snd_pcm_mmap_writei,
writen: snd_pcm_mmap_writen,