[alsa-devel] Getting pcm_usb_stream plugin to know its limits. [Kind of SOLVED]

Michaël Cadilhac michael at cadilhac.name
Tue Jan 5 04:26:23 CET 2010


michael at cadilhac.name (Michaël Cadilhac) writes:

> So, my final saying is the following patch.  It fixes the segfault on
> stopping a non-started usb_stream, plus it adds the ability to set a
> period size and sound rate.  The latter offers a workaround for the
> second issue I came with (that the default values for period bytes, and
> hence period size, were too high for us122l to work).

Any comment on that patch would be greatly appreciated.  I'm just
wondering if it's safe for me to give it to some people.

> --- /dd/alsa-plugins/usb_stream/pcm_usb_stream.c	2008-11-21 18:08:16.000000000 -0500
> +++ pcm_usb_stream.c	2009-12-30 23:40:46.467973740 -0500
> @@ -48,6 +48,9 @@
>  #define VDBG(f, ...)
>  #endif
>  
> +#define FRAME_SIZE 6
> +
> +
>  #define LCARD 32
>  struct user_usb_stream {
>  	char			card[LCARD];
> @@ -70,6 +73,8 @@
>  	unsigned		periods_done;
>  
>  	unsigned 		channels;
> +	snd_pcm_uframes_t	period_size;
> +	unsigned int		rate;
>  } snd_pcm_us_t;
>  
>  static struct user_usb_stream *uus;
> @@ -177,7 +182,7 @@
>  	VDBG("");
>  
>  	us_cfg.version = USB_STREAM_INTERFACE_VERSION;
> -	us_cfg.frame_size = 6;
> +	us_cfg.frame_size = FRAME_SIZE;
>  	us_cfg.sample_rate = io->rate;
>  	us_cfg.period_frames = io->period_size;
>  
> @@ -256,8 +261,11 @@
>  static int snd_pcm_us_stop(snd_pcm_ioplug_t *io)
>  {
>  	snd_pcm_us_t *us = io->private_data;
> -	VDBG("%u", us->uus->s->periods_done);
>  
> +	if (!us->uus->s)
> +	  return 0;
> +
> +	VDBG("%u", us->uus->s->periods_done);
>  	if (io->stream == SND_PCM_STREAM_PLAYBACK)
>  		memset(us->uus->write_area, 0, us->uus->s->write_size);
>  
> @@ -370,6 +378,10 @@
>  	};
>  
>  	int err;
> +	unsigned int rate_min = us->rate ? us->rate : 44100,
> +		rate_max = us->rate ? us->rate : 96000,
> +		period_bytes_min = us->period_size ? FRAME_SIZE * us->period_size : 128,
> +		period_bytes_max = us->period_size ? FRAME_SIZE * us->period_size : 64*4096;
>  
>  	if ((err = snd_pcm_ioplug_set_param_list(&us->io, SND_PCM_IOPLUG_HW_ACCESS,
>  						 ARRAY_SIZE(access_list), access_list)) < 0 ||
> @@ -378,19 +390,20 @@
>  	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_CHANNELS,
>  						   us->channels, us->channels)) < 0 ||
>  	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_RATE,
> -						   44100, 96000)) < 0 ||
> +						   rate_min, rate_max)) < 0 ||
>  	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
> -						   128, 64*4096)) < 0 ||
> +						   period_bytes_min, period_bytes_max)) < 0 ||
>  	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_PERIODS,
>  						   2, 2)) < 0)
>  		return err;
> -
>  	return 0;
>  }
>  
>  static int snd_pcm_us_open(snd_pcm_t **pcmp, const char *name,
>  				   const char *card,
> -				   snd_pcm_stream_t stream, int mode)
> +			   snd_pcm_stream_t stream, int mode,
> +			   snd_pcm_uframes_t period_size,
> +			   unsigned int rate)
>  {
>  	snd_pcm_us_t *us;
>  	int err;
> @@ -421,6 +434,8 @@
>  	snd_hwdep_poll_descriptors(us->hwdep, &us->pfd, 1);
>  
>  	us->channels = 2;
> +	us->period_size = period_size;
> +	us->rate = rate;
>  
>  	us->io.version = SND_PCM_IOPLUG_VERSION;
>  	us->io.name = "ALSA <-> USB_STREAM PCM I/O Plugin";
> @@ -455,6 +470,7 @@
>  	snd_config_iterator_t i, next;
>  	const char *card;
>  	int err;
> +	long period_size = 0, rate = 0;
>  	
>  	snd_config_for_each(i, next, conf) {
>  		snd_config_t *n = snd_config_iterator_entry(i);
> @@ -472,12 +488,27 @@
>  			snd_config_get_string(n, &card);
>  			continue;
>  		}
> +		if (strcmp(id, "period_size") == 0) {
> +			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
> +				SNDERR("Invalid type for %s", id);
> +				return -EINVAL;
> +			}
> +			snd_config_get_integer(n, &period_size);
> +			continue;
> +		}
> +		if (strcmp(id, "rate") == 0) {
> +			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
> +				SNDERR("Invalid type for %s", id);
> +				return -EINVAL;
> +			}
> +			snd_config_get_integer(n, &rate);
> +			continue;
> +		}
>  		SNDERR("Unknown field %s", id);
>  		return -EINVAL;
>  	}
>  
> -	err = snd_pcm_us_open(pcmp, name, card, stream, mode);
> -
> +	err = snd_pcm_us_open(pcmp, name, card, stream, mode, period_size, rate);
>  	return err;
>  }

-- 
Michaël `Micha' Cadilhac (LITQ, U. de Montréal) -- http://michael.cadilhac.name
	|| <ESC>ape this <COLON> thing,
	||   <Q>uit and do <NOT> <RET>urn.
	||         -- VI



More information about the Alsa-devel mailing list