summaryrefslogtreecommitdiff
path: root/lib/libsndio/sun.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libsndio/sun.c')
-rw-r--r--lib/libsndio/sun.c83
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);
/*