OSDN Git Service

Synchronized snd_pcm_write_areas and snd_pcm_read_areas with the kernel
authorJaroslav Kysela <perex@perex.cz>
Sun, 9 Dec 2001 12:32:42 +0000 (12:32 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sun, 9 Dec 2001 12:32:42 +0000 (12:32 +0000)
write/read functions.
Changed snd_pcm_xfer_areas_func_t to return snd_pcm_sframes_t (pass errors).

src/pcm/pcm.c
src/pcm/pcm_local.h
src/pcm/pcm_mmap.c
src/pcm/pcm_null.c
src/pcm/pcm_plugin.c

index b221f92..c5b872a 100644 (file)
@@ -4945,7 +4945,7 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
                                     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)
@@ -4976,17 +4976,17 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
        _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;
@@ -5029,7 +5029,7 @@ snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area
                                      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)
@@ -5051,19 +5051,26 @@ snd_pcm_sframes_t snd_pcm_write_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 = -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;
index 6d33f7d..dcea957 100644 (file)
@@ -232,7 +232,7 @@ snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_ufram
 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);
index 0dca310..cf842bc 100644 (file)
@@ -80,12 +80,14 @@ void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
        *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;
@@ -96,31 +98,39 @@ static snd_pcm_uframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
                                   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;
index a5f7b05..79c5abf 100644 (file)
@@ -191,7 +191,7 @@ static snd_pcm_sframes_t snd_pcm_null_fwd(snd_pcm_t *pcm, snd_pcm_uframes_t size
        }
 }
 
-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)
index 78712e3..c127bc3 100644 (file)
@@ -197,14 +197,16 @@ int snd_pcm_plugin_resume(snd_pcm_t *pcm)
        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;
@@ -217,22 +219,27 @@ static snd_pcm_uframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
                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;
@@ -245,9 +252,12 @@ static snd_pcm_uframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
                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;