]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Added snd_pcm_hwptr() and enhanced snd_pcm_mmap_begin() for no xrun mode.
authorJaroslav Kysela <perex@perex.cz>
Sat, 22 Feb 2003 10:19:53 +0000 (10:19 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sat, 22 Feb 2003 10:19:53 +0000 (10:19 +0000)
17 files changed:
aserver/aserver.c
include/aserver.h
include/pcm.h
src/Versions
src/pcm/pcm.c
src/pcm/pcm_dmix.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_jack.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_multi.c
src/pcm/pcm_null.c
src/pcm/pcm_plugin.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c

index 60af87bfcb51f7485c5178f5c40ebd25a055abb0..a6b4a4e2ba6a16e2b9202c2f93e1d936690dbdd8 100644 (file)
@@ -471,6 +471,9 @@ 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;
index 0a2dfbeb2b97fc6e039fb040041ebcc418ef4924..c6e9f957cb8d47eb174dd3a3bfc5a4ff57912021 100644 (file)
@@ -50,6 +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)
 
 typedef struct {
        snd_pcm_uframes_t ptr;
@@ -73,6 +74,9 @@ 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;
index eb7a91b8f2c14840ca34800656959f6245f9af88..0ea5012c1d75cffa9927634a8443c151daeeda3f 100644 (file)
@@ -410,6 +410,7 @@ 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_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);
index 64cab9a96cea89108d7ef696364f64682cca4e43..6abc98e4db27b9a99bbfe253dee312e85ba1794f 100644 (file)
@@ -6,6 +6,7 @@ ALSA_0.9 {
   local:
     *;
 };
+
 ALSA_0.9.0rc4 {
   global:
 
@@ -77,4 +78,11 @@ ALSA_0.9.0rc4 {
     snd_pcm_hw_params_set_tick_time_first;
     snd_pcm_hw_params_set_tick_time_last;
 
-}ALSA_0.9;
+} ALSA_0.9;
+
+ALSA_0.9.0rc8 {
+  global:
+
+    snd_pcm_hwptr;
+
+} ALSA_0.9.0rc4;
index 1b1daa44aa6c9caea1702b6333de03774eae55a0..9383346efeddec04f1d41e919f45a64c0e5eae92 100644 (file)
@@ -868,6 +868,30 @@ int snd_pcm_hwsync(snd_pcm_t *pcm)
        return pcm->fast_ops->hwsync(pcm->fast_op_arg);
 }
 
+/**
+ * \brief Return hardware pointer
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ *
+ * The hardware pointer is in range 0 ... (boundary - 1). It contains
+ * count_of_ring_buffer_crosses * buffer_size + offset in the ring buffer.
+ *
+ * Note this function does not return the real hardware pointer.
+ * 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)
+#else
+int snd_pcm_hwptr(snd_pcm_t *pcm, snd_pcm_uframes_t *hwptr)
+#endif
+{
+       assert(pcm);
+       assert(pcm->setup);
+       return pcm->fast_ops->hwptr(pcm->fast_op_arg, hwptr);
+}
+default_symbol_version(__snd_pcm_hwptr, snd_pcm_hwptr, ALSA_0.9.0rc8);
+
 /**
  * \brief Obtain delay for a running PCM handle
  * \param pcm PCM handle
@@ -5792,7 +5816,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 Returned mmap area offset in area steps (== frames)
+ * \param offset mmap area offset in area steps (== frames) (wanted on entry (see note), returned on exit)
  * \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit)
  * \return 0 on success otherwise a negative error code
  *
@@ -5805,6 +5829,9 @@ 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,
@@ -5817,12 +5844,18 @@ 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);
-       *offset = *pcm->appl.ptr % pcm->buffer_size;
+       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;
-       avail = snd_pcm_mmap_avail(pcm);
-       if (avail > pcm->buffer_size)
-               avail = pcm->buffer_size;
        if (f > avail)
                f = avail;
        if (f > cont)
index 5ab09a7a9960fc4e650439ff3b6516cdc11ea05b..ca322b894dc588aa1a890a339bfbbf63cffe5258 100644 (file)
@@ -954,7 +954,6 @@ static int snd_pcm_dmix_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
        snd_pcm_dmix_t *dmix = pcm->private_data;
        int err;
        
-       assert(pcm && delayp);
        switch(dmix->state) {
        case SNDRV_PCM_STATE_DRAINING:
        case SNDRV_PCM_STATE_RUNNING:
@@ -990,6 +989,25 @@ 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;
@@ -1206,6 +1224,7 @@ 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,
index e14217c88d2feef10113097750e3483fc16463d2..4ecb44aaefea6e964a4f40ffe64e440430905ecf 100644 (file)
@@ -168,6 +168,12 @@ 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;
@@ -366,6 +372,9 @@ 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);
 }
 
@@ -413,6 +422,7 @@ 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,
index 6f9cf98c7782e5041a1ca21f5606930f7a9d413e..c4cbd0a903ebe4e0a02498dab829365bf6de2642 100644 (file)
@@ -122,6 +122,12 @@ 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;
@@ -299,6 +305,7 @@ 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,
index d4b58b8ef120b49b4012941b98aad6331b1f7f49..b04bc55a16857a3d79ca826a58d8a23828631b34 100644 (file)
@@ -345,6 +345,9 @@ 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;
@@ -428,6 +431,23 @@ 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;
@@ -690,7 +710,7 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm)
 }
 
 static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
-                                               snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
+                                               snd_pcm_uframes_t offset,
                                                snd_pcm_uframes_t size)
 {
        snd_pcm_hw_t *hw = pcm->private_data;
@@ -698,6 +718,12 @@ 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);
@@ -793,6 +819,7 @@ 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,
index dc66dbdd8809a7d29e2a466d503c7c85313ad6fb..69625901d45122b50d20e536809e5bb67c4cf81c 100644 (file)
@@ -185,6 +185,24 @@ 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
@@ -593,6 +611,7 @@ 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,
index 5060b70294f48ca3da5594fc19c6d718176f7220..0866ca7b7d3b734ef2b3ede5499276e78d60640c 100644 (file)
@@ -147,6 +147,7 @@ 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);
@@ -549,6 +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_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);
 int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
index 0eb6a07ef3dc210bc1cd87c2cc51ce85f3be7c59..8d163b192202e5be649a34f51943cdf3441c9a29 100644 (file)
@@ -325,6 +325,12 @@ 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;
index 0be871650c103848b66516156ffc726cad85ba89..9373cdf1b9c7d8fc0bcb59fdc3bcff68732ddea0 100644 (file)
@@ -89,7 +89,7 @@ static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock
 static int snd_pcm_multi_async(snd_pcm_t *pcm, int sig, pid_t pid)
 {
        snd_pcm_multi_t *multi = pcm->private_data;
-       snd_pcm_t *slave_0 = multi->slaves[0].pcm;
+       snd_pcm_t *slave_0 = multi->slaves[multi->master_slave].pcm;
        return snd_pcm_async(slave_0, sig, pid);
 }
 
@@ -340,28 +340,35 @@ static int snd_pcm_multi_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
 static int snd_pcm_multi_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
 {
        snd_pcm_multi_t *multi = pcm->private_data;
-       snd_pcm_t *slave = multi->slaves[0].pcm;
+       snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
        return snd_pcm_status(slave, status);
 }
 
 static snd_pcm_state_t snd_pcm_multi_state(snd_pcm_t *pcm)
 {
        snd_pcm_multi_t *multi = pcm->private_data;
-       snd_pcm_t *slave = multi->slaves[0].pcm;
+       snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
        return snd_pcm_state(slave);
 }
 
 static int snd_pcm_multi_hwsync(snd_pcm_t *pcm)
 {
        snd_pcm_multi_t *multi = pcm->private_data;
-       snd_pcm_t *slave = multi->slaves[0].pcm;
+       snd_pcm_t *slave = multi->slaves[multi->master_slave].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;
-       snd_pcm_t *slave = multi->slaves[0].pcm;
+       snd_pcm_t *slave = multi->slaves[multi->master_slave].pcm;
        return snd_pcm_delay(slave, delayp);
 }
 
@@ -602,6 +609,7 @@ 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,
index a727f2b11f6b487c96681ddaff5010de3e4c75ad..239e91660fa62523155104750099fc433f713c8b 100644 (file)
@@ -105,6 +105,23 @@ 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;
@@ -312,6 +329,7 @@ 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,
index b01d30f8df186cab505483e9920eaec7bf745f57..9be8ffbb7a8e99daa2ba3597c15f469841c14c15 100644 (file)
@@ -199,6 +199,12 @@ 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;
@@ -626,6 +632,7 @@ 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,
index 7b82296ccd0f4fec09a27070b19ae57b76df3123..02290df760c30b335c93787bb3e65b4374a42e8a 100644 (file)
@@ -737,6 +737,36 @@ 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;
@@ -1234,6 +1264,7 @@ 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,
index 687863263636004821941f14ce15f4c644430430..65194d14230488d341be64f9c6f3097a131c041b 100644 (file)
@@ -451,6 +451,19 @@ 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;
@@ -619,6 +632,7 @@ 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,