mirror of
https://github.com/ericonr/sndio.git
synced 2024-02-18 04:45:21 -06:00
Allow programs using OSS/FreeBSD backend to select the buffer size.
According to kernel sources, SNDCTL_DSP_POLICY ioctl doesn't seem to always set play and rec buffer sizes to the same value. That's why we use the SNDCTL_DSP_SETFRAGMENT ioctl instead.
This commit is contained in:
parent
a282420a49
commit
9be2c65600
@ -361,8 +361,8 @@ static int
|
|||||||
sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
|
sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
|
||||||
{
|
{
|
||||||
struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
|
struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
|
||||||
unsigned int i;
|
unsigned int i, round, bufsz;
|
||||||
int policy;
|
int frag_max, frag_shift, frag_count, frag;
|
||||||
|
|
||||||
hdl->fmt = AFMT_S16_LE;
|
hdl->fmt = AFMT_S16_LE;
|
||||||
for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
|
for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
|
||||||
@ -387,28 +387,6 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
|
|||||||
else if (hdl->sio.mode & SIO_REC)
|
else if (hdl->sio.mode & SIO_REC)
|
||||||
hdl->chan = par->rchan;
|
hdl->chan = par->rchan;
|
||||||
|
|
||||||
if (par->round != ~0U && par->appbufsz != ~0U) {
|
|
||||||
hdl->round = par->round;
|
|
||||||
hdl->appbufsz = par->appbufsz;
|
|
||||||
} else if (par->round != ~0U) {
|
|
||||||
hdl->round = par->round;
|
|
||||||
hdl->appbufsz = 2 * par->round;
|
|
||||||
} else if (par->appbufsz != ~0U) {
|
|
||||||
hdl->round = par->appbufsz / 2;
|
|
||||||
hdl->appbufsz = par->appbufsz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set timing policy to 5 which is OSS' default. The
|
|
||||||
* user-settable hw.snd.latency sysctl influences the default
|
|
||||||
* policy.
|
|
||||||
*/
|
|
||||||
policy = 5;
|
|
||||||
if (ioctl(hdl->fd, SNDCTL_DSP_POLICY, &policy) < 0) {
|
|
||||||
DPERROR("sio_oss_setpar: POLICY");
|
|
||||||
hdl->sio.eof = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &hdl->fmt) < 0) {
|
if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &hdl->fmt) < 0) {
|
||||||
DPERROR("sio_oss_setpar: SETFMT");
|
DPERROR("sio_oss_setpar: SETFMT");
|
||||||
hdl->sio.eof = 1;
|
hdl->sio.eof = 1;
|
||||||
@ -437,6 +415,43 @@ sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (par->round != ~0U && par->appbufsz != ~0U) {
|
||||||
|
round = par->round;
|
||||||
|
bufsz = par->appbufsz;
|
||||||
|
} else if (par->round != ~0U) {
|
||||||
|
round = par->round;
|
||||||
|
bufsz = 2 * par->round;
|
||||||
|
} else if (par->appbufsz != ~0U) {
|
||||||
|
round = par->appbufsz / 2;
|
||||||
|
bufsz = par->appbufsz;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* even if it's not specified, we have to set the
|
||||||
|
* block size to ensure that both play and record
|
||||||
|
* direction get the same block size. Pick an
|
||||||
|
* arbitrary value that would work for most players at
|
||||||
|
* 48kHz, stereo, 16-bit.
|
||||||
|
*/
|
||||||
|
round = 512;
|
||||||
|
bufsz = 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag_max = round * hdl->chan * formats[i].bps;
|
||||||
|
frag_shift = 0;
|
||||||
|
while (1 << (frag_shift + 1) < frag_max)
|
||||||
|
frag_shift++;
|
||||||
|
|
||||||
|
frag_count = bufsz / round;
|
||||||
|
if (frag_count < 2)
|
||||||
|
frag_count = 2;
|
||||||
|
|
||||||
|
frag = frag_count << 16 | frag_shift;
|
||||||
|
if (ioctl(hdl->fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0) {
|
||||||
|
DPERROR("sio_oss_setpar: SETFRAGMENT");
|
||||||
|
hdl->sio.eof = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user