Update of /cvsroot/alsa/alsa-lib/src/ordinary_pcm
In directory sc8-pr-cvs1:/tmp/cvs-serv749/src/ordinary_pcm

Modified Files:
        ordinary_pcm.c 
Log Message:
More completion.


Index: ordinary_pcm.c
===================================================================
RCS file: /cvsroot/alsa/alsa-lib/src/ordinary_pcm/ordinary_pcm.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ordinary_pcm.c      5 Nov 2003 10:38:38 -0000       1.3
+++ ordinary_pcm.c      19 Jan 2004 19:49:55 -0000      1.4
@@ -3,7 +3,7 @@
  * \ingroup PCM_ordinary
  * \brief Ordinary PCM interface
  * \author Jaroslav Kysela <[EMAIL PROTECTED]>
- * \date 2003
+ * \date 2003,2004
  *
  * Ordinary PCM interface is a high level abtraction for
  * digital audio streaming.
@@ -56,6 +56,7 @@
 #include <sys/mman.h>
 #include <limits.h>
 #include "asoundlib.h"
+#include "alisp.h"
 #include "pcm_ordinary.h"
 
 struct sndo_pcm {
@@ -70,6 +71,12 @@
        unsigned int samplebytes;
        snd_pcm_uframes_t p_offset;
        snd_pcm_uframes_t c_offset;
+       snd_pcm_uframes_t p_period_size;
+       snd_pcm_uframes_t c_period_size;
+       snd_pcm_uframes_t transfer_block;
+       snd_pcm_uframes_t ring_size;
+       enum sndo_pcm_latency_type latency;
+       enum sndo_pcm_xrun_type xrun;
        int setting_up;
        int initialized;
 };
@@ -95,7 +102,7 @@
 int sndo_pcm_open(sndo_pcm_t **ppcm,
                  const char *playback_name,
                  const char *capture_name,
-                 snd_config_t *lconf)
+                 struct alisp_cfg *lconf)
 {
        int err = 0;
        sndo_pcm_t *pcm;
@@ -122,12 +129,12 @@
                goto __end;
        if (lconf) {
                if (playback_name) {
-                       err = snd_pcm_open_lconf(&pcm->playback, playback_name, 
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, lconf);
+                       err = snd_pcm_open_lconf(&pcm->playback, playback_name, 
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, NULL);
                        if (err < 0)
                                goto __end;
                }
                if (capture_name) {
-                       err = snd_pcm_open_lconf(&pcm->capture, playback_name, 
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, lconf);
+                       err = snd_pcm_open_lconf(&pcm->capture, playback_name, 
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, NULL);
                        if (err < 0)
                                goto __end;
                }
@@ -149,8 +156,6 @@
                        goto __end;
                pcm->master = pcm->playback;
        }
-       if (sndo_pcm_param_reset(pcm) >= 0)
-               *ppcm = pcm;
       __end:
        if (err < 0)
                sndo_pcm_close(pcm);
@@ -262,6 +267,11 @@
  */
 int sndo_pcm_start(sndo_pcm_t *pcm)
 {
+       int err;
+
+       err = sndo_pcm_check_setup(pcm);
+       if (err < 0)
+               return err;
        /* the streams are linked, so use only one stream */
        return snd_pcm_start(pcm->master);
 }
@@ -307,11 +317,14 @@
  */
 int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
-       int err = 0;
+       int err;
        snd_pcm_sframes_t pdelay, cdelay;
 
        assert(pcm);
        assert(delayp);
+       err = sndo_pcm_check_setup(pcm);
+       if (err < 0)
+               return err;
        if (pcm->playback)
                err = snd_pcm_avail_update(pcm->playback);
        if (err >= 0 && pcm->capture)
@@ -327,6 +340,27 @@
 }
 
 /**
+ * \brief Obtain transfer block size (aka period size)
+ * \param pcm ordinary PCM handle
+ * \param tblock Returned transfer block size in frames
+ * \return 0 on success otherwise a negative error code
+ *
+ * All read/write operations must use this transfer block.
+ */
+int sndo_pcm_transfer_block(sndo_pcm_t *pcm, snd_pcm_uframes_t *tblock)
+{
+       int err;
+
+       assert(pcm);
+       assert(tblock);
+       err = sndo_pcm_check_setup(pcm);
+       if (err < 0)
+               return err;
+       *tblock = pcm->transfer_block;
+       return 0;
+}
+
+/**
  * \brief Resume from suspend, no samples are lost
  * \param pcm ordinary PCM handle
  * \return 0 on success otherwise a negative error code
@@ -412,7 +446,11 @@
 int sndo_pcm_param_reset(sndo_pcm_t *pcm)
 {
        int err;
-       
+
+       err = sndo_pcm_drain(pcm);
+       if (err < 0)
+               return err;
+       pcm->initialized = 0;
        if (pcm->playback) {
                err = snd_pcm_hw_params_any(pcm->playback, pcm->p_hw_params);
                if (err < 0)
@@ -577,6 +615,9 @@
  * \param latency requested latency
  * \param used_latency returned real latency in frames
  * \return 0 on success otherwise a negative error code
+ *
+ * Note that the result value is only approximate and for one direction.
+ * For example, hardware FIFOs are not counted etc.
  */
 int sndo_pcm_param_latency(sndo_pcm_t *pcm, enum sndo_pcm_latency_type latency, 
snd_pcm_uframes_t *used_latency)
 {
@@ -585,7 +626,13 @@
        err = sndo_pcm_setup(pcm);
        if (err < 0)
                return err;
-       return -EIO;
+       pcm->latency = latency;
+       err = sndo_pcm_check_setup(pcm);
+       if (err < 0)
+               return err;
+       if (used_latency)
+               *used_latency = pcm->ring_size;
+       return 0;
 }
 
 /**
@@ -601,7 +648,8 @@
        err = sndo_pcm_setup(pcm);
        if (err < 0)
                return err;
-       return -EIO;
+       pcm->xrun = xrun;
+       return 0;
 }
 
 /**
@@ -622,7 +670,12 @@
        err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
        if (err < 0)
                return err;
-       *ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->p_offset * 
pcm->samplebytes;
+       if (*frames < pcm->transfer_block) {
+               frames = 0;
+       } else {
+               *frames -= *frames % pcm->transfer_block;
+               *ring_buffer = (char *)areas->addr + (areas->first / 8) + 
pcm->p_offset * pcm->samplebytes;
+       }
        return 0;
 }
 
@@ -634,6 +687,10 @@
  */
 snd_pcm_sframes_t sndo_pcm_pio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+       if (frames <= 0)
+               return -EINVAL;
+       if (frames % pcm->transfer_block)
+               return -EINVAL;
        return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
 }
 
@@ -656,8 +713,13 @@
        err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
        if (err < 0)
                return err;
-       for (ch = 0; ch < pcm->channels; ch++)
-               ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->p_offset * 
pcm->samplebytes;
+       if (*frames < pcm->transfer_block) {
+               frames = 0;
+       } else {
+               *frames -= *frames % pcm->transfer_block;
+               for (ch = 0; ch < pcm->channels; ch++)
+                       ring_buffer[ch] = areas->addr + (areas->first / 8) + 
pcm->p_offset * pcm->samplebytes;
+       }
        return 0;
 }
 
@@ -669,6 +731,10 @@
  */
 snd_pcm_sframes_t sndo_pcm_pio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+       if (frames <= 0)
+               return -EINVAL;
+       if (frames % pcm->transfer_block)
+               return -EINVAL;
        return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
 }
 
@@ -690,7 +756,12 @@
        err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
        if (err < 0)
                return err;
-       *ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->c_offset * 
pcm->samplebytes;
+       if (*frames < pcm->transfer_block) {
+               frames = 0;
+       } else {
+               *frames -= *frames % pcm->transfer_block;
+               *ring_buffer = (char *)areas->addr + (areas->first / 8) + 
pcm->c_offset * pcm->samplebytes;
+       }
        return 0;
 }
 
@@ -702,6 +773,10 @@
  */
 snd_pcm_sframes_t sndo_pcm_cio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+       if (frames <= 0)
+               return -EINVAL;
+       if (frames % pcm->transfer_block)
+               return -EINVAL;
        return snd_pcm_mmap_commit(pcm->capture, pcm->p_offset, frames);
 }
 
@@ -724,8 +799,13 @@
        err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
        if (err < 0)
                return err;
-       for (ch = 0; ch < pcm->channels; ch++)
-               ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->c_offset * 
pcm->samplebytes;
+       if (*frames < pcm->transfer_block) {
+               frames = 0;
+       } else {
+               *frames -= *frames % pcm->transfer_block;
+               for (ch = 0; ch < pcm->channels; ch++)
+                       ring_buffer[ch] = areas->addr + (areas->first / 8) + 
pcm->c_offset * pcm->samplebytes;
+       }
        return 0;
 }
 
@@ -737,6 +817,10 @@
  */
 snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+       if (frames <= 0)
+               return -EINVAL;
+       if (frames % pcm->transfer_block)
+               return -EINVAL;
        return snd_pcm_mmap_commit(pcm->capture, pcm->c_offset, frames);
 }
 
@@ -746,8 +830,11 @@
  
 static int sndo_pcm_setup(sndo_pcm_t *pcm)
 {
-       if (pcm->initialized)
-               return 0;
+       int err;
+
+       err = sndo_pcm_drain(pcm);
+       if (err < 0)
+               return err;
        if (!pcm->setting_up) {
                int err = sndo_pcm_param_reset(pcm);
                if (err < 0)
@@ -761,19 +848,56 @@
 {
        int err;
        snd_pcm_uframes_t boundary;
-       snd_pcm_uframes_t avail_min = 1; /* FIXME */
+       snd_pcm_uframes_t p_period_size = ~0UL, c_period_size = ~0UL;
+       snd_pcm_uframes_t p_buffer_size = ~0UL, c_buffer_size = ~0UL;
 
        if (pcm->playback) {
+               err = snd_pcm_hw_params(pcm->playback, pcm->p_hw_params);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_hw_params_get_period_size(pcm->p_hw_params, 
&p_period_size, NULL);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_hw_params_get_buffer_size(pcm->p_hw_params, 
&p_buffer_size);
+               if (err < 0)
+                       return err;
+       }
+       if (pcm->capture) {
+               err = snd_pcm_hw_params(pcm->capture, pcm->c_hw_params);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_hw_params_get_period_size(pcm->c_hw_params, 
&c_period_size, NULL);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_hw_params_get_buffer_size(pcm->c_hw_params, 
&c_buffer_size);
+               if (err < 0)
+                       return err;
+       }
+       if (p_period_size < c_period_size)
+               pcm->transfer_block = p_period_size;
+       else
+               pcm->transfer_block = c_period_size;
+       if (p_buffer_size < c_buffer_size)
+               pcm->ring_size = p_buffer_size;
+       else
+               pcm->ring_size = c_buffer_size;
+       if (pcm->playback) {
                err = snd_pcm_sw_params_get_boundary(pcm->p_sw_params, &boundary);
                if (err < 0)
                        return err;
-               err = snd_pcm_sw_params_set_start_threshold(pcm->capture, 
pcm->p_sw_params, boundary);
+               err = snd_pcm_sw_params_set_start_threshold(pcm->playback, 
pcm->p_sw_params, boundary);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_sw_params_set_stop_threshold(pcm->playback, 
pcm->p_sw_params, pcm->xrun == SNDO_PCM_XRUN_IGNORE ? boundary : pcm->ring_size);
                if (err < 0)
                        return err;
                err = snd_pcm_sw_params_set_xfer_align(pcm->playback, 
pcm->p_sw_params, 1);
                if (err < 0)
                        return err;
-               err = snd_pcm_sw_params_set_avail_min(pcm->playback, pcm->p_sw_params, 
avail_min);
+               err = snd_pcm_sw_params_set_avail_min(pcm->playback, pcm->p_sw_params, 
pcm->transfer_block);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_sw_params(pcm->playback, pcm->p_sw_params);
                if (err < 0)
                        return err;
        }
@@ -784,10 +908,16 @@
                err = snd_pcm_sw_params_set_start_threshold(pcm->capture, 
pcm->c_sw_params, boundary);
                if (err < 0)
                        return err;
+               err = snd_pcm_sw_params_set_stop_threshold(pcm->capture, 
pcm->c_sw_params, pcm->xrun == SNDO_PCM_XRUN_IGNORE ? boundary : pcm->ring_size);
+               if (err < 0)
+                       return err;
                err = snd_pcm_sw_params_set_xfer_align(pcm->capture, pcm->c_sw_params, 
1);
                if (err < 0)
                        return err;
-               err = snd_pcm_sw_params_set_avail_min(pcm->capture, pcm->c_sw_params, 
avail_min);
+               err = snd_pcm_sw_params_set_avail_min(pcm->capture, pcm->c_sw_params, 
pcm->transfer_block);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_sw_params(pcm->capture, pcm->c_sw_params);
                if (err < 0)
                        return err;
        }



-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to