[xiph-cvs] cvs commit: ao/src/plugins/alsa09 ao_alsa09.c

Stan Seibert volsung at xiph.org
Sat Aug 30 08:30:24 PDT 2003



volsung     03/08/30 11:30:23

  Modified:    src/plugins/alsa09 ao_alsa09.c
  Log:
  ALSA 0.9.x fixes from Warren Dukes <shank at mercury.chem.pitt.edu>

Revision  Changes    Path
1.14      +55 -20    ao/src/plugins/alsa09/ao_alsa09.c

Index: ao_alsa09.c
===================================================================
RCS file: /usr/local/cvsroot/ao/src/plugins/alsa09/ao_alsa09.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ao_alsa09.c	26 Aug 2003 19:57:18 -0000	1.13
+++ ao_alsa09.c	30 Aug 2003 15:30:23 -0000	1.14
@@ -23,6 +23,10 @@
  *
  */
 
+/* use new API's */
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#define ALSA_PCM_NEW_SW_PARAMS_API
+
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -140,7 +144,9 @@
 
         int err;
         int fmt;
+	snd_pcm_uframes_t period_size;
         char *cmd;
+	unsigned int rate;
 
 
         /* Open the ALSA device */
@@ -186,18 +192,23 @@
                 goto error;
         internal->sample_size = format->bits * format->channels / 8;
 
-	cmd = "snd_pcm_hw_params_set_rate";
+	rate = format->rate;
+	cmd = "snd_pcm_hw_params_set_rate_near";
+	/* make compatible with new API */
         err = snd_pcm_hw_params_set_rate_near(internal->pcm_handle, hwparams,
-			format->rate, 0);
+			&rate, 0);
         if (err < 0)
                 goto error;
 
-	cmd = "snd_pcm_hw_params_set_period_size";
-	err = snd_pcm_hw_params_set_period_size(internal->pcm_handle, hwparams,
-			internal->buf_size / internal->sample_size, 0);
+	period_size = internal->buf_size / internal->sample_size;
+	cmd = "snd_pcm_hw_params_set_period_size_near";
+	err = snd_pcm_hw_params_set_period_size_near(internal->pcm_handle, 
+			hwparams, &period_size, 0);
         if (err < 0)
                 goto error;
 
+	internal->buf_size = period_size*internal->sample_size;
+
         cmd = "snd_pcm_hw_params_set_periods";
         err = snd_pcm_hw_params_set_periods(internal->pcm_handle, hwparams,
                         internal->periods * format->channels, 0);
@@ -221,6 +232,36 @@
         return 0;
 }
 
+/* xrun_recover is ripped from pcm example at alsa-project.org */
+
+/*
+ *   Underrun and suspend recovery
+ */
+ 
+static int xrun_recovery(snd_pcm_t *handle, int err)
+{
+        if (err == -EPIPE) {    /* under-run */
+                err = snd_pcm_prepare(handle);
+                if (err < 0)
+                        printf("ALSA write error: Can't recovery from underrun" 
+					", prepare failed: %s\n", 
+					snd_strerror(err));
+                return 0;
+        } else if (err == -ESTRPIPE) {
+                while ((err = snd_pcm_resume(handle)) == -EAGAIN)
+                        sleep(1); /* wait until the suspend flag is released */
+                if (err < 0) {
+                        err = snd_pcm_prepare(handle);
+                        if (err < 0)
+                                printf("ALSA write error: Can't recovery from "
+						"suspend, prepare failed: %s\n",
+						snd_strerror(err));
+                }
+                return 0;
+        }
+        return err;
+}
+
 int ao_plugin_play(ao_device *device, const char *output_samples, 
                 uint_32 num_bytes)
 {
@@ -229,27 +270,19 @@
         char *buf = (char *)output_samples;
         int len = num_bytes / internal->sample_size;
 
-	do {
+	while (len > 0) {
                 res = snd_pcm_writei(internal->pcm_handle, buf, len);
-		if (res > 0) {
+		if(res == -EAGAIN) continue;
+		else if(res < 0) {
+			if(xrun_recovery(internal->pcm_handle, res)<0)
+				return 0;
+		}
+		else {
                         len -= res;
                         buf += res;
                 }
-	} while (len > 0 && (res > 0 || res == -EAGAIN));
-	if (res == -EPIPE) {
-		/* fprintf(stderr, "ALSA: underrun. resetting stream\n"); */
-		snd_pcm_prepare(internal->pcm_handle);
-		res = snd_pcm_writei(internal->pcm_handle, buf, len);
-		if (res != len) {
-			fprintf(stderr, "ALSA write error: %s\n", snd_strerror(res));
-			return 0;
-		} else if (res < 0) {
-			fprintf(stderr, "ALSA write error: %s\n", snd_strerror(res));
-			return 0;
-		}
         }
 
-
         return 1;
 }
 
@@ -258,6 +291,8 @@
 {
         ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
 
+	/* drain audio, bug id 282 */
+	snd_pcm_drain(internal->pcm_handle);
         snd_pcm_close(internal->pcm_handle);
 
         return 1;

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list