mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-19 02:29:40 +00:00
sound: Refactor sndstat_get_caps()
The current implementation of sndstat_get_caps() does not work properly when VCHANs are enabled, as it skips all information about physical channels, and also assigns the min/max rates and channels to same values, which is usually not the case. A device either supports any sample rate within the [feeder_rate_min, feeder_rate_max] range, or [hw_rate_min, hw_rate_max] range when the device is opened in exclusive or bitperfect mode. The number of channels can also vary and is not always the same for both min and max. Refactor the whole function to resemble the way we handle fetching of these values in dsp_oss_audioinfo() and dsp_oss_engineinfo(). Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D45872
This commit is contained in:
parent
86585210fd
commit
9d8b93bc9c
@ -323,47 +323,37 @@ sndstat_write(struct cdev *i_dev, struct uio *buf, int flag)
|
||||
}
|
||||
|
||||
static void
|
||||
sndstat_get_caps(struct snddev_info *d, bool play, uint32_t *min_rate,
|
||||
sndstat_get_caps(struct snddev_info *d, int dir, uint32_t *min_rate,
|
||||
uint32_t *max_rate, uint32_t *fmts, uint32_t *minchn, uint32_t *maxchn)
|
||||
{
|
||||
struct pcm_channel *c;
|
||||
int dir;
|
||||
|
||||
dir = play ? PCMDIR_PLAY : PCMDIR_REC;
|
||||
|
||||
if (play && d->pvchancount > 0) {
|
||||
*min_rate = *max_rate = d->pvchanrate;
|
||||
*fmts = AFMT_ENCODING(d->pvchanformat);
|
||||
*minchn = *maxchn = AFMT_CHANNEL(d->pvchanformat);
|
||||
return;
|
||||
} else if (!play && d->rvchancount > 0) {
|
||||
*min_rate = *max_rate = d->rvchanrate;
|
||||
*fmts = AFMT_ENCODING(d->rvchanformat);
|
||||
*minchn = *maxchn = AFMT_CHANNEL(d->rvchanformat);
|
||||
return;
|
||||
}
|
||||
struct pcmchan_caps *caps;
|
||||
int i;
|
||||
|
||||
*fmts = 0;
|
||||
*min_rate = UINT32_MAX;
|
||||
*max_rate = 0;
|
||||
*minchn = UINT32_MAX;
|
||||
*maxchn = 0;
|
||||
|
||||
CHN_FOREACH(c, d, channels.pcm) {
|
||||
struct pcmchan_caps *caps;
|
||||
int i;
|
||||
|
||||
if (c->direction != dir || (c->flags & CHN_F_VIRTUAL) != 0)
|
||||
if (c->direction != dir)
|
||||
continue;
|
||||
|
||||
CHN_LOCK(c);
|
||||
caps = chn_getcaps(c);
|
||||
*min_rate = min(caps->minspeed, *min_rate);
|
||||
*max_rate = max(caps->maxspeed, *max_rate);
|
||||
for (i = 0; caps->fmtlist[i]; i++) {
|
||||
*fmts |= AFMT_ENCODING(caps->fmtlist[i]);
|
||||
*minchn = min(AFMT_CHANNEL(caps->fmtlist[i]), *minchn);
|
||||
*maxchn = max(AFMT_CHANNEL(caps->fmtlist[i]), *maxchn);
|
||||
}
|
||||
if ((c->flags & CHN_F_EXCLUSIVE) ||
|
||||
(pcm_getflags(d->dev) & SD_F_BITPERFECT)) {
|
||||
*min_rate = min(*min_rate, caps->minspeed);
|
||||
*max_rate = max(*max_rate, caps->maxspeed);
|
||||
} else {
|
||||
*min_rate = min(*min_rate, feeder_rate_min);
|
||||
*max_rate = max(*max_rate, feeder_rate_max);
|
||||
}
|
||||
CHN_UNLOCK(c);
|
||||
}
|
||||
if (*min_rate == UINT32_MAX)
|
||||
@ -422,8 +412,8 @@ sndstat_build_sound4_nvlist(struct snddev_info *d, nvlist_t **dip)
|
||||
nvlist_add_number(di, SNDST_DSPS_PCHAN, d->playcount);
|
||||
nvlist_add_number(di, SNDST_DSPS_RCHAN, d->reccount);
|
||||
if (d->playcount > 0) {
|
||||
sndstat_get_caps(d, true, &minrate, &maxrate, &fmts, &minchn,
|
||||
&maxchn);
|
||||
sndstat_get_caps(d, PCMDIR_PLAY, &minrate, &maxrate, &fmts,
|
||||
&minchn, &maxchn);
|
||||
nvlist_add_number(di, "pminrate", minrate);
|
||||
nvlist_add_number(di, "pmaxrate", maxrate);
|
||||
nvlist_add_number(di, "pfmts", fmts);
|
||||
@ -435,8 +425,8 @@ sndstat_build_sound4_nvlist(struct snddev_info *d, nvlist_t **dip)
|
||||
nvlist_move_nvlist(di, SNDST_DSPS_INFO_PLAY, diinfo);
|
||||
}
|
||||
if (d->reccount > 0) {
|
||||
sndstat_get_caps(d, false, &minrate, &maxrate, &fmts, &minchn,
|
||||
&maxchn);
|
||||
sndstat_get_caps(d, PCMDIR_REC, &minrate, &maxrate, &fmts,
|
||||
&minchn, &maxchn);
|
||||
nvlist_add_number(di, "rminrate", minrate);
|
||||
nvlist_add_number(di, "rmaxrate", maxrate);
|
||||
nvlist_add_number(di, "rfmts", fmts);
|
||||
|
Loading…
Reference in New Issue
Block a user