shithub: sox

Download patch

ref: 8ce49bf56ccbb47def4531a2643262049eb6b297
parent: 288129c5d240041c816bdf932c33d934f469c746
author: cbagwell <cbagwell>
date: Thu Jan 2 22:07:32 EST 2003

Added over/under run detecting to ALSA driver.

--- a/Changelog
+++ b/Changelog
@@ -47,6 +47,7 @@
     a comment.  Found by Rhys Chard.
   o Change command line to compile soxmix.o slightly to try and make
     Forte compiler happy.
+  o Added support for ALSA 0.9 driver. Jimen Ching
 
 sox-12.17.3
 -----------
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -646,4 +646,69 @@
     return 0;
 }
 
+st_ssize_t st_alsaread(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
+{
+    st_ssize_t len;
+
+    len = st_rawread(ft, buf, nsamp);
+
+#if USE_ALSA9
+    /* ALSA 0.9 and above require that we detects underruns and
+     * reset the driver if it occurs.
+     */
+    if (len != nsamp)
+    {
+	/* Reset the driver.  A future enhancement would be to
+	 * fill up the empty spots in the buffer (starting at
+	 * nsamp - len).  But I'm being lazy (cbagwell) and just
+	 * returning with a partial buffer.
+	 */
+	ioctl(fileno(ft->fp), SNDRV_PCM_IOCTL_PREPARE);
+
+	/* Raw routines use eof flag to store when we've
+	 * hit EOF or if an internal error occurs.  The
+	 * above ioctl is much like calling the stdio clearerr() function
+	 * and so we should reset libst's flag as well.  If the
+	 * error condition is still really there, it will be
+	 * detected on a future read.
+	 */
+	ft->file.eof = ST_SUCCESS;
+    }
+#endif
+
+    return len;
+}
+
+st_ssize_t st_alsawrite(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
+{
+    st_ssize_t len;
+
+    len = st_rawwrite(ft, buf, nsamp);
+
+#if USE_ALSA9
+    /* ALSA 0.9 and above require that we detects overruns and
+     * reset the driver if it occurs.
+     */
+    if (len != nsamp)
+    {
+	/* Reset the driver.  A future enhancement would be to
+	 * resend the remaining data (starting at (nsamp - len) in the buffer).
+	 * But since we've already lost some data, I'm being lazy
+	 * and letting a little more data be lost as well.
+	 */
+	ioctl(fileno(ft->fp), SNDRV_PCM_IOCTL_PREPARE);
+
+	/* Raw routines use eof flag to store when an internal error
+	 * the above ioctl is much like calling the stdio clearerr() function
+	 * and so we should reset libst's flag as well.  If the
+	 * error condition is still really there, it will be
+	 * detected on a future write.
+	 */
+	ft->file.eof = ST_SUCCESS;
+    }
+#endif
+
+    return len;
+}
+
 #endif /* ALSA_PLAYER */
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -258,8 +258,8 @@
         st_alstartwrite, st_rawwrite, st_rawstopwrite, st_format_nothing_seek},
 #ifdef ALSA_PLAYER
     {alsanames, ST_FILE_STEREO,
-        st_alsastartread, st_rawread, st_rawstopread,
-        st_alsastartwrite, st_rawwrite, st_alsastopwrite,
+        st_alsastartread, st_alsaread, st_rawstopread,
+        st_alsastartwrite, st_alsawrite, st_alsastopwrite,
         st_format_nothing_seek},
 #endif
     {aunames, ST_FILE_STEREO | ST_FILE_SEEK,
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -159,7 +159,9 @@
 
 #ifdef ALSA_PLAYER
 int st_alsastartread(ft_t ft);
+st_ssize_t st_alsaread(ft_t ft, st_sample_t *buf, st_ssize_t len);
 int st_alsastartwrite(ft_t ft);
+st_ssize_t st_alsawrite(ft_t ft, st_sample_t *buf, st_ssize_t len);
 int st_alsastopwrite(ft_t ft);
 #endif