/* Set constraints for hw_params. This lists the handled formats, sample rates, * access patters, and buffer/period sizes. These are enforce in * snd_pcm_set_params(). */ static int set_hw_constraints(struct snd_pcm_cras *pcm_cras) { static const unsigned int access_list[] = { SND_PCM_ACCESS_MMAP_INTERLEAVED, SND_PCM_ACCESS_MMAP_NONINTERLEAVED, SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_ACCESS_RW_NONINTERLEAVED }; static const unsigned int format_list[] = { SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S24_3LE, }; int rc; rc = snd_pcm_ioplug_set_param_list(&pcm_cras->io, SND_PCM_IOPLUG_HW_ACCESS, ARRAY_SIZE(access_list), access_list); if (rc < 0) return rc; rc = snd_pcm_ioplug_set_param_list(&pcm_cras->io, SND_PCM_IOPLUG_HW_FORMAT, ARRAY_SIZE(format_list), format_list); if (rc < 0) return rc; rc = snd_pcm_ioplug_set_param_minmax(&pcm_cras->io, SND_PCM_IOPLUG_HW_CHANNELS, 1, pcm_cras->channels); if (rc < 0) return rc; rc = snd_pcm_ioplug_set_param_minmax(&pcm_cras->io, SND_PCM_IOPLUG_HW_RATE, 8000, 48000); if (rc < 0) return rc; rc = snd_pcm_ioplug_set_param_minmax(&pcm_cras->io, SND_PCM_IOPLUG_HW_BUFFER_BYTES, 64, 2 * 1024 * 1024); if (rc < 0) return rc; rc = snd_pcm_ioplug_set_param_minmax(&pcm_cras->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 64, 2 * 1024 * 1024); if (rc < 0) return rc; rc = snd_pcm_ioplug_set_param_minmax(&pcm_cras->io, SND_PCM_IOPLUG_HW_PERIODS, 1, 2048); return rc; }
static int ste_iop_set_hw_constraint(ste_iop_t *ste_iop) { unsigned int access_list[] = { SND_PCM_ACCESS_RW_INTERLEAVED }; unsigned int format_list[] = { SND_PCM_FORMAT_S16_LE }; int err; /* Set access constraint */ err = snd_pcm_ioplug_set_param_list(&ste_iop->io, SND_PCM_IOPLUG_HW_ACCESS, ARRAY_SIZE(access_list), access_list); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to set access constraint: %s\n", snd_strerror(err)); return err; } /* Set format constraint */ err = snd_pcm_ioplug_set_param_list(&ste_iop->io, SND_PCM_IOPLUG_HW_FORMAT, ARRAY_SIZE(format_list), format_list); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to set access constraint: %s\n", snd_strerror(err)); return err; } /* Set channels constraint */ err = snd_pcm_ioplug_set_param_minmax(&ste_iop->io, SND_PCM_IOPLUG_HW_CHANNELS, STE_IOP_MIN_CHANNELS, STE_IOP_MAX_CHANNELS); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to set channels constraint: %s\n", snd_strerror(err)); return err; } /* Set sample rate constraint */ err = snd_pcm_ioplug_set_param_minmax(&ste_iop->io, SND_PCM_IOPLUG_HW_RATE, STE_IOP_MIN_RATE, STE_IOP_MAX_RATE); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to set rate constraint: %s\n", snd_strerror(err)); return err; } /* Set period bytes constraint */ err = snd_pcm_ioplug_set_param_minmax(&ste_iop->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, STE_IOP_MIN_PERIOD_BYTES, STE_IOP_MAX_PERIOD_BYTES); if (err < 0) { fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to set period bytes constraint: %s\n", snd_strerror(err)); return err; } return 0; }
static int a2dp_constraint(snd_pcm_a2dp_t *a2dp) { snd_pcm_ioplug_t *io = &a2dp->io; snd_pcm_access_t access_list[] = { SND_PCM_ACCESS_RW_INTERLEAVED, SND_PCM_ACCESS_MMAP_INTERLEAVED, }; unsigned int format[2], channel[2], rate[2]; int err; DBG("a2dp %p", a2dp); err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 2, access_list); if (err < 0) return err; format[0] = SND_PCM_FORMAT_S16_LE; err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1, format); if (err < 0) return err; channel[0] = 1; channel[1] = 2; err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_CHANNELS, 2, channel); if (err < 0) return err; rate[0] = 44100; rate[1] = 48000; err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 2, rate); if (err < 0) return err; err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 8192, 8192); if (err < 0) return err; err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 2); if (err < 0) return err; return 0; }
// Alsa can convert about any format/channels/rate to any other rate // However, since we added some code in the daemon to convert, why not do it ourselves!!! // Moreover some player like aplay won't play a wav file if the device that do not natively support the requested format // If you want alsa to do the conversion, just remove the value you want to see converted static int a2dp_constraint(snd_pcm_a2dp_t * a2dp) { snd_pcm_ioplug_t *io = &a2dp->io; #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) snd_pcm_access_t access_list[] = { SND_PCM_ACCESS_RW_INTERLEAVED }; unsigned int formats[] = { SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_S16_LE }; unsigned int channels[] = { 1, 2 }; unsigned int rates[] = { 8000, 11025, 22050, 32000, 44100, 48000 }; int formats_nb = ARRAY_SIZE(formats); int channels_nb = ARRAY_SIZE(channels); int rates_nb = ARRAY_SIZE(rates); int rate_daemon = 0; int rate_prefered = 0; char srcfilename[512]; int err; get_config_filename(srcfilename, sizeof(srcfilename)); // Default is same as the daemon rate_daemon = read_config_int(srcfilename, "a2dpd", "rate", A2DPD_FRAME_RATE); // If a value is specified, use it rate_prefered = read_config_int(srcfilename, "a2dpd", "plugin-rate", rate_daemon); // If this value is not 0, alsa will convert to plugin-rate if(rate_prefered != 0) { // use defaults settings the rate specified + 16 bits stereo rates[0] = rate_prefered; rates_nb = 1; formats[0] = SND_PCM_FORMAT_S16_LE; formats_nb = 1; channels[0] = 2; channels_nb = 1; } else { // If this value is 0, the daemon will do most conversions } syslog(LOG_INFO, "[build %s %s] a2dp %p", __DATE__, __TIME__, a2dp); err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, ARRAY_SIZE(access_list), access_list); if (err < 0) return err; err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, formats_nb, formats); if (err < 0) return err; err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_CHANNELS, channels_nb, channels); if (err < 0) return err; err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, rates_nb, rates); if (err < 0) return err; err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 8192, 8192); if (err < 0) return err; err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 2); if (err < 0) return err; return 0; }