diff options
Diffstat (limited to 'lib/libsndio/sun.c')
-rw-r--r-- | lib/libsndio/sun.c | 83 |
1 files changed, 59 insertions, 24 deletions
diff --git a/lib/libsndio/sun.c b/lib/libsndio/sun.c index c15d1a67fc9..192b8449348 100644 --- a/lib/libsndio/sun.c +++ b/lib/libsndio/sun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sun.c,v 1.21 2009/07/26 15:50:04 ratchov Exp $ */ +/* $OpenBSD: sun.c,v 1.22 2009/10/10 08:34:12 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -128,18 +128,17 @@ sun_infotoenc(struct sun_hdl *hdl, struct audio_prinfo *ai, struct sio_par *par) * convert sio_par encoding to sun encoding */ static void -sun_enctoinfo(struct sun_hdl *hdl, struct audio_prinfo *ai, struct sio_par *par) +sun_enctoinfo(struct sun_hdl *hdl, unsigned *renc, struct sio_par *par) { if (par->le && par->sig) { - ai->encoding = AUDIO_ENCODING_SLINEAR_LE; + *renc = AUDIO_ENCODING_SLINEAR_LE; } else if (!par->le && par->sig) { - ai->encoding = AUDIO_ENCODING_SLINEAR_BE; + *renc = AUDIO_ENCODING_SLINEAR_BE; } else if (par->le && !par->sig) { - ai->encoding = AUDIO_ENCODING_ULINEAR_LE; + *renc = AUDIO_ENCODING_ULINEAR_LE; } else { - ai->encoding = AUDIO_ENCODING_ULINEAR_BE; + *renc = AUDIO_ENCODING_ULINEAR_BE; } - ai->precision = par->bits; } /* @@ -520,25 +519,61 @@ sun_setpar(struct sio_hdl *sh, struct sio_par *par) struct audio_info aui; unsigned i, infr, ibpf, onfr, obpf; unsigned bufsz, round; + unsigned rate, prec, enc; /* - * first, set encoding, rate and channels + * try to set parameters until the device accepts + * a common encoding and rate for play and record */ - AUDIO_INITINFO(&aui); - if (hdl->sio.mode & SIO_PLAY) { - aui.play.sample_rate = par->rate; - aui.play.channels = par->pchan; - sun_enctoinfo(hdl, &aui.play, par); - } - if (hdl->sio.mode & SIO_REC) { - aui.record.sample_rate = par->rate; - aui.record.channels = par->rchan; - sun_enctoinfo(hdl, &aui.record, par); - } - if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0 && errno != EINVAL) { - DPERROR("sun_setpar: setinfo"); - hdl->sio.eof = 1; - return 0; + rate = par->rate; + prec = par->bits; + sun_enctoinfo(hdl, &enc, par); + for (i = 0;; i++) { + if (i == NRETRIES) { + DPRINTF("sun_setpar: couldn't set parameters\n"); + hdl->sio.eof = 1; + return 0; + } + AUDIO_INITINFO(&aui); + if (hdl->sio.mode & SIO_PLAY) { + aui.play.sample_rate = rate; + aui.play.precision = prec; + aui.play.encoding = enc; + aui.play.channels = par->pchan; + } + if (hdl->sio.mode & SIO_REC) { + aui.record.sample_rate = rate; + aui.record.precision = prec; + aui.record.encoding = enc; + aui.record.channels = par->rchan; + } + DPRINTF("sun_setpar: %i: trying pars = %u/%u/%u\n", + i, rate, prec, enc); + if (ioctl(hdl->fd, AUDIO_SETINFO, &aui) < 0 && errno != EINVAL) { + DPERROR("sun_setpar: setinfo(pars)"); + hdl->sio.eof = 1; + return 0; + } + if (hdl->sio.mode != (SIO_REC | SIO_PLAY)) + break; + if (ioctl(hdl->fd, AUDIO_GETINFO, &aui) < 0) { + DPERROR("sun_setpar: getinfo(pars)"); + hdl->sio.eof = 1; + return 0; + } + if (aui.play.sample_rate == aui.record.sample_rate && + aui.play.precision == aui.record.precision && + aui.play.encoding == aui.record.encoding) + break; + if (i < NRETRIES / 2) { + rate = aui.play.sample_rate; + prec = aui.play.precision; + enc = aui.play.encoding; + } else { + rate = aui.record.sample_rate; + prec = aui.record.precision; + enc = aui.record.encoding; + } } /* @@ -595,7 +630,7 @@ sun_setpar(struct sio_hdl *sh, struct sio_par *par) } infr = aui.record.block_size / ibpf; onfr = aui.play.block_size / obpf; - DPRINTF("sun_setpar: %i: trying rond = %u -> (%u, %u)\n", + DPRINTF("sun_setpar: %i: trying round = %u -> (%u, %u)\n", i, round, infr, onfr); /* |