write/read functions.
Changed snd_pcm_xfer_areas_func_t to return snd_pcm_sframes_t (pass errors).
snd_pcm_xfer_areas_func_t func)
{
snd_pcm_uframes_t xfer = 0;
- int err = 0;
+ snd_pcm_sframes_t err = 0;
snd_pcm_state_t state = snd_pcm_state(pcm);
if (size == 0)
_again:
avail = snd_pcm_avail_update(pcm);
if (avail < 0) {
- err = -EPIPE;
+ err = avail;
goto _end;
}
- if (state == SND_PCM_STATE_DRAINING) {
- if (avail == 0) {
+ 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 (avail == 0 ||
- (size >= pcm->xfer_align &&
- (snd_pcm_uframes_t) avail < pcm->xfer_align)) {
+ } 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;
snd_pcm_xfer_areas_func_t func)
{
snd_pcm_uframes_t xfer = 0;
- int err = 0;
+ snd_pcm_sframes_t err = 0;
snd_pcm_state_t state = snd_pcm_state(pcm);
if (size == 0)
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 = -EPIPE;
+ err = avail;
goto _end;
}
- if (state == SND_PCM_STATE_PREPARED) {
- if (avail == 0) {
+ 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 (avail == 0 ||
- (size >= pcm->xfer_align &&
- (snd_pcm_uframes_t) avail < pcm->xfer_align)) {
+ } 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;
snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
-typedef snd_pcm_uframes_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm,
+typedef snd_pcm_sframes_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm,
const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
snd_pcm_uframes_t size);
*pcm->hw_ptr = hw_ptr;
}
-static snd_pcm_uframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
+static snd_pcm_sframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
snd_pcm_uframes_t size)
{
- snd_pcm_uframes_t xfer = size;
+ snd_pcm_uframes_t xfer = 0;
+ int err;
+
assert(snd_pcm_mmap_playback_avail(pcm) >= size);
while (size > 0) {
const snd_pcm_channel_area_t *pcm_areas;
areas, offset,
pcm->channels,
frames, pcm->format);
- snd_pcm_mmap_commit(pcm, pcm_offset, frames);
+ err = snd_pcm_mmap_commit(pcm, pcm_offset, frames);
+ if (err < 0)
+ return xfer > 0 ? xfer : err;
offset += frames;
+ xfer += frames;
size -= frames;
}
return xfer;
}
-static snd_pcm_uframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
+static snd_pcm_sframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
snd_pcm_uframes_t size)
{
- snd_pcm_uframes_t xfer = size;
+ snd_pcm_uframes_t xfer = 0;
+ int err;
+
assert(snd_pcm_mmap_capture_avail(pcm) >= size);
while (size > 0) {
const snd_pcm_channel_area_t *pcm_areas;
snd_pcm_uframes_t pcm_offset;
snd_pcm_uframes_t frames = size;
snd_pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
- snd_pcm_areas_copy(areas, offset,
+ snd_pcm_areas_copy(areas, offset,
pcm_areas, pcm_offset,
pcm->channels,
frames, pcm->format);
- snd_pcm_mmap_commit(pcm, pcm_offset, frames);
+ err = snd_pcm_mmap_commit(pcm, pcm_offset, frames);
+ if (err < 0)
+ return xfer > 0 ? xfer : err;
offset += frames;
+ xfer += frames;
size -= frames;
}
return xfer;
}
}
-static snd_pcm_uframes_t snd_pcm_null_xfer_areas(snd_pcm_t *pcm,
+static snd_pcm_sframes_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)
return snd_pcm_resume(plugin->slave);
}
-static snd_pcm_uframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
+static snd_pcm_sframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
snd_pcm_uframes_t size)
{
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_t *slave = plugin->slave;
- snd_pcm_uframes_t xfer = size;
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_sframes_t err;
+
while (size > 0) {
snd_pcm_uframes_t frames = size;
const snd_pcm_channel_area_t *slave_areas;
snd_atomic_write_begin(&plugin->watom);
snd_pcm_mmap_appl_forward(pcm, frames);
snd_pcm_mmap_hw_forward(pcm, frames);
- snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
+ err = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
snd_atomic_write_end(&plugin->watom);
+ if (err < 0)
+ return xfer > 0 ? xfer : err;
offset += frames;
+ xfer += frames;
size -= frames;
}
return xfer;
}
-static snd_pcm_uframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
+static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
snd_pcm_uframes_t size)
{
snd_pcm_plugin_t *plugin = pcm->private_data;
snd_pcm_t *slave = plugin->slave;
- snd_pcm_uframes_t xfer = size;
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_sframes_t err;
+
while (size > 0) {
snd_pcm_uframes_t frames = size;
const snd_pcm_channel_area_t *slave_areas;
snd_atomic_write_begin(&plugin->watom);
snd_pcm_mmap_appl_forward(pcm, frames);
snd_pcm_mmap_hw_forward(pcm, frames);
- snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
+ err = snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
snd_atomic_write_end(&plugin->watom);
+ if (err < 0)
+ return xfer > 0 ? xfer : err;
offset += frames;
+ xfer += frames;
size -= frames;
}
return xfer;