[alsa-devel] Getting pcm_usb_stream plugin to know its limits. [Kind of SOLVED]
Michaël Cadilhac
michael at cadilhac.name
Mon Jan 11 19:35:19 CET 2010
michael at cadilhac.name (Michaël Cadilhac) writes:
> 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.
Anyone? Note that this also fixes a real bug, so it might be of
interest to include it in the trunk.
>> --- /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
|| 21 seems like a good value: half of 42,
|| and just old enough to drink! Why would you want to change it?
|| -- Stefan Monnier
More information about the Alsa-devel
mailing list