int snd_pcm_delay(snd_pcm_t *pcm, ssize_t *delayp)
{
assert(pcm);
+ assert(pcm->valid_setup);
return pcm->fast_ops->delay(pcm->fast_op_arg, delayp);
}
int snd_pcm_prepare(snd_pcm_t *pcm)
{
assert(pcm);
+ assert(pcm->valid_setup);
return pcm->fast_ops->prepare(pcm->fast_op_arg);
}
int snd_pcm_start(snd_pcm_t *pcm)
{
assert(pcm);
+ assert(pcm->valid_setup);
return pcm->fast_ops->start(pcm->fast_op_arg);
}
int snd_pcm_drop(snd_pcm_t *pcm)
{
assert(pcm);
+ assert(pcm->valid_setup);
return pcm->fast_ops->drop(pcm->fast_op_arg);
}
int snd_pcm_drain(snd_pcm_t *pcm)
{
assert(pcm);
+ assert(pcm->valid_setup);
return pcm->fast_ops->drain(pcm->fast_op_arg);
}
int snd_pcm_pause(snd_pcm_t *pcm, int enable)
{
assert(pcm);
+ assert(pcm->valid_setup);
return pcm->fast_ops->pause(pcm->fast_op_arg, enable);
}
fprintf(fp, "tstamp : %ld.%06ld\n",
status->tstamp.tv_sec, status->tstamp.tv_usec);
fprintf(fp, "delay : %ld\n", (long)status->delay);
- fprintf(fp, "avail_max : %ld\n", (long)status->avail_max);
- fprintf(fp, "appl_ptr : %ld\n", (long)status->appl_ptr);
- fprintf(fp, "hw_ptr : %ld\n", (long)status->hw_ptr);
fprintf(fp, "avail : %ld\n", (long)status->avail);
+ fprintf(fp, "avail_max : %ld\n", (long)status->avail_max);
return 0;
}
static int snd_pcm_hw_state(snd_pcm_t *pcm)
{
- snd_pcm_hw_t *hw = pcm->private;
- int fd = hw->fd;
- snd_pcm_status_t status;
- if (pcm->mmap_status)
- return pcm->mmap_status->state;
- if (ioctl(fd, SND_PCM_IOCTL_STATUS, &status) < 0)
- return -errno;
- return status.state;
+ return pcm->mmap_status->state;
}
static int snd_pcm_hw_delay(snd_pcm_t *pcm, ssize_t *delayp)
if (err < 0)
return -errno;
}
- avail = snd_pcm_mmap_avail(pcm);
- if (avail > 0 && hw->mmap_emulation &&
- pcm->stream == SND_PCM_STREAM_CAPTURE) {
- err = snd_pcm_read_mmap(pcm, avail);
- if (err < 0)
+ if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
+ avail = snd_pcm_mmap_playback_avail(pcm);
+ } else {
+ avail = snd_pcm_mmap_capture_avail(pcm);
+ if (avail > 0 && hw->mmap_emulation) {
+ err = snd_pcm_read_mmap(pcm, avail);
+ if (err < 0)
+ return err;
+ assert((size_t)err == avail);
return err;
- assert((size_t)err == avail);
- return err;
+ }
}
return avail;
}
ssize_t snd_pcm_mmap_appl_ptr(snd_pcm_t *pcm, off_t offset);
void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames);
void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, size_t frames);
+void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, size_t frames);
void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, size_t frames);
size_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm);
size_t snd_pcm_mmap_avail(snd_pcm_t *pcm);
return pcm->mmap_status->hw_ptr % pcm->setup.buffer_size;
}
-int snd_pcm_mmap_state(snd_pcm_t *pcm)
-{
- assert(pcm);
- assert(pcm->mmap_status);
- return pcm->mmap_status->state;
-}
-
-ssize_t snd_pcm_mmap_hw_ptr(snd_pcm_t *pcm)
-{
- assert(pcm);
- assert(pcm->mmap_status);
- return pcm->mmap_status->hw_ptr;
-}
-
-ssize_t snd_pcm_mmap_appl_ptr(snd_pcm_t *pcm, off_t offset)
-{
- ssize_t appl_ptr;
- assert(pcm);
- assert(pcm->mmap_status && pcm->mmap_control);
- assert(offset == 0 || pcm->type == SND_PCM_TYPE_HW);
- appl_ptr = pcm->mmap_control->appl_ptr;
- if (offset == 0)
- return appl_ptr;
- switch (pcm->mmap_status->state) {
- case SND_PCM_STATE_RUNNING:
- if (pcm->setup.xrun_mode == SND_PCM_XRUN_ASAP)
- snd_pcm_avail_update(pcm);
- break;
- case SND_PCM_STATE_READY:
- case SND_PCM_STATE_NOTREADY:
- return -EBADFD;
- }
- if (offset < 0) {
- if (offset < -(ssize_t)pcm->setup.buffer_size)
- offset = -(ssize_t)pcm->setup.buffer_size;
- appl_ptr += offset;
- if (appl_ptr < 0)
- appl_ptr += pcm->setup.boundary;
- } else {
- size_t avail;
- if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
- avail = snd_pcm_mmap_playback_avail(pcm);
- else
- avail = snd_pcm_mmap_capture_avail(pcm);
- if ((size_t)offset > avail)
- offset = avail;
- appl_ptr += offset;
- if ((size_t)appl_ptr >= pcm->setup.boundary)
- appl_ptr -= pcm->setup.boundary;
- }
- pcm->mmap_control->appl_ptr = appl_ptr;
- return appl_ptr;
-}
-
void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, size_t frames)
{
ssize_t appl_ptr = pcm->mmap_control->appl_ptr;
pcm->mmap_control->appl_ptr = appl_ptr;
}
+void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, size_t frames)
+{
+ ssize_t hw_ptr = pcm->mmap_status->hw_ptr;
+ hw_ptr -= frames;
+ if (hw_ptr < 0)
+ hw_ptr += pcm->setup.boundary;
+ pcm->mmap_status->hw_ptr = hw_ptr;
+}
+
void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, size_t frames)
{
size_t hw_ptr = pcm->mmap_status->hw_ptr;
int err = snd_pcm_status(plugin->slave, status);
if (err < 0)
return err;
- status->hw_ptr = plugin->mmap_status.hw_ptr;
- status->appl_ptr = plugin->mmap_control.appl_ptr;
- status->avail = (pcm->stream == SND_PCM_STREAM_PLAYBACK ?
- snd_pcm_mmap_playback_avail(pcm) :
- snd_pcm_mmap_capture_avail(pcm));
+ status->avail = snd_pcm_avail_update(pcm);
return 0;
}
int snd_pcm_plugin_delay(snd_pcm_t *pcm, ssize_t *delayp)
{
snd_pcm_plugin_t *plugin = pcm->private;
- ssize_t sd;
+ ssize_t sd, d;
int err = snd_pcm_delay(plugin->slave, &sd);
- int d;
if (err < 0)
return err;
if (plugin->client_frames)
{
snd_pcm_plugin_t *plugin = pcm->private;
ssize_t n = pcm->setup.buffer_size - snd_pcm_mmap_avail(pcm);
+ assert(n >= 0);
if (n > 0) {
if ((size_t)n > frames)
n = frames;
- snd_pcm_mmap_appl_backward(pcm, n);
frames -= n;
}
if (frames > 0) {
ssize_t err = snd_pcm_rewind(plugin->slave, frames);
if (err < 0) {
- if (n > 0)
- return n;
- return err;
+ if (n <= 0)
+ return err;
+ goto _end;
}
if (plugin->client_frames)
err = plugin->client_frames(pcm, err);
+ snd_pcm_mmap_hw_backward(pcm, err);
n += err;
}
+ _end:
+ snd_pcm_mmap_appl_backward(pcm, n);
return n;
}
ssize_t slave_size;
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
snd_pcm_mmap_appl_forward(pcm, client_size);
+ // snd_pcm_plugin_avail_update(pcm);
return client_size;
}
slave_size = snd_pcm_avail_update(slave);
slave_xfer < (size_t)slave_size) {
size_t slave_frames = slave_size - slave_xfer;
size_t client_frames = client_size - client_xfer;
- size_t cont = pcm->setup.buffer_size - snd_pcm_mmap_hw_offset(pcm);
+ size_t offset = snd_pcm_mmap_hw_offset(pcm);
+ size_t cont = pcm->setup.buffer_size - offset;
if (cont < client_frames)
client_frames = cont;
- err = plugin->write(pcm, pcm->mmap_areas,
- snd_pcm_mmap_hw_offset(pcm),
+ err = plugin->write(pcm, pcm->mmap_areas, offset,
client_frames, &slave_frames);
if (err < 0)
break;
client_xfer < client_size) {
size_t slave_frames = slave_size - slave_xfer;
size_t client_frames = client_size - client_xfer;
- size_t cont = pcm->setup.buffer_size - snd_pcm_mmap_hw_offset(pcm);
+ size_t offset = snd_pcm_mmap_hw_offset(pcm);
+ size_t cont = pcm->setup.buffer_size - offset;
if (cont < client_frames)
client_frames = cont;
- err = plugin->read(pcm, pcm->mmap_areas,
- snd_pcm_mmap_hw_offset(pcm),
+ err = plugin->read(pcm, pcm->mmap_areas, offset,
client_frames, &slave_frames);
if (err < 0)
break;