audio(4): fix for the "pause" feature

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

audio(4): fix for the "pause" feature

Alexandre Ratchov-2
If the audio device is paused, then play (or record) shouldn't start,
write() should just fill the kernel buffer, so that when pause mode
is unset, it can start with buffers full (this is usefull to
sychronize accurately play and record)

in the audio(4) driver, "pause" parameters aren't used properly:

In a call to the SETINFO ioctl (see audiosetinfo(), in
sys/dev/audio.c), pause parameters are reset to zero every time the
buffers are cleared. Even if the user set them explicitely in the
audio_info structure, they are overwritten by the call to
audio_init_ringbuffer().

Also, there are few places in the code where the audiostartp() and
audiostartr() shouldn't be called if the device is paused.

The attached patch fixes this, tested on i386 with an uaudio(4)
device.
Index: audio.c
===================================================================
RCS file: /cvs/src/sys/dev/audio.c,v
retrieving revision 1.49
diff -u -r1.49 audio.c
--- audio.c 12 Mar 2006 10:34:50 -0000 1.49
+++ audio.c 26 Apr 2006 06:19:19 -0000
@@ -852,7 +852,6 @@
  rp->stamp_last = 0;
  rp->drops = 0;
  rp->pdrops = 0;
- rp->pause = 0;
  rp->copying = 0;
  rp->needfill = 0;
  rp->mmapped = 0;
@@ -1037,10 +1036,12 @@
  ai.record.encoding    = sc->sc_rparams.encoding;
  ai.record.channels    = sc->sc_rparams.channels;
  ai.record.precision   = sc->sc_rparams.precision;
+ ai.record.pause      = 0;
  ai.play.sample_rate   = sc->sc_pparams.sample_rate;
  ai.play.encoding       = sc->sc_pparams.encoding;
  ai.play.channels      = sc->sc_pparams.channels;
  ai.play.precision     = sc->sc_pparams.precision;
+ ai.play.pause      = 0;
  ai.mode      = mode;
  sc->sc_pr.blksize = sc->sc_rr.blksize = 0; /* force recalculation */
  error = audiosetinfo(sc, &ai);
@@ -1276,7 +1277,7 @@
  while (uio->uio_resid > 0 && !error) {
  s = splaudio();
  while (cb->used <= 0) {
- if (!sc->sc_rbus) {
+ if (!sc->sc_rbus && !sc->sc_rr.pause) {
  error = audiostartr(sc);
  if (error) {
  splx(s);
@@ -1660,6 +1661,8 @@
  splx(s);
  return error;
  }
+ sc->sc_rr.pause = 0;
+ sc->sc_pr.pause = 0;
  if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_pbus && pbus)
  error = audiostartp(sc);
  if (!error &&
@@ -1879,12 +1882,12 @@
  if (cb == &sc->sc_pr) {
  audio_fill_silence(&sc->sc_pparams, cb->start, cb->bufsize);
  s = splaudio();
- if (!sc->sc_pbus)
+ if (!sc->sc_pbus && !sc->sc_pr.pause)
  (void)audiostartp(sc);
  splx(s);
  } else {
  s = splaudio();
- if (!sc->sc_rbus)
+ if (!sc->sc_rbus && !sc->sc_rr.pause)
  (void)audiostartr(sc);
  splx(s);
  }
@@ -2783,11 +2786,11 @@
     sc->sc_rr.blksize != oldrblksize)
  audio_calcwater(sc);
  if ((sc->sc_mode & AUMODE_PLAY) &&
-    pbus && !sc->sc_pbus)
+    pbus && !sc->sc_pbus && !sc->sc_pr.pause)
  error = audiostartp(sc);
  if (!error &&
     (sc->sc_mode & AUMODE_RECORD) &&
-    rbus && !sc->sc_rbus)
+    rbus && !sc->sc_rbus && !sc->sc_rr.pause)
  error = audiostartr(sc);
  err:
  splx(s);