]> git.alsa-project.org Git - alsa-lib.git/commitdiff
The stream linking problem for pcm_multi.c should be fixed now
authorJaroslav Kysela <perex@perex.cz>
Thu, 20 Jan 2005 18:37:13 +0000 (18:37 +0000)
committerJaroslav Kysela <perex@perex.cz>
Thu, 20 Jan 2005 18:37:13 +0000 (18:37 +0000)
- extended link_fd callback
- added snd_pcm_generic_link2()
- added _snd_pcm_link_descriptors()

src/pcm/pcm.c
src/pcm/pcm_generic.c
src/pcm/pcm_generic.h
src/pcm/pcm_hw.c
src/pcm/pcm_local.h
src/pcm/pcm_multi.c

index 13af39424f001e368827e49aa67aa922e6f3bd4a..a4df4698ae76b5972fd852ca0858955b0c63b8c1 100644 (file)
@@ -603,7 +603,6 @@ playback devices.
 #include <stdarg.h>
 #include <signal.h>
 #include <dlfcn.h>
-#include <sys/ioctl.h>
 #include <sys/poll.h>
 #include <sys/shm.h>
 #include <sys/mman.h>
@@ -6140,11 +6139,12 @@ snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm,
 
 #ifndef DOC_HIDDEN
 
-int _snd_pcm_link_descriptor(snd_pcm_t *pcm)
+int _snd_pcm_link_descriptors(snd_pcm_t *pcm, int *fds, int count,
+                             int (**failed)(snd_pcm_t *, int))
 {
        assert(pcm);
        if (pcm->fast_ops->link_fd)
-               return pcm->fast_ops->link_fd(pcm);
+               return pcm->fast_ops->link_fd(pcm, fds, count, failed);
        return -ENOSYS;
 }
 
index 44aae856b597d529e2edefee4a0a779ebad86b81..9cf2505fa25a754708f0f8d560c32e1ae7d8b818 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <sys/shm.h>
+#include <sys/ioctl.h>
 #include <limits.h>
 #include "pcm_local.h"
 #include "pcm_generic.h"
@@ -182,11 +183,11 @@ int snd_pcm_generic_poll_ask(snd_pcm_t *pcm)
        return 0;
 }
 
-int snd_pcm_generic_link_fd(snd_pcm_t *pcm)
+int snd_pcm_generic_link_fd(snd_pcm_t *pcm, int *fds, int count, int (**failed)(snd_pcm_t *, int))
 {
        snd_pcm_generic_t *generic = pcm->private_data;
        if (generic->slave->fast_ops->link_fd)
-               return generic->slave->fast_ops->link_fd(generic->slave->fast_op_arg);
+               return generic->slave->fast_ops->link_fd(generic->slave->fast_op_arg, fds, count, failed);
        return -ENOSYS;
 }
 
@@ -198,6 +199,46 @@ int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
        return -ENOSYS;
 }
 
+int snd_pcm_generic_link2(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
+{
+       int fds1[16], fds2[16];
+       int (*failed1)(snd_pcm_t *, int) = NULL;
+       int (*failed2)(snd_pcm_t *, int) = NULL;
+       int count1 = _snd_pcm_link_descriptors(pcm1, fds1, 16, &failed1);
+       int count2 = _snd_pcm_link_descriptors(pcm2, fds2, 16, &failed2);
+       int i, err = 0;
+
+       if (count1 < 0)
+               return count1;
+       if (count2 < 0)
+               return count2;
+       for (i = 1; i < count1; i++) {
+               if (fds1[i] < 0)
+                       return 0;
+               if (ioctl(fds1[0], SNDRV_PCM_IOCTL_LINK, fds1[i]) < 0) {
+                       if (failed1 != NULL) {
+                               err = failed1(pcm2, fds1[i]);
+                       } else {
+                               SYSMSG("SNDRV_PCM_IOCTL_LINK failed");
+                               err = -errno;
+                       }
+               }
+       }
+       for (i = 0; i < count2; i++) {
+               if (fds2[i] < 0)
+                       return 0;
+               if (ioctl(fds1[0], SNDRV_PCM_IOCTL_LINK, fds2[i]) < 0) {
+                       if (failed1 != NULL) {
+                               err = failed2(pcm2, fds2[i]);
+                       } else {
+                               SYSMSG("SNDRV_PCM_IOCTL_LINK failed");
+                               err = -errno;
+                       }
+               }
+       }
+       return err;
+}
+
 int snd_pcm_generic_unlink(snd_pcm_t *pcm)
 {
        snd_pcm_generic_t *generic = pcm->private_data;
index 202a9fb517ebebfc0586300303a7bf15ce98caa8..bb086c9dc24abe693bbc1a825ae68df215ef250c 100644 (file)
@@ -48,8 +48,9 @@ int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
 snd_pcm_sframes_t snd_pcm_generic_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
 snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
 int snd_pcm_generic_poll_ask(snd_pcm_t *pcm);
-int snd_pcm_generic_link_fd(snd_pcm_t *pcm); 
+int snd_pcm_generic_link_fd(snd_pcm_t *pcm, int *fds, int count, int (**failed)(snd_pcm_t *, int)); 
 int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
+int snd_pcm_generic_link2(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
 int snd_pcm_generic_unlink(snd_pcm_t *pcm);
 snd_pcm_sframes_t snd_pcm_generic_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
 snd_pcm_sframes_t snd_pcm_generic_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
index b3b028004acdd57376eac3637f3e4281119bd48c..499bd0ccfe95c02e8157ca5dd954a262391e7966 100644 (file)
@@ -656,25 +656,40 @@ static int snd_pcm_hw_resume(snd_pcm_t *pcm)
        return 0;
 }
 
-static int snd_pcm_hw_link_fd(snd_pcm_t *pcm)
+static int snd_pcm_hw_link_fd(snd_pcm_t *pcm, int *fds, int count, int (**failed)(snd_pcm_t *, int))
 {
        snd_pcm_hw_t *hw = pcm->private_data;
 
-       return hw->fd;
+       if (count < 1)
+               return -EINVAL;
+       *failed = NULL;
+       fds[0] = hw->fd;
+       return 1;
 }
 
 static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
 {
        snd_pcm_hw_t *hw = pcm1->private_data;
-       int fd2 = _snd_pcm_link_descriptor(pcm2);
-
-       if (fd2 < 0)
-               return -ENOSYS;
-       if (ioctl(hw->fd, SNDRV_PCM_IOCTL_LINK, fd2) < 0) {
-               SYSMSG("SNDRV_PCM_IOCTL_LINK failed");
-               return -errno;
+       int fds[16];
+       int (*failed)(snd_pcm_t *, int) = NULL;
+       int count = _snd_pcm_link_descriptors(pcm2, fds, 16, &failed);
+       int i, err = 0;
+
+       if (count < 0)
+               return count;
+       for (i = 0; i < count; i++) {
+               if (fds[i] < 0)
+                       return 0;
+               if (ioctl(hw->fd, SNDRV_PCM_IOCTL_LINK, fds[i]) < 0) {
+                       if (failed != NULL) {
+                               err = failed(pcm2, fds[i]);
+                       } else {
+                               SYSMSG("SNDRV_PCM_IOCTL_LINK failed");
+                               err = -errno;
+                       }
+               }
        }
-       return 0;
+       return err;
 }
 
 static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
index 5b9ef3b21a374950de1962aa6d9e9d14c33c072c..5d7569bb9b687183d060896c3275cc2c0c3ac5fb 100644 (file)
@@ -152,7 +152,7 @@ typedef struct {
        int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
        int (*resume)(snd_pcm_t *pcm);
        int (*poll_ask)(snd_pcm_t *pcm);
-       int (*link_fd)(snd_pcm_t *pcm);
+       int (*link_fd)(snd_pcm_t *pcm, int *fds, int count, int (**failed)(snd_pcm_t *, int));
        int (*link)(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
        int (*unlink)(snd_pcm_t *pcm);
        snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
@@ -265,7 +265,8 @@ snd_pcm_sframes_t snd_pcm_write_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t size);
 int snd_pcm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info);
 int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info, int shmid);
 int _snd_pcm_poll_descriptor(snd_pcm_t *pcm);
-int _snd_pcm_link_descriptor(snd_pcm_t *pcm);
+int _snd_pcm_link_descriptors(snd_pcm_t *pcm, int *fds, int size, int (**failed)(snd_pcm_t *, int));
+#define _snd_pcm_link_descriptor _snd_pcm_poll_descriptor /* FIXME */
 #define _snd_pcm_async_descriptor _snd_pcm_poll_descriptor /* FIXME */
 
 /* handle special error cases */
index b23b28617f752f0328cbe6d7466e9043423a5f34..ce3fc5ea50127b6fa4cdd22609386dd50725be34 100644 (file)
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <math.h>
 #include "pcm_local.h"
+#include "pcm_generic.h"
 
 #ifndef PIC
 /* entry for static linking */
@@ -56,6 +57,7 @@ typedef struct {
        unsigned int slaves_count;
        unsigned int master_slave;
        snd_pcm_multi_slave_t *slaves;
+       int slave_link_master;
        unsigned int channels_count;
        snd_pcm_multi_channel_t *channels;
 } snd_pcm_multi_t;
@@ -296,6 +298,7 @@ static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
                }
        }
        multi->slaves[0].linked = 0;
+       multi->slave_link_master = 0;
        for (i = 1; i < multi->slaves_count; ++i) {
                err = snd_pcm_link(multi->slaves[0].pcm, multi->slaves[i].pcm);
                multi->slaves[i].linked = (err >= 0);
@@ -577,6 +580,49 @@ static int snd_pcm_multi_poll_ask(snd_pcm_t *pcm)
        return err;
 }
 
+static int snd_pcm_multi_link_fd_failed(snd_pcm_t *pcm, int fd)
+{
+       snd_pcm_multi_t *multi = pcm->private_data;
+       unsigned int i;
+
+       for (i = 0; i < multi->slaves_count; ++i) {
+               if (_snd_pcm_link_descriptor(multi->slaves[i].pcm) != fd)
+                       continue;
+                multi->slaves[i].linked = 0;
+       }
+       return 0;
+}
+
+static int snd_pcm_multi_link_fd(snd_pcm_t *pcm, int *fds, int count, int (**failed)(snd_pcm_t *pcm, int fd))
+{ 
+       snd_pcm_multi_t *multi = pcm->private_data;
+       unsigned int i;
+
+       if (count < (int)multi->slaves_count)
+               return -ENOMEM;
+       for (i = 0; i < multi->slaves_count; ++i) {
+               if (multi->slaves[i].linked)
+                       snd_pcm_unlink(multi->slaves[i].pcm);
+               fds[i] = _snd_pcm_link_descriptor(multi->slaves[i].pcm);
+               multi->slaves[i].linked = 1;
+       }
+       *failed = snd_pcm_multi_link_fd_failed;
+       return multi->slaves_count;
+}
+
+static int snd_pcm_multi_unlink(snd_pcm_t *pcm)
+{
+       snd_pcm_multi_t *multi = pcm->private_data;
+       unsigned int i;
+
+       for (i = 0; i < multi->slaves_count; ++i) {
+               if (multi->slaves[i].linked)
+                       snd_pcm_unlink(multi->slaves[i].pcm);
+               multi->slaves[i].linked = 0;
+       }
+       return 0;
+}
+
 static snd_pcm_sframes_t snd_pcm_multi_mmap_commit(snd_pcm_t *pcm,
                                                   snd_pcm_uframes_t offset,
                                                   snd_pcm_uframes_t size)
@@ -664,6 +710,9 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
        .forward = snd_pcm_multi_forward,
        .resume = snd_pcm_multi_resume,
        .poll_ask = snd_pcm_multi_poll_ask,
+       .link_fd = snd_pcm_multi_link_fd,
+       .link = snd_pcm_generic_link2,
+       .unlink = snd_pcm_multi_unlink,
        .avail_update = snd_pcm_multi_avail_update,
        .mmap_commit = snd_pcm_multi_mmap_commit,
 };