mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-27 01:40:09 -05:00
More better fix for linked start/stop
Instead of link_fd, more generic callback link_slaves is introduced. This is called for linking the slave streams as the source to the given master stream.
This commit is contained in:
parent
1753ae794f
commit
8048321c76
13 changed files with 93 additions and 134 deletions
|
|
@ -6314,15 +6314,6 @@ snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm,
|
||||||
|
|
||||||
#ifndef DOC_HIDDEN
|
#ifndef DOC_HIDDEN
|
||||||
|
|
||||||
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, fds, count, failed);
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _snd_pcm_poll_descriptor(snd_pcm_t *pcm)
|
int _snd_pcm_poll_descriptor(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
assert(pcm);
|
assert(pcm);
|
||||||
|
|
|
||||||
|
|
@ -757,8 +757,8 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = {
|
||||||
.rewind = snd_pcm_dmix_rewind,
|
.rewind = snd_pcm_dmix_rewind,
|
||||||
.forward = snd_pcm_dmix_forward,
|
.forward = snd_pcm_dmix_forward,
|
||||||
.resume = snd_pcm_direct_resume,
|
.resume = snd_pcm_direct_resume,
|
||||||
.link_fd = NULL,
|
|
||||||
.link = NULL,
|
.link = NULL,
|
||||||
|
.link_slaves = NULL,
|
||||||
.unlink = NULL,
|
.unlink = NULL,
|
||||||
.writei = snd_pcm_mmap_writei,
|
.writei = snd_pcm_mmap_writei,
|
||||||
.writen = snd_pcm_mmap_writen,
|
.writen = snd_pcm_mmap_writen,
|
||||||
|
|
|
||||||
|
|
@ -562,8 +562,8 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = {
|
||||||
.rewind = snd_pcm_dshare_rewind,
|
.rewind = snd_pcm_dshare_rewind,
|
||||||
.forward = snd_pcm_dshare_forward,
|
.forward = snd_pcm_dshare_forward,
|
||||||
.resume = snd_pcm_direct_resume,
|
.resume = snd_pcm_direct_resume,
|
||||||
.link_fd = NULL,
|
|
||||||
.link = NULL,
|
.link = NULL,
|
||||||
|
.link_slaves = NULL,
|
||||||
.unlink = NULL,
|
.unlink = NULL,
|
||||||
.writei = snd_pcm_mmap_writei,
|
.writei = snd_pcm_mmap_writei,
|
||||||
.writen = snd_pcm_mmap_writen,
|
.writen = snd_pcm_mmap_writen,
|
||||||
|
|
|
||||||
|
|
@ -452,8 +452,8 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
|
||||||
.rewind = snd_pcm_dsnoop_rewind,
|
.rewind = snd_pcm_dsnoop_rewind,
|
||||||
.forward = snd_pcm_dsnoop_forward,
|
.forward = snd_pcm_dsnoop_forward,
|
||||||
.resume = snd_pcm_direct_resume,
|
.resume = snd_pcm_direct_resume,
|
||||||
.link_fd = NULL,
|
|
||||||
.link = NULL,
|
.link = NULL,
|
||||||
|
.link_slaves = NULL,
|
||||||
.unlink = NULL,
|
.unlink = NULL,
|
||||||
.writei = snd_pcm_dsnoop_writei,
|
.writei = snd_pcm_dsnoop_writei,
|
||||||
.writen = snd_pcm_dsnoop_writen,
|
.writen = snd_pcm_dsnoop_writen,
|
||||||
|
|
|
||||||
|
|
@ -373,8 +373,8 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
||||||
.rewind = snd_pcm_file_rewind,
|
.rewind = snd_pcm_file_rewind,
|
||||||
.forward = snd_pcm_file_forward,
|
.forward = snd_pcm_file_forward,
|
||||||
.resume = snd_pcm_generic_resume,
|
.resume = snd_pcm_generic_resume,
|
||||||
.link_fd = snd_pcm_generic_link_fd,
|
|
||||||
.link = snd_pcm_generic_link,
|
.link = snd_pcm_generic_link,
|
||||||
|
.link_slaves = snd_pcm_generic_link_slaves,
|
||||||
.unlink = snd_pcm_generic_unlink,
|
.unlink = snd_pcm_generic_unlink,
|
||||||
.writei = snd_pcm_file_writei,
|
.writei = snd_pcm_file_writei,
|
||||||
.writen = snd_pcm_file_writen,
|
.writen = snd_pcm_file_writen,
|
||||||
|
|
|
||||||
|
|
@ -197,14 +197,6 @@ snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frame
|
||||||
return snd_pcm_rewind(generic->slave, frames);
|
return snd_pcm_rewind(generic->slave, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
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, fds, count, failed);
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
||||||
{
|
{
|
||||||
snd_pcm_generic_t *generic = pcm1->private_data;
|
snd_pcm_generic_t *generic = pcm1->private_data;
|
||||||
|
|
@ -213,44 +205,12 @@ int snd_pcm_generic_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_generic_link2(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
int snd_pcm_generic_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
|
||||||
{
|
{
|
||||||
int fds1[16], fds2[16];
|
snd_pcm_generic_t *generic = pcm->private_data;
|
||||||
int (*failed1)(snd_pcm_t *, int) = NULL;
|
if (generic->slave->fast_ops->link_slaves)
|
||||||
int (*failed2)(snd_pcm_t *, int) = NULL;
|
return generic->slave->fast_ops->link_slaves(generic->slave->fast_op_arg, master);
|
||||||
int count1 = _snd_pcm_link_descriptors(pcm1, fds1, 16, &failed1);
|
return -ENOSYS;
|
||||||
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)
|
int snd_pcm_generic_unlink(snd_pcm_t *pcm)
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,8 @@ int snd_pcm_generic_resume(snd_pcm_t *pcm);
|
||||||
int snd_pcm_generic_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
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_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);
|
snd_pcm_sframes_t snd_pcm_generic_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||||
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_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_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master);
|
||||||
int snd_pcm_generic_unlink(snd_pcm_t *pcm);
|
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_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);
|
snd_pcm_sframes_t snd_pcm_generic_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,8 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
|
||||||
.rewind = snd_pcm_generic_rewind,
|
.rewind = snd_pcm_generic_rewind,
|
||||||
.forward = snd_pcm_generic_forward,
|
.forward = snd_pcm_generic_forward,
|
||||||
.resume = snd_pcm_generic_resume,
|
.resume = snd_pcm_generic_resume,
|
||||||
.link_fd = snd_pcm_generic_link_fd,
|
|
||||||
.link = snd_pcm_generic_link,
|
.link = snd_pcm_generic_link,
|
||||||
|
.link_slaves = snd_pcm_generic_link_slaves,
|
||||||
.unlink = snd_pcm_generic_unlink,
|
.unlink = snd_pcm_generic_unlink,
|
||||||
.writei = snd_pcm_generic_writei,
|
.writei = snd_pcm_generic_writei,
|
||||||
.writen = snd_pcm_generic_writen,
|
.writen = snd_pcm_generic_writen,
|
||||||
|
|
|
||||||
|
|
@ -686,41 +686,35 @@ static int snd_pcm_hw_resume(snd_pcm_t *pcm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_link_fd(snd_pcm_t *pcm, int *fds, int count, int (**failed)(snd_pcm_t *, int))
|
static int hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_t *hw = pcm->private_data;
|
snd_pcm_hw_t *hw1 = pcm1->private_data;
|
||||||
|
snd_pcm_hw_t *hw2 = pcm2->private_data;
|
||||||
|
if (ioctl(hw1->fd, SNDRV_PCM_IOCTL_LINK, hw2->fd) < 0) {
|
||||||
|
SYSMSG("SNDRV_PCM_IOCTL_LINK failed");
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (count < 1)
|
static int snd_pcm_hw_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
|
||||||
|
{
|
||||||
|
if (master->type != SND_PCM_TYPE_HW) {
|
||||||
|
SYSMSG("Invalid type for SNDRV_PCM_IOCTL_LINK");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
*failed = NULL;
|
}
|
||||||
fds[0] = hw->fd;
|
return hw_link(master, pcm);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_t *hw = pcm1->private_data;
|
if (pcm2->type != SND_PCM_TYPE_HW) {
|
||||||
int fds[16];
|
if (pcm2->fast_ops->link_slaves)
|
||||||
int (*failed)(snd_pcm_t *, int) = NULL;
|
return pcm2->fast_ops->link_slaves(pcm2, pcm1);
|
||||||
int count = _snd_pcm_link_descriptors(pcm2, fds, 16, &failed);
|
return -ENOSYS;
|
||||||
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 err;
|
return hw_link(pcm1, pcm2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
|
static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
|
|
@ -1045,8 +1039,8 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
|
||||||
.rewind = snd_pcm_hw_rewind,
|
.rewind = snd_pcm_hw_rewind,
|
||||||
.forward = snd_pcm_hw_forward,
|
.forward = snd_pcm_hw_forward,
|
||||||
.resume = snd_pcm_hw_resume,
|
.resume = snd_pcm_hw_resume,
|
||||||
.link_fd = snd_pcm_hw_link_fd,
|
|
||||||
.link = snd_pcm_hw_link,
|
.link = snd_pcm_hw_link,
|
||||||
|
.link_slaves = snd_pcm_hw_link_slaves,
|
||||||
.unlink = snd_pcm_hw_unlink,
|
.unlink = snd_pcm_hw_unlink,
|
||||||
.writei = snd_pcm_hw_writei,
|
.writei = snd_pcm_hw_writei,
|
||||||
.writen = snd_pcm_hw_writen,
|
.writen = snd_pcm_hw_writen,
|
||||||
|
|
|
||||||
|
|
@ -747,8 +747,8 @@ static snd_pcm_fast_ops_t snd_pcm_ioplug_fast_ops = {
|
||||||
.hwsync = snd_pcm_ioplug_hwsync,
|
.hwsync = snd_pcm_ioplug_hwsync,
|
||||||
.delay = snd_pcm_ioplug_delay,
|
.delay = snd_pcm_ioplug_delay,
|
||||||
.resume = snd_pcm_ioplug_resume,
|
.resume = snd_pcm_ioplug_resume,
|
||||||
.link_fd = NULL,
|
|
||||||
.link = NULL,
|
.link = NULL,
|
||||||
|
.link_slaves = NULL,
|
||||||
.unlink = NULL,
|
.unlink = NULL,
|
||||||
.rewind = snd_pcm_ioplug_rewind,
|
.rewind = snd_pcm_ioplug_rewind,
|
||||||
.forward = snd_pcm_ioplug_forward,
|
.forward = snd_pcm_ioplug_forward,
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,8 @@ typedef struct {
|
||||||
int (*hwsync)(snd_pcm_t *pcm);
|
int (*hwsync)(snd_pcm_t *pcm);
|
||||||
int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
||||||
int (*resume)(snd_pcm_t *pcm);
|
int (*resume)(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 (*link)(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
|
||||||
|
int (*link_slaves)(snd_pcm_t *pcm, snd_pcm_t *master);
|
||||||
int (*unlink)(snd_pcm_t *pcm);
|
int (*unlink)(snd_pcm_t *pcm);
|
||||||
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||||
snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
snd_pcm_sframes_t (*forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ typedef struct {
|
||||||
snd_pcm_t *pcm;
|
snd_pcm_t *pcm;
|
||||||
unsigned int channels_count;
|
unsigned int channels_count;
|
||||||
int close_slave;
|
int close_slave;
|
||||||
int linked;
|
snd_pcm_t *linked;
|
||||||
} snd_pcm_multi_slave_t;
|
} snd_pcm_multi_slave_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -57,7 +57,6 @@ typedef struct {
|
||||||
unsigned int slaves_count;
|
unsigned int slaves_count;
|
||||||
unsigned int master_slave;
|
unsigned int master_slave;
|
||||||
snd_pcm_multi_slave_t *slaves;
|
snd_pcm_multi_slave_t *slaves;
|
||||||
int slave_link_master;
|
|
||||||
unsigned int channels_count;
|
unsigned int channels_count;
|
||||||
snd_pcm_multi_channel_t *channels;
|
snd_pcm_multi_channel_t *channels;
|
||||||
} snd_pcm_multi_t;
|
} snd_pcm_multi_t;
|
||||||
|
|
@ -314,6 +313,21 @@ static int snd_pcm_multi_hw_params_slave(snd_pcm_t *pcm,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_links(snd_pcm_multi_t *multi)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
|
if (multi->slaves[i].linked)
|
||||||
|
snd_pcm_unlink(multi->slaves[i].linked);
|
||||||
|
multi->slaves[0].linked = NULL;
|
||||||
|
if (! i)
|
||||||
|
continue;
|
||||||
|
if (snd_pcm_link(multi->slaves[0].pcm, multi->slaves[i].pcm) >= 0)
|
||||||
|
multi->slaves[i].linked = multi->slaves[0].pcm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
|
|
@ -331,12 +345,7 @@ static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
multi->slaves[0].linked = 0;
|
reset_links(multi);
|
||||||
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);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,10 +361,10 @@ static int snd_pcm_multi_hw_free(snd_pcm_t *pcm)
|
||||||
err = e;
|
err = e;
|
||||||
if (!multi->slaves[i].linked)
|
if (!multi->slaves[i].linked)
|
||||||
continue;
|
continue;
|
||||||
multi->slaves[i].linked = 0;
|
|
||||||
e = snd_pcm_unlink(slave);
|
e = snd_pcm_unlink(slave);
|
||||||
if (e < 0)
|
if (e < 0)
|
||||||
err = e;
|
err = e;
|
||||||
|
multi->slaves[i].linked = NULL;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +430,7 @@ static snd_pcm_sframes_t snd_pcm_multi_avail_update(snd_pcm_t *pcm)
|
||||||
static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
|
static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int result = 0, err;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
/* We call prepare to each slave even if it's linked.
|
/* We call prepare to each slave even if it's linked.
|
||||||
|
|
@ -429,23 +438,23 @@ static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
|
||||||
*/
|
*/
|
||||||
err = snd_pcm_prepare(multi->slaves[i].pcm);
|
err = snd_pcm_prepare(multi->slaves[i].pcm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
result = err;
|
||||||
}
|
}
|
||||||
return err;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_reset(snd_pcm_t *pcm)
|
static int snd_pcm_multi_reset(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int result = 0, err;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
/* Reset each slave, as well as in prepare */
|
/* Reset each slave, as well as in prepare */
|
||||||
err = snd_pcm_reset(multi->slaves[i].pcm);
|
err = snd_pcm_reset(multi->slaves[i].pcm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
result = err;
|
||||||
}
|
}
|
||||||
return err;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_start(snd_pcm_t *pcm)
|
static int snd_pcm_multi_start(snd_pcm_t *pcm)
|
||||||
|
|
@ -453,6 +462,8 @@ static int snd_pcm_multi_start(snd_pcm_t *pcm)
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
if (multi->slaves[0].linked)
|
||||||
|
return snd_pcm_start(multi->slaves[0].linked);
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (multi->slaves[i].linked)
|
if (multi->slaves[i].linked)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -468,6 +479,8 @@ static int snd_pcm_multi_drop(snd_pcm_t *pcm)
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
if (multi->slaves[0].linked)
|
||||||
|
return snd_pcm_drop(multi->slaves[0].linked);
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (multi->slaves[i].linked)
|
if (multi->slaves[i].linked)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -483,6 +496,8 @@ static int snd_pcm_multi_drain(snd_pcm_t *pcm)
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
if (multi->slaves[0].linked)
|
||||||
|
return snd_pcm_drain(multi->slaves[0].linked);
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (multi->slaves[i].linked)
|
if (multi->slaves[i].linked)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -498,6 +513,8 @@ static int snd_pcm_multi_pause(snd_pcm_t *pcm, int enable)
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
if (multi->slaves[0].linked)
|
||||||
|
return snd_pcm_pause(multi->slaves[0].linked, enable);
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (multi->slaves[i].linked)
|
if (multi->slaves[i].linked)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -587,6 +604,8 @@ static int snd_pcm_multi_resume(snd_pcm_t *pcm)
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
if (multi->slaves[0].linked)
|
||||||
|
return snd_pcm_resume(multi->slaves[0].linked);
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (multi->slaves[i].linked)
|
if (multi->slaves[i].linked)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -597,35 +616,31 @@ static int snd_pcm_multi_resume(snd_pcm_t *pcm)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_link_fd_failed(snd_pcm_t *pcm, int fd)
|
static int snd_pcm_multi_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm->private_data;
|
||||||
unsigned int i;
|
unsigned int i, j;
|
||||||
|
int err;
|
||||||
|
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (_snd_pcm_link_descriptor(multi->slaves[i].pcm) != fd)
|
snd_pcm_unlink(multi->slaves[i].pcm);
|
||||||
continue;
|
multi->slaves[i].linked = NULL;
|
||||||
multi->slaves[i].linked = 0;
|
err = snd_pcm_link(master, multi->slaves[i].pcm);
|
||||||
|
if (err < 0) {
|
||||||
|
reset_links(multi);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
multi->slaves[i].linked = master;
|
||||||
}
|
}
|
||||||
return 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))
|
static int snd_pcm_multi_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private_data;
|
snd_pcm_multi_t *multi = pcm1->private_data;
|
||||||
unsigned int i;
|
if (multi->slaves[0].pcm->fast_ops->link)
|
||||||
|
return multi->slaves[0].pcm->fast_ops->link(multi->slaves[0].pcm, pcm2);
|
||||||
if (count < (int)multi->slaves_count)
|
return -ENOSYS;
|
||||||
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);
|
|
||||||
if (i > 0)
|
|
||||||
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)
|
static int snd_pcm_multi_unlink(snd_pcm_t *pcm)
|
||||||
|
|
@ -635,8 +650,8 @@ static int snd_pcm_multi_unlink(snd_pcm_t *pcm)
|
||||||
|
|
||||||
for (i = 0; i < multi->slaves_count; ++i) {
|
for (i = 0; i < multi->slaves_count; ++i) {
|
||||||
if (multi->slaves[i].linked)
|
if (multi->slaves[i].linked)
|
||||||
snd_pcm_unlink(multi->slaves[i].pcm);
|
snd_pcm_unlink(multi->slaves[i].linked);
|
||||||
multi->slaves[i].linked = 0;
|
multi->slaves[0].linked = NULL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -727,8 +742,8 @@ static snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
|
||||||
.rewind = snd_pcm_multi_rewind,
|
.rewind = snd_pcm_multi_rewind,
|
||||||
.forward = snd_pcm_multi_forward,
|
.forward = snd_pcm_multi_forward,
|
||||||
.resume = snd_pcm_multi_resume,
|
.resume = snd_pcm_multi_resume,
|
||||||
.link_fd = snd_pcm_multi_link_fd,
|
.link = snd_pcm_multi_link,
|
||||||
.link = snd_pcm_generic_link2,
|
.link_slaves = snd_pcm_multi_link_slaves,
|
||||||
.unlink = snd_pcm_multi_unlink,
|
.unlink = snd_pcm_multi_unlink,
|
||||||
.avail_update = snd_pcm_multi_avail_update,
|
.avail_update = snd_pcm_multi_avail_update,
|
||||||
.mmap_commit = snd_pcm_multi_mmap_commit,
|
.mmap_commit = snd_pcm_multi_mmap_commit,
|
||||||
|
|
|
||||||
|
|
@ -566,8 +566,8 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
|
||||||
.rewind = snd_pcm_plugin_rewind,
|
.rewind = snd_pcm_plugin_rewind,
|
||||||
.forward = snd_pcm_plugin_forward,
|
.forward = snd_pcm_plugin_forward,
|
||||||
.resume = snd_pcm_generic_resume,
|
.resume = snd_pcm_generic_resume,
|
||||||
.link_fd = snd_pcm_generic_link_fd,
|
|
||||||
.link = snd_pcm_generic_link,
|
.link = snd_pcm_generic_link,
|
||||||
|
.link_slaves = snd_pcm_generic_link_slaves,
|
||||||
.unlink = snd_pcm_generic_unlink,
|
.unlink = snd_pcm_generic_unlink,
|
||||||
.writei = snd_pcm_plugin_writei,
|
.writei = snd_pcm_plugin_writei,
|
||||||
.writen = snd_pcm_plugin_writen,
|
.writen = snd_pcm_plugin_writen,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue