Re: pcm_multi broken in alsa-lib - no duplex mode with jackd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



At Tue, 13 Mar 2007 10:05:06 +0100,
Simon Lewis wrote:
> 
> Dear Takashi
> 
> Can I use the two patchs with alsa-lib 1.0.13 ?

Might work, but don't try.  It simply increases another unknown
factors.  First try the latest HG version with the patch to confirm
that it works.  After that, try any version you like.

> If yes, please let me know the terminal commands assuming that I have
> already cd'ed into the unpacked alsa-lib folder.

	% patch -p1 -i this_patch

In doubt, wait until tomorrow, then grab the latest daily snapshot
tarball from 
	ftp://ftp.suse.com/pub/projects/alsa/snapshot/

which will include the all patches.


Takashi
> 
> 
> Takashi Iwai schrieb:
> > At Tue, 13 Mar 2007 00:46:52 +0100,
> > I wrote:
> >   
> >> At Sat, 10 Mar 2007 14:17:13 +0000,
> >> John Rigg wrote:
> >>     
> >>> On Fri, Mar 09, 2007 at 05:38:34PM +0100, Takashi Iwai wrote:
> >>>       
> >>>> At Thu, 8 Mar 2007 21:51:28 +0000,
> >>>> John Rigg wrote:
> >>>>         
> >>>>> On Thu, Mar 08, 2007 at 07:58:23PM +0100, Takashi Iwai wrote:
> >>>>>           
> >>>>>> At Thu, 08 Mar 2007 18:16:02 +0100,
> >>>>>> Simon Lewis wrote:
> >>>>>>             
> >>>>>>> Many JACK users have successfully used the following patch:
> >>>>>>>
> >>>>>>> http://www.sound-man.co.uk/linuxaudio/pcm_multi-patch
> >>>>>>>               
> >>>>>> Well, the patch is no real fix.  It's likely a workaround for JACK,
> >>>>>> though.  Someone has to take time to track down this bug more deeply.
> >>>>>>             
> >>>>> True, the patch is just a workaround for JACK. However, I would
> >>>>> argue that most users of pcm_multi are probably JACK users.
> >>>>>           
> >>>> No, multi plugin is used in many surround PCM definitions as default.
> >>>> It's pretty hidden, but multi streams are no rare case.
> >>>>         
> >>> I hadn't noticed that. Thanks for pointing it out (and thank you for
> >>> looking at this problem!)
> >>>
> >>>       
> >>>>> Surely adding code that breaks something for the majority of users (no
> >>>>> matter how correct that code is in isolation) is not a good thing.
> >>>>>           
> >>>> Sure.  However, this code addition was for bugfixes of major other use
> >>>> cases like above, IIRC.  The regression should be avoided and should
> >>>> be fixed.  But the point is, we (at least, I) haven't been enough
> >>>> informed, unfortunately (or simply burried in a big TODO list :)
> >>>>
> >>>> Now, let's back to the original problem:  Could someone give a pointer
> >>>> describing for this problem, or just explain a bit details here?
> >>>> I vaguely remember but not precisely at all now...
> >>>> I'm willing to dig down after knowing how I can reproduce the bug.
> >>>>         
> >>> To summarise, using multiple sound cards with pcm_multi and jackd
> >>> no longer works in duplex mode ever since extra linking code was
> >>> added to pcm_multi.c in alsa-lib-1.0.9rc1.
> >>>
> >>> Trying to start jackd in duplex fails with a poll timeout message.
> >>> It still works in playback-only or capture-only modes.
> >>> The lack of duplex operation makes overdubbing in a recording studio,
> >>> for example, impossible.
> >>>
> >>> A configuration which produces the problem with two ice1712 cards
> >>> set up as a 16 channel multi device is shown here:
> >>> http://www.sound-man.co.uk/linuxaudio/ice1712multi.html
> >>>
> >>> With the .asoundrc described in the above link the following
> >>> command fails with a poll timeout message:
> >>>
> >>> jackd -d alsa -P multi_playback -C multi_capture
> >>>
> >>> The following still work:
> >>> jackd -d alsa -P multi_playback
> >>> jackd -d alsa -C multi_capture
> >>>       
> >> OK, played a bit around this bug.  A temporary fix is attached below.
> >> It's applied to HG tree now, too.  Please give it a try.
> >>
> >> The real fix will come later...
> >>     
> >
> > More complete fix is below.  Apply after the previous patch.
> > (Or more easily use the HG version.)
> >
> >
> > Takashi
> >
> >
> > # HG changeset patch
> > # User tiwai
> > # Date 1173750753 -3600
> > # Node ID 4883f0ba21df769cea44345f35dcdd3b6214b8e7
> > # Parent  78c78fa6c41db913484d6e3cff2f1e31e5fc6075
> > 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.
> >
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm.c
> > --- a/src/pcm/pcm.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -6313,15 +6313,6 @@ snd_pcm_sframes_t snd_pcm_mmap_commit(sn
> >  }
> >  
> >  #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)
> >  {
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_dmix.c
> > --- a/src/pcm/pcm_dmix.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_dmix.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -757,8 +757,8 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_f
> >  	.rewind = snd_pcm_dmix_rewind,
> >  	.forward = snd_pcm_dmix_forward,
> >  	.resume = snd_pcm_direct_resume,
> > -	.link_fd = NULL,
> >  	.link = NULL,
> > +	.link_slaves = NULL,
> >  	.unlink = NULL,
> >  	.writei = snd_pcm_mmap_writei,
> >  	.writen = snd_pcm_mmap_writen,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_dshare.c
> > --- a/src/pcm/pcm_dshare.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_dshare.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -562,8 +562,8 @@ static snd_pcm_fast_ops_t snd_pcm_dshare
> >  	.rewind = snd_pcm_dshare_rewind,
> >  	.forward = snd_pcm_dshare_forward,
> >  	.resume = snd_pcm_direct_resume,
> > -	.link_fd = NULL,
> >  	.link = NULL,
> > +	.link_slaves = NULL,
> >  	.unlink = NULL,
> >  	.writei = snd_pcm_mmap_writei,
> >  	.writen = snd_pcm_mmap_writen,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_dsnoop.c
> > --- a/src/pcm/pcm_dsnoop.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_dsnoop.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -452,8 +452,8 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop
> >  	.rewind = snd_pcm_dsnoop_rewind,
> >  	.forward = snd_pcm_dsnoop_forward,
> >  	.resume = snd_pcm_direct_resume,
> > -	.link_fd = NULL,
> >  	.link = NULL,
> > +	.link_slaves = NULL,
> >  	.unlink = NULL,
> >  	.writei = snd_pcm_dsnoop_writei,
> >  	.writen = snd_pcm_dsnoop_writen,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_file.c
> > --- a/src/pcm/pcm_file.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_file.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -373,8 +373,8 @@ static snd_pcm_fast_ops_t snd_pcm_file_f
> >  	.rewind = snd_pcm_file_rewind,
> >  	.forward = snd_pcm_file_forward,
> >  	.resume = snd_pcm_generic_resume,
> > -	.link_fd = snd_pcm_generic_link_fd,
> >  	.link = snd_pcm_generic_link,
> > +	.link_slaves = snd_pcm_generic_link_slaves,
> >  	.unlink = snd_pcm_generic_unlink,
> >  	.writei = snd_pcm_file_writei,
> >  	.writen = snd_pcm_file_writen,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_generic.c
> > --- a/src/pcm/pcm_generic.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_generic.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -197,14 +197,6 @@ snd_pcm_sframes_t snd_pcm_generic_rewind
> >  	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)
> >  {
> >  	snd_pcm_generic_t *generic = pcm1->private_data;
> > @@ -213,44 +205,12 @@ int snd_pcm_generic_link(snd_pcm_t *pcm1
> >  	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_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
> > +{
> > +	snd_pcm_generic_t *generic = pcm->private_data;
> > +	if (generic->slave->fast_ops->link_slaves)
> > +		return generic->slave->fast_ops->link_slaves(generic->slave->fast_op_arg, master);
> > +	return -ENOSYS;
> >  }
> >  
> >  int snd_pcm_generic_unlink(snd_pcm_t *pcm)
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_generic.h
> > --- a/src/pcm/pcm_generic.h	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_generic.h	Tue Mar 13 02:52:33 2007 +0100
> > @@ -50,9 +50,8 @@ int snd_pcm_generic_delay(snd_pcm_t *pcm
> >  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_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_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master);
> >  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);
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_hooks.c
> > --- a/src/pcm/pcm_hooks.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_hooks.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -151,8 +151,8 @@ static snd_pcm_fast_ops_t snd_pcm_hooks_
> >  	.rewind = snd_pcm_generic_rewind,
> >  	.forward = snd_pcm_generic_forward,
> >  	.resume = snd_pcm_generic_resume,
> > -	.link_fd = snd_pcm_generic_link_fd,
> >  	.link = snd_pcm_generic_link,
> > +	.link_slaves = snd_pcm_generic_link_slaves,
> >  	.unlink = snd_pcm_generic_unlink,
> >  	.writei = snd_pcm_generic_writei,
> >  	.writen = snd_pcm_generic_writen,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_hw.c
> > --- a/src/pcm/pcm_hw.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_hw.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -686,41 +686,35 @@ static int snd_pcm_hw_resume(snd_pcm_t *
> >  	return 0;
> >  }
> >  
> > -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;
> > -
> > -	if (count < 1)
> > +static int hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
> > +{
> > +	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;
> > +}
> > +
> > +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;
> > -	*failed = NULL;
> > -	fds[0] = hw->fd;
> > -	return 1;
> > +	}
> > +	return hw_link(master, pcm);
> >  }
> >  
> >  static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
> >  {
> > -	snd_pcm_hw_t *hw = pcm1->private_data;
> > -	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 err;
> > -}
> > +	if (pcm2->type != SND_PCM_TYPE_HW) {
> > +		if (pcm2->fast_ops->link_slaves)
> > +			return pcm2->fast_ops->link_slaves(pcm2, pcm1);
> > +		return -ENOSYS;
> > +	}
> > +	return hw_link(pcm1, pcm2);
> > + }
> >  
> >  static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
> >  {
> > @@ -1045,8 +1039,8 @@ static snd_pcm_fast_ops_t snd_pcm_hw_fas
> >  	.rewind = snd_pcm_hw_rewind,
> >  	.forward = snd_pcm_hw_forward,
> >  	.resume = snd_pcm_hw_resume,
> > -	.link_fd = snd_pcm_hw_link_fd,
> >  	.link = snd_pcm_hw_link,
> > +	.link_slaves = snd_pcm_hw_link_slaves,
> >  	.unlink = snd_pcm_hw_unlink,
> >  	.writei = snd_pcm_hw_writei,
> >  	.writen = snd_pcm_hw_writen,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_ioplug.c
> > --- a/src/pcm/pcm_ioplug.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_ioplug.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -747,8 +747,8 @@ static snd_pcm_fast_ops_t snd_pcm_ioplug
> >  	.hwsync = snd_pcm_ioplug_hwsync,
> >  	.delay = snd_pcm_ioplug_delay,
> >  	.resume = snd_pcm_ioplug_resume,
> > -	.link_fd = NULL,
> >  	.link = NULL,
> > +	.link_slaves = NULL,
> >  	.unlink = NULL,
> >  	.rewind = snd_pcm_ioplug_rewind,
> >  	.forward = snd_pcm_ioplug_forward,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_local.h
> > --- a/src/pcm/pcm_local.h	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_local.h	Tue Mar 13 02:52:33 2007 +0100
> > @@ -152,8 +152,8 @@ typedef struct {
> >  	int (*hwsync)(snd_pcm_t *pcm);
> >  	int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
> >  	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_slaves)(snd_pcm_t *pcm, snd_pcm_t *master);
> >  	int (*unlink)(snd_pcm_t *pcm);
> >  	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);
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_multi.c
> > --- a/src/pcm/pcm_multi.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_multi.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -45,7 +45,7 @@ typedef struct {
> >  	snd_pcm_t *pcm;
> >  	unsigned int channels_count;
> >  	int close_slave;
> > -	int linked;
> > +	snd_pcm_t *linked;
> >  } snd_pcm_multi_slave_t;
> >  
> >  typedef struct {
> > @@ -57,7 +57,6 @@ 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;
> > @@ -314,6 +313,21 @@ static int snd_pcm_multi_hw_params_slave
> >  	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)
> >  {
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> > @@ -331,12 +345,7 @@ static int snd_pcm_multi_hw_params(snd_p
> >  			return err;
> >  		}
> >  	}
> > -	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);
> > -	}
> > +	reset_links(multi);
> >  	return 0;
> >  }
> >  
> > @@ -352,10 +361,10 @@ static int snd_pcm_multi_hw_free(snd_pcm
> >  			err = e;
> >  		if (!multi->slaves[i].linked)
> >  			continue;
> > -		multi->slaves[i].linked = 0;
> >  		e = snd_pcm_unlink(slave);
> >  		if (e < 0)
> >  			err = e;
> > +		multi->slaves[i].linked = NULL;
> >  	}
> >  	return err;
> >  }
> > @@ -421,7 +430,7 @@ static int snd_pcm_multi_prepare(snd_pcm
> >  static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
> >  {
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> > -	int err = 0;
> > +	int result = 0, err;
> >  	unsigned int i;
> >  	for (i = 0; i < multi->slaves_count; ++i) {
> >  		/* We call prepare to each slave even if it's linked.
> > @@ -429,75 +438,83 @@ static int snd_pcm_multi_prepare(snd_pcm
> >  		 */
> >  		err = snd_pcm_prepare(multi->slaves[i].pcm);
> >  		if (err < 0)
> > -			return err;
> > -	}
> > -	return err;
> > +			result = err;
> > +	}
> > +	return result;
> >  }
> >  
> >  static int snd_pcm_multi_reset(snd_pcm_t *pcm)
> >  {
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> > -	int err = 0;
> > +	int result = 0, err;
> >  	unsigned int i;
> >  	for (i = 0; i < multi->slaves_count; ++i) {
> >  		/* Reset each slave, as well as in prepare */
> >  		err = snd_pcm_reset(multi->slaves[i].pcm);
> > +		if (err < 0) 
> > +			result = err;
> > +	}
> > +	return result;
> > +}
> > +
> > +static int snd_pcm_multi_start(snd_pcm_t *pcm)
> > +{
> > +	snd_pcm_multi_t *multi = pcm->private_data;
> > +	int err = 0;
> > +	unsigned int i;
> > +	if (multi->slaves[0].linked)
> > +		return snd_pcm_start(multi->slaves[0].linked);
> > +	for (i = 0; i < multi->slaves_count; ++i) {
> > +		if (multi->slaves[i].linked)
> > +			continue;
> > +		err = snd_pcm_start(multi->slaves[i].pcm);
> >  		if (err < 0)
> >  			return err;
> >  	}
> >  	return err;
> >  }
> >  
> > -static int snd_pcm_multi_start(snd_pcm_t *pcm)
> > +static int snd_pcm_multi_drop(snd_pcm_t *pcm)
> >  {
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> >  	int err = 0;
> >  	unsigned int i;
> > +	if (multi->slaves[0].linked)
> > +		return snd_pcm_drop(multi->slaves[0].linked);
> >  	for (i = 0; i < multi->slaves_count; ++i) {
> >  		if (multi->slaves[i].linked)
> >  			continue;
> > -		err = snd_pcm_start(multi->slaves[i].pcm);
> > +		err = snd_pcm_drop(multi->slaves[i].pcm);
> >  		if (err < 0)
> >  			return err;
> >  	}
> >  	return err;
> >  }
> >  
> > -static int snd_pcm_multi_drop(snd_pcm_t *pcm)
> > +static int snd_pcm_multi_drain(snd_pcm_t *pcm)
> >  {
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> >  	int err = 0;
> >  	unsigned int i;
> > +	if (multi->slaves[0].linked)
> > +		return snd_pcm_drain(multi->slaves[0].linked);
> >  	for (i = 0; i < multi->slaves_count; ++i) {
> >  		if (multi->slaves[i].linked)
> >  			continue;
> > -		err = snd_pcm_drop(multi->slaves[i].pcm);
> > +		err = snd_pcm_drain(multi->slaves[i].pcm);
> >  		if (err < 0)
> >  			return err;
> >  	}
> >  	return err;
> >  }
> >  
> > -static int snd_pcm_multi_drain(snd_pcm_t *pcm)
> > +static int snd_pcm_multi_pause(snd_pcm_t *pcm, int enable)
> >  {
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> >  	int err = 0;
> >  	unsigned int i;
> > -	for (i = 0; i < multi->slaves_count; ++i) {
> > -		if (multi->slaves[i].linked)
> > -			continue;
> > -		err = snd_pcm_drain(multi->slaves[i].pcm);
> > -		if (err < 0)
> > -			return err;
> > -	}
> > -	return err;
> > -}
> > -
> > -static int snd_pcm_multi_pause(snd_pcm_t *pcm, int enable)
> > -{
> > -	snd_pcm_multi_t *multi = pcm->private_data;
> > -	int err = 0;
> > -	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) {
> >  		if (multi->slaves[i].linked)
> >  			continue;
> > @@ -587,6 +604,8 @@ static int snd_pcm_multi_resume(snd_pcm_
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> >  	int err = 0;
> >  	unsigned int i;
> > +	if (multi->slaves[0].linked)
> > +		return snd_pcm_resume(multi->slaves[0].linked);
> >  	for (i = 0; i < multi->slaves_count; ++i) {
> >  		if (multi->slaves[i].linked)
> >  			continue;
> > @@ -597,46 +616,42 @@ static int snd_pcm_multi_resume(snd_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))
> > +static int snd_pcm_multi_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
> >  { 
> >  	snd_pcm_multi_t *multi = pcm->private_data;
> > -	unsigned int i;
> > -
> > -	if (count < (int)multi->slaves_count)
> > -		return -ENOMEM;
> > +	unsigned int i, j;
> > +	int err;
> > +
> > +	for (i = 0; i < multi->slaves_count; ++i) {
> > +		snd_pcm_unlink(multi->slaves[i].pcm);
> > +		multi->slaves[i].linked = NULL;
> > +		err = snd_pcm_link(master, multi->slaves[i].pcm);
> > +		if (err < 0) {
> > +			reset_links(multi);
> > +			return err;
> > +		}
> > +		multi->slaves[i].linked = master;
> > +	}
> > +	return 0;
> > +}
> > +
> > +static int snd_pcm_multi_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
> > +{
> > +	snd_pcm_multi_t *multi = pcm1->private_data;
> > +	if (multi->slaves[0].pcm->fast_ops->link)
> > +		return multi->slaves[0].pcm->fast_ops->link(multi->slaves[0].pcm, pcm2);
> > +	return -ENOSYS;
> > +}
> > +
> > +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);
> > -		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)
> > -{
> > -	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;
> > +			snd_pcm_unlink(multi->slaves[i].linked);
> > +		multi->slaves[0].linked = NULL;
> >  	}
> >  	return 0;
> >  }
> > @@ -727,8 +742,8 @@ static snd_pcm_fast_ops_t snd_pcm_multi_
> >  	.rewind = snd_pcm_multi_rewind,
> >  	.forward = snd_pcm_multi_forward,
> >  	.resume = snd_pcm_multi_resume,
> > -	.link_fd = snd_pcm_multi_link_fd,
> > -	.link = snd_pcm_generic_link2,
> > +	.link = snd_pcm_multi_link,
> > +	.link_slaves = snd_pcm_multi_link_slaves,
> >  	.unlink = snd_pcm_multi_unlink,
> >  	.avail_update = snd_pcm_multi_avail_update,
> >  	.mmap_commit = snd_pcm_multi_mmap_commit,
> > diff -r 78c78fa6c41d -r 4883f0ba21df src/pcm/pcm_plugin.c
> > --- a/src/pcm/pcm_plugin.c	Tue Mar 13 00:40:22 2007 +0100
> > +++ b/src/pcm/pcm_plugin.c	Tue Mar 13 02:52:33 2007 +0100
> > @@ -566,8 +566,8 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_o
> >  	.rewind = snd_pcm_plugin_rewind,
> >  	.forward = snd_pcm_plugin_forward,
> >  	.resume = snd_pcm_generic_resume,
> > -	.link_fd = snd_pcm_generic_link_fd,
> >  	.link = snd_pcm_generic_link,
> > +	.link_slaves = snd_pcm_generic_link_slaves,
> >  	.unlink = snd_pcm_generic_unlink,
> >  	.writei = snd_pcm_plugin_writei,
> >  	.writen = snd_pcm_plugin_writen,
> >
> > -------------------------------------------------------------------------
> > Take Surveys. Earn Cash. Influence the Future of IT
> > Join SourceForge.net's Techsay panel and you'll get the chance to share your
> > opinions on IT & business topics through brief surveys-and earn cash
> > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> > _______________________________________________
> > Alsa-devel mailing list
> > Alsa-devel@xxxxxxxxxxxxxxxxxxxxx
> > https://lists.sourceforge.net/lists/listinfo/alsa-devel
> >
> >
> >   
> 

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux