All of lore.kernel.org
 help / color / mirror / Atom feed
* snd_pcm_writei is stuck with EPIPE
@ 2004-11-13  6:24 Pete Zaitcev
  2004-11-13 17:17 ` Dirk Jagdmann
  0 siblings, 1 reply; 6+ messages in thread
From: Pete Zaitcev @ 2004-11-13  6:24 UTC (permalink / raw)
  To: alsa-devel; +Cc: mh, syrjala, ahermans, zaitcev

[-- Attachment #1: Type: text/plain, Size: 660 bytes --]

Hello, All:

I have updated mpg123 to ALSA 0.9.0 API. The support for ALSA in currently
available mpg123-0.59r does not build on Fedora Core 3.

Everything seems to work, except that a single underflow is enough to
kill everything. When an underflow happens, instead of a mere skip,
snd_pcm_writei starts to return EPIPE and that's it. The device has to
be closed and reopened before it can work again. Does anyone have an
idea what may be going on?

I am attaching a patch and audio_alsa.c file itself in case anyone
is curious.

Thanks,
-- Pete



		
__________________________________ 
Do you Yahoo!? 
Check out the new Yahoo! Front Page. 
www.yahoo.com 
 

[-- Attachment #2: audio_alsa.c --]
[-- Type: application/octet-stream, Size: 6877 bytes --]

/*
 *  Driver for Advanced Linux Sound Architecture, http://alsa.jcu.cz
 * 
 *  Code by Anders Semb Hermansen <ahermans@vf.telia.no>
 *  Cleanups by Jaroslav Kysela <perex@jcu.cz>
 *              Ville Syrjala <syrjala@sci.fi>
 *  ALSA 0.9.0 API by Pete Zaitcev <zaitcev@yahoo.com>
 *
 *  You can use -a <soundcard name>:<device #>[,<subdevice #>]...
 *  For example: mpg123 -a hw:0,0 aaa.mpg
 *               mpg123 -a guspnp:1 aaa.mpg
 *
 * This file comes under GPL license. 
 */

#include "mpg123.h"

#include <stdlib.h>
#include <ctype.h>
#include <alsa/asoundlib.h>

static int audio_set_playback_params(struct audio_info_struct *ai);

int audio_open(struct audio_info_struct *ai)
{
	int err;
	char *device;

	if(!ai)
		return -1;
	if(ai->device) {	/* parse ALSA device name */
		device = ai->device;
	} else {
		device = "hw:0,0";
	}

	if ((err = snd_pcm_open(&ai->handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
	{
		fprintf(stderr, "open failed for %s: %s\n", device, snd_strerror(err));
		/*
		 * An exit is pretty disgusting, for a library.
		 * We are trying to prevent perror() in mpg123 from
		 * using a bogus errno.
		 */
		exit(1);
	}

	if ((err = snd_pcm_hw_params_malloc(&ai->params)) < 0) {
		fprintf(stderr, "params malloc failed: %s\n", snd_strerror(err));
		snd_pcm_close(ai->handle);
		return -1;
	}

	audio_set_playback_params(ai);	/* Probably not really needed. */
	return 0;
}

/*
 * ALSA's setting model is a phantasmagoric nightmare. It has no notion of a
 * current setting, but only a notion of a current set of settings. The only way
 * to set rate and format is to start with a set which includes all settings,
 * then narrow it down to the settings you need.
 */
static int audio_set_playback_params(struct audio_info_struct *ai)
{
	snd_pcm_hw_params_t *pp = ai->params;
	int err;
#if 0
	int dir;
	snd_pcm_uframes_t buffer_size;
	snd_pcm_uframes_t period_size, min_period_size, max_period_size;
#endif
	snd_pcm_format_t format;

	/*
	 * First, obtain the complete set.
	 */
	if ((err = snd_pcm_hw_params_any(ai->handle, pp)) < 0) {
		fprintf(stderr, "snd_pcm_hw_params_any failed: %s\n",
		    snd_strerror(err));
		return -1;
	}

	/*
	 * Narrorow access (not settable)
	 */
	err = snd_pcm_hw_params_set_access(ai->handle, pp, SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		fprintf(stderr, "snd_pcm_hw_params_set_access failed: %s\n",
		    snd_strerror(err));
		return -1;
	}

	/*
	 * Narrow the set with mpg123 settables: channels, format, rate.
	 */
	if (ai->channels >= 1) {
		err = snd_pcm_hw_params_set_channels(ai->handle, pp, ai->channels);
		if (err < 0) {
			fprintf(stderr,
			    "snd_pcm_hw_params_set_channels failed: %s\n",
			    snd_strerror(err));
			return -1;
		}
	}

	switch(ai->format)
	{
	case AUDIO_FORMAT_SIGNED_16:
	default:
		format = SND_PCM_FORMAT_S16;
		break;
	case AUDIO_FORMAT_UNSIGNED_8:
		format = SND_PCM_FORMAT_U8;
		break;
	case AUDIO_FORMAT_SIGNED_8:
		format = SND_PCM_FORMAT_S8;
		break;
	case AUDIO_FORMAT_ULAW_8:
		format = SND_PCM_FORMAT_MU_LAW;
		break;
	case AUDIO_FORMAT_ALAW_8:
		format = SND_PCM_FORMAT_A_LAW;
		break;
	case AUDIO_FORMAT_UNSIGNED_16:
		format = SND_PCM_FORMAT_U16;
		break;
	}
	err = snd_pcm_hw_params_set_format(ai->handle, pp, format);
	if (err < 0) {
		fprintf(stderr,
		    "snd_pcm_hw_params_set_format failed: %s\n",
		    snd_strerror(err));
		return -1;
	}

	if (ai->rate >= 0) {
		err = snd_pcm_hw_params_set_rate(ai->handle, pp, ai->rate, 0);
		if (err < 0) {
			fprintf(stderr,
			    "snd_pcm_hw_params_set_rate failed: %s\n",
			    snd_strerror(err));
			return -1;
		}
	}

	/*
	 * Recalculate the latency settings. This is not something you want
	 * often. The mpg123 needs this when you do  netcat|mpg123  to listen
	 * to the radio.
	 */
#if 0 /* Keep this off temporarily while we debug cutoffs on underflow */
	if ((err = snd_pcm_hw_params_get_period_size(pp, &period_size, &dir)) != 0) {
		fprintf(stderr, "snd_pcm_hw_params_get_period_size error %d\n", err);
	}
	printf("old period size %d (dir %d)\n", (int) period_size, dir); /* P3 */

	snd_pcm_hw_params_get_period_size_min(pp, &min_period_size, &dir);
	snd_pcm_hw_params_get_period_size_max(pp, &max_period_size, &dir);
	if (snd_pcm_hw_params_get_buffer_size(pp, &buffer_size) != 0) {
		fprintf(stderr, "snd_pcm_hw_params_get_buffer_size error\n");
	}

	period_size = buffer_size/4;
	if (period_size > max_period_size) period_size = max_period_size;
	if (period_size < min_period_size) period_size = min_period_size;
	printf("new period size %d\n", (int) period_size); /* P3 */
	if ((err = snd_pcm_hw_params_set_period_size(ai->handle, pp, period_size, 0)) != 0) {
		fprintf(stderr, "playback params failed: %s\n", snd_strerror(err));
	}

	// P3
	// pp.fragments_max = -1;
	// pp.fragments_room = 1;
#endif

	/*
	 * Finally, commit settings to the hardware.
	 */
	if ((err = snd_pcm_hw_params(ai->handle, pp)) < 0) {
		fprintf(stderr, "snd_pcm_hw_params failed: %s\n", snd_strerror(err));
		/* Not fatal for partial settings at initialization */
		return 0;
	}

	return 0;
}

int audio_reset_parameters(struct audio_info_struct *ai)
{

	audio_set_playback_params(ai);
	return 0;
}

int audio_rate_best_match(struct audio_info_struct *ai)
{
	return 0;
}

int audio_set_rate(struct audio_info_struct *ai)
{

	if(!ai || ai->rate < 0)
		return -1;
	return audio_set_playback_params(ai);
}

int audio_set_channels(struct audio_info_struct *ai)
{

	if(ai->channels < 0)
		return 0;
	return audio_set_playback_params(ai);
}

int audio_set_format(struct audio_info_struct *ai)
{

	if(ai->format == -1)
		return 0;
	return audio_set_playback_params(ai);
}

int audio_get_formats(struct audio_info_struct *ai)
{
	snd_pcm_format_mask_t *mask;
	int i;
	int fmt = -1;

	static int fmts[] = {
		AUDIO_FORMAT_SIGNED_16, AUDIO_FORMAT_UNSIGNED_16,
		AUDIO_FORMAT_UNSIGNED_8, AUDIO_FORMAT_SIGNED_8,
		AUDIO_FORMAT_ULAW_8, AUDIO_FORMAT_ALAW_8
	};
	static int afmts[] = {
		SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16,
		SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8,
		SND_PCM_FORMAT_MU_LAW, SND_PCM_FORMAT_A_LAW
	};

	snd_pcm_format_mask_alloca(&mask);

	snd_pcm_hw_params_any(ai->handle, ai->params);
	snd_pcm_hw_params_get_format_mask(ai->params, mask);
	for (i = 0; i < 6; i++) {
		if (snd_pcm_format_mask_test(mask, afmts[i])) {
			if (fmt == -1)
				fmt = 0;
			fmt |= fmts[i];
		}
	}

	return fmt;
}

int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
{
	ssize_t ret;
	unsigned int factor;

	factor = 0;
	if (ai->channels != 1) factor += 1;
	if (ai->format & AUDIO_FORMAT_MASK) factor += 1;
	ret = snd_pcm_writei(ai->handle, buf, len >> factor);
	if (ret < 0) {
		fprintf(stderr, "snd_pcm_write failed: %s\n", snd_strerror(ret));
	}
	return ret;
}

int audio_close(struct audio_info_struct *ai)
{
	int ret;

	ret = snd_pcm_close(ai->handle);
	snd_pcm_hw_params_free(ai->params);
	return ret;
}

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: mpg123-0.59r-p3.diff --]
[-- Type: text/x-patch; name="mpg123-0.59r-p3.diff", Size: 12170 bytes --]

diff -upr mpg123-0.59r/audio_alsa.c mpg123-0.59r-p3/audio_alsa.c
--- mpg123-0.59r/audio_alsa.c	1999-05-28 03:25:50.000000000 -0700
+++ mpg123-0.59r-p3/audio_alsa.c	2004-11-12 22:00:26.704988507 -0800
@@ -4,9 +4,10 @@
  *  Code by Anders Semb Hermansen <ahermans@vf.telia.no>
  *  Cleanups by Jaroslav Kysela <perex@jcu.cz>
  *              Ville Syrjala <syrjala@sci.fi>
+ *  ALSA 0.9.0 API by Pete Zaitcev <zaitcev@yahoo.com>
  *
- *  You can use -a <soundcard #>:<device #>...
- *  For example: mpg123 -a 1:0 aaa.mpg
+ *  You can use -a <soundcard name>:<device #>[,<subdevice #>]...
+ *  For example: mpg123 -a hw:0,0 aaa.mpg
  *               mpg123 -a guspnp:1 aaa.mpg
  *
  * This file comes under GPL license. 
@@ -16,97 +17,179 @@
 
 #include <stdlib.h>
 #include <ctype.h>
-#include <sys/asoundlib.h>
+#include <alsa/asoundlib.h>
 
-#ifdef SND_LITTLE_ENDIAN
-#define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_LE
-#define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_LE
-#define SND_PCM_FMT_S16_NE SND_PCM_FMT_S16_LE
-#define SND_PCM_FMT_U16_NE SND_PCM_FMT_U16_LE
-#else
-#define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_BE
-#define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_BE
-#define SND_PCM_FMT_S16_NE SND_PCM_FMT_S16_BE
-#define SND_PCM_FMT_U16_NE SND_PCM_FMT_U16_BE
-#endif
+static int audio_set_playback_params(struct audio_info_struct *ai);
 
 int audio_open(struct audio_info_struct *ai)
 {
 	int err;
-	int card=0,device=0;
-	char scard[128], sdevice[128];
+	char *device;
 
 	if(!ai)
 		return -1;
 	if(ai->device) {	/* parse ALSA device name */
-		if(strchr(ai->device,':')) {	/* card with device */
-			strncpy(scard, ai->device, sizeof(scard)-1);
-			scard[sizeof(scard)-1] = '\0';
-			if (strchr(scard,':')) *strchr(scard,':') = '\0';
-			card = snd_card_name(scard);
-			if (card < 0) {
-				fprintf(stderr, "wrong soundcard number: %s\n", scard);
-				exit(1);
-			}
-			strncpy(sdevice, strchr(ai->device, ':') + 1, sizeof(sdevice)-1);
-		} else {
-			strncpy(sdevice, ai->device, sizeof(sdevice)-1);
-		}
-		sdevice[sizeof(sdevice)-1] = '\0';
-		device = atoi(sdevice);
-		if (!isdigit(sdevice[0]) || device < 0 || device > 31) {
-			fprintf(stderr, "wrong device number: %s\n", sdevice);
-			exit(1);
-		}
+		device = ai->device;
+	} else {
+		device = "hw:0,0";
 	}
 
-	if((err=snd_pcm_open(&ai->handle, card, device, SND_PCM_OPEN_PLAYBACK)) < 0 )
+	if ((err = snd_pcm_open(&ai->handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
 	{
-		fprintf(stderr, "open failed: %s\n", snd_strerror(err));
+		fprintf(stderr, "open failed for %s: %s\n", device, snd_strerror(err));
+		/*
+		 * An exit is pretty disgusting, for a library.
+		 * We are trying to prevent perror() in mpg123 from
+		 * using a bogus errno.
+		 */
 		exit(1);
 	}
 
-	if(audio_reset_parameters(ai) < 0)
-	{
-		audio_close(ai);
+	if ((err = snd_pcm_hw_params_malloc(&ai->params)) < 0) {
+		fprintf(stderr, "params malloc failed: %s\n", snd_strerror(err));
+		snd_pcm_close(ai->handle);
 		return -1;
 	}
 
+	audio_set_playback_params(ai);	/* Probably not really needed. */
 	return 0;
 }
 
-static void audio_set_playback_params(struct audio_info_struct *ai)
+/*
+ * ALSA's setting model is a phantasmagoric nightmare. It has no notion of a
+ * current setting, but only a notion of a current set of settings. The only way
+ * to set rate and format is to start with a set which includes all settings,
+ * then narrow it down to the settings you need.
+ */
+static int audio_set_playback_params(struct audio_info_struct *ai)
 {
+	snd_pcm_hw_params_t *pp = ai->params;
 	int err;
-	snd_pcm_playback_info_t pi;
-	snd_pcm_playback_params_t pp;
+#if 0
+	int dir;
+	snd_pcm_uframes_t buffer_size;
+	snd_pcm_uframes_t period_size, min_period_size, max_period_size;
+#endif
+	snd_pcm_format_t format;
 
-	if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
-	{
-		fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
-		return;	/* not fatal error */
+	/*
+	 * First, obtain the complete set.
+	 */
+	if ((err = snd_pcm_hw_params_any(ai->handle, pp)) < 0) {
+		fprintf(stderr, "snd_pcm_hw_params_any failed: %s\n",
+		    snd_strerror(err));
+		return -1;
 	}
 
-	bzero(&pp, sizeof(pp));
-	pp.fragment_size = pi.buffer_size/4;
-	if (pp.fragment_size > pi.max_fragment_size) pp.fragment_size = pi.max_fragment_size;
-	if (pp.fragment_size < pi.min_fragment_size) pp.fragment_size = pi.min_fragment_size;
-	pp.fragments_max = -1;
-	pp.fragments_room = 1;
+	/*
+	 * Narrorow access (not settable)
+	 */
+	err = snd_pcm_hw_params_set_access(ai->handle, pp, SND_PCM_ACCESS_RW_INTERLEAVED);
+	if (err < 0) {
+		fprintf(stderr, "snd_pcm_hw_params_set_access failed: %s\n",
+		    snd_strerror(err));
+		return -1;
+	}
+
+	/*
+	 * Narrow the set with mpg123 settables: channels, format, rate.
+	 */
+	if (ai->channels >= 1) {
+		err = snd_pcm_hw_params_set_channels(ai->handle, pp, ai->channels);
+		if (err < 0) {
+			fprintf(stderr,
+			    "snd_pcm_hw_params_set_channels failed: %s\n",
+			    snd_strerror(err));
+			return -1;
+		}
+	}
 
-	if((err=snd_pcm_playback_params(ai->handle, &pp)) < 0 )
+	switch(ai->format)
 	{
+	case AUDIO_FORMAT_SIGNED_16:
+	default:
+		format = SND_PCM_FORMAT_S16;
+		break;
+	case AUDIO_FORMAT_UNSIGNED_8:
+		format = SND_PCM_FORMAT_U8;
+		break;
+	case AUDIO_FORMAT_SIGNED_8:
+		format = SND_PCM_FORMAT_S8;
+		break;
+	case AUDIO_FORMAT_ULAW_8:
+		format = SND_PCM_FORMAT_MU_LAW;
+		break;
+	case AUDIO_FORMAT_ALAW_8:
+		format = SND_PCM_FORMAT_A_LAW;
+		break;
+	case AUDIO_FORMAT_UNSIGNED_16:
+		format = SND_PCM_FORMAT_U16;
+		break;
+	}
+	err = snd_pcm_hw_params_set_format(ai->handle, pp, format);
+	if (err < 0) {
+		fprintf(stderr,
+		    "snd_pcm_hw_params_set_format failed: %s\n",
+		    snd_strerror(err));
+		return -1;
+	}
+
+	if (ai->rate >= 0) {
+		err = snd_pcm_hw_params_set_rate(ai->handle, pp, ai->rate, 0);
+		if (err < 0) {
+			fprintf(stderr,
+			    "snd_pcm_hw_params_set_rate failed: %s\n",
+			    snd_strerror(err));
+			return -1;
+		}
+	}
+
+	/*
+	 * Recalculate the latency settings. This is not something you want
+	 * often. The mpg123 needs this when you do  netcat|mpg123  to listen
+	 * to the radio.
+	 */
+#if 0 /* Keep this off temporarily while we debug cutoffs on underflow */
+	if ((err = snd_pcm_hw_params_get_period_size(pp, &period_size, &dir)) != 0) {
+		fprintf(stderr, "snd_pcm_hw_params_get_period_size error %d\n", err);
+	}
+	printf("old period size %d (dir %d)\n", (int) period_size, dir); /* P3 */
+
+	snd_pcm_hw_params_get_period_size_min(pp, &min_period_size, &dir);
+	snd_pcm_hw_params_get_period_size_max(pp, &max_period_size, &dir);
+	if (snd_pcm_hw_params_get_buffer_size(pp, &buffer_size) != 0) {
+		fprintf(stderr, "snd_pcm_hw_params_get_buffer_size error\n");
+	}
+
+	period_size = buffer_size/4;
+	if (period_size > max_period_size) period_size = max_period_size;
+	if (period_size < min_period_size) period_size = min_period_size;
+	printf("new period size %d\n", (int) period_size); /* P3 */
+	if ((err = snd_pcm_hw_params_set_period_size(ai->handle, pp, period_size, 0)) != 0) {
 		fprintf(stderr, "playback params failed: %s\n", snd_strerror(err));
-		return; /* not fatal error */
 	}
+
+	// P3
+	// pp.fragments_max = -1;
+	// pp.fragments_room = 1;
+#endif
+
+	/*
+	 * Finally, commit settings to the hardware.
+	 */
+	if ((err = snd_pcm_hw_params(ai->handle, pp)) < 0) {
+		fprintf(stderr, "snd_pcm_hw_params failed: %s\n", snd_strerror(err));
+		/* Not fatal for partial settings at initialization */
+		return 0;
+	}
+
+	return 0;
 }
 
 int audio_reset_parameters(struct audio_info_struct *ai)
 {
-	audio_set_format(ai);
-	audio_set_channels(ai);
-	audio_set_rate(ai);
 
+	audio_set_playback_params(ai);
 	return 0;
 }
 
@@ -117,81 +200,33 @@ int audio_rate_best_match(struct audio_i
 
 int audio_set_rate(struct audio_info_struct *ai)
 {
-	int ret;
 
 	if(!ai || ai->rate < 0)
 		return -1;
-
-	ai->alsa_format.rate=ai->rate;
-
-	if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 )
-		return -1;
-
-	audio_set_playback_params(ai);
-
-	return 0;
+	return audio_set_playback_params(ai);
 }
 
 int audio_set_channels(struct audio_info_struct *ai)
 {
-	int ret;
 
-	if(ai->alsa_format.channels < 0)
+	if(ai->channels < 0)
 		return 0;
-
-	ai->alsa_format.channels = ai->channels;
-
-	if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 )
-		return -1;
-
-	audio_set_playback_params(ai);
-
-	return 0;
+	return audio_set_playback_params(ai);
 }
 
 int audio_set_format(struct audio_info_struct *ai)
 {
-	int ret;
 
 	if(ai->format == -1)
 		return 0;
-
-	switch(ai->format)
-	{
-		case AUDIO_FORMAT_SIGNED_16:
-		default:
-			ai->alsa_format.format=SND_PCM_SFMT_S16_NE;
-			break;
-		case AUDIO_FORMAT_UNSIGNED_8:
-			ai->alsa_format.format=SND_PCM_SFMT_U8;
-			break;
-		case AUDIO_FORMAT_SIGNED_8:
-			ai->alsa_format.format=SND_PCM_SFMT_S8;
-			break;
-		case AUDIO_FORMAT_ULAW_8:
-			ai->alsa_format.format=SND_PCM_SFMT_MU_LAW;
-			break;
-		case AUDIO_FORMAT_ALAW_8:
-			ai->alsa_format.format=SND_PCM_SFMT_A_LAW;
-			break;
-		case AUDIO_FORMAT_UNSIGNED_16:
-			ai->alsa_format.format=SND_PCM_SFMT_U16_NE;
-			break;
-	}
-
-	if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 )
-		return -1;
-
-	audio_set_playback_params(ai);
-
-	return 0;
+	return audio_set_playback_params(ai);
 }
 
 int audio_get_formats(struct audio_info_struct *ai)
 {
-	int i, err;
+	snd_pcm_format_mask_t *mask;
+	int i;
 	int fmt = -1;
-	snd_pcm_playback_info_t pi;
 
 	static int fmts[] = {
 		AUDIO_FORMAT_SIGNED_16, AUDIO_FORMAT_UNSIGNED_16,
@@ -199,19 +234,17 @@ int audio_get_formats(struct audio_info_
 		AUDIO_FORMAT_ULAW_8, AUDIO_FORMAT_ALAW_8
 	};
 	static int afmts[] = {
-		SND_PCM_FMT_S16_NE, SND_PCM_FMT_U16_NE,
-		SND_PCM_FMT_U8, SND_PCM_FMT_S8,
-		SND_PCM_FMT_MU_LAW, SND_PCM_FMT_A_LAW
+		SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16,
+		SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8,
+		SND_PCM_FORMAT_MU_LAW, SND_PCM_FORMAT_A_LAW
 	};
 
-	if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
-	{
-		fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
-		return -1;
-	}
+	snd_pcm_format_mask_alloca(&mask);
 
+	snd_pcm_hw_params_any(ai->handle, ai->params);
+	snd_pcm_hw_params_get_format_mask(ai->params, mask);
 	for (i = 0; i < 6; i++) {
-		if (pi.formats & afmts[i]) {
+		if (snd_pcm_format_mask_test(mask, afmts[i])) {
 			if (fmt == -1)
 				fmt = 0;
 			fmt |= fmts[i];
@@ -224,15 +257,23 @@ int audio_get_formats(struct audio_info_
 int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
 {
 	ssize_t ret;
+	unsigned int factor;
 
-	ret=snd_pcm_write(ai->handle, buf, len);
-
+	factor = 0;
+	if (ai->channels != 1) factor += 1;
+	if (ai->format & AUDIO_FORMAT_MASK) factor += 1;
+	ret = snd_pcm_writei(ai->handle, buf, len >> factor);
+	if (ret < 0) {
+		fprintf(stderr, "snd_pcm_write failed: %s\n", snd_strerror(ret));
+	}
 	return ret;
 }
 
 int audio_close(struct audio_info_struct *ai)
 {
 	int ret;
+
 	ret = snd_pcm_close(ai->handle);
+	snd_pcm_hw_params_free(ai->params);
 	return ret;
 }
Only in mpg123-0.59r-p3: audio_alsa.o
diff -upr mpg123-0.59r/audio.c mpg123-0.59r-p3/audio.c
--- mpg123-0.59r/audio.c	1999-04-06 08:53:05.000000000 -0700
+++ mpg123-0.59r-p3/audio.c	2004-11-10 23:04:58.000000000 -0800
@@ -17,9 +17,7 @@ void audio_info_struct_init(struct audio
   ai->output = -1;
 #ifdef ALSA
   ai->handle = NULL;
-  ai->alsa_format.format = -1;
-  ai->alsa_format.rate = -1;
-  ai->alsa_format.channels = -1;
+  ai->params = NULL;
 #endif
   ai->device = NULL;
   ai->channels = -1;
diff -upr mpg123-0.59r/audio.h mpg123-0.59r-p3/audio.h
--- mpg123-0.59r/audio.h	1999-06-15 13:22:03.000000000 -0700
+++ mpg123-0.59r-p3/audio.h	2004-11-10 22:15:16.000000000 -0800
@@ -35,9 +35,8 @@ enum { DECODE_TEST, DECODE_AUDIO, DECODE
 #include <dmedia/audio.h>
 #endif
 
-
 #ifdef ALSA
-#include <sys/asoundlib.h>
+#include <alsa/asoundlib.h>
 #endif
 
 struct audio_info_struct
@@ -53,8 +52,8 @@ struct audio_info_struct
   long gain;
   int output;
 #ifdef ALSA
-  void *handle;
-  snd_pcm_format_t alsa_format;
+  snd_pcm_t *handle;
+  snd_pcm_hw_params_t *params;
 #endif
   char *device;
   int channels;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: snd_pcm_writei is stuck with EPIPE
  2004-11-13  6:24 snd_pcm_writei is stuck with EPIPE Pete Zaitcev
@ 2004-11-13 17:17 ` Dirk Jagdmann
  2004-11-13 18:19   ` Pete Zaitcev
  2004-11-14 19:06   ` Pete Zaitcev
  0 siblings, 2 replies; 6+ messages in thread
From: Dirk Jagdmann @ 2004-11-13 17:17 UTC (permalink / raw)
  To: Pete Zaitcev, alsa-devel

> I am attaching a patch and audio_alsa.c file itself in case anyone
> is curious.

I am curious, but can't compile this. I have ALSA 1.0.6 running and this 
gives me the following error:

audio_alsa.c: In function `audio_open':
audio_alsa.c:48: error: structure has no member named `params'
audio_alsa.c: In function `audio_set_playback_params':
audio_alsa.c:66: error: structure has no member named `params'
audio_alsa.c: In function `audio_get_formats':
audio_alsa.c:244: error: structure has no member named `params'
audio_alsa.c:245: error: structure has no member named `params'
audio_alsa.c: In function `audio_close':
audio_alsa.c:277: error: structure has no member named `params'

-- 
---> doj / cubic
----> http://cubic.org/~doj
-----> http://llg.cubic.org


-------------------------------------------------------
This SF.Net email is sponsored by: InterSystems CACHE
FREE OODBMS DOWNLOAD - A multidimensional database that combines
robust object and relational technologies, making it a perfect match
for Java, C++,COM, XML, ODBC and JDBC. www.intersystems.com/match8

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: snd_pcm_writei is stuck with EPIPE
  2004-11-13 17:17 ` Dirk Jagdmann
@ 2004-11-13 18:19   ` Pete Zaitcev
  2004-11-13 21:43     ` Dirk Jagdmann
  2004-11-14 19:06   ` Pete Zaitcev
  1 sibling, 1 reply; 6+ messages in thread
From: Pete Zaitcev @ 2004-11-13 18:19 UTC (permalink / raw)
  To: Dirk Jagdmann, alsa-devel; +Cc: zaitcev


--- Dirk Jagdmann <doj@cubic.org> wrote:

> > I am attaching a patch and audio_alsa.c file itself in case anyone
> > is curious.
> 
> I am curious, but can't compile this. I have ALSA 1.0.6 running and this 
> gives me the following error:

Use the patch file, it is complete. The audio_alsa.c is for reference
only, because patches are difficult to read when they get too divergent.

-- Pete



		
__________________________________ 
Do you Yahoo!? 
Check out the new Yahoo! Front Page. 
www.yahoo.com 
 



-------------------------------------------------------
This SF.Net email is sponsored by: InterSystems CACHE
FREE OODBMS DOWNLOAD - A multidimensional database that combines
robust object and relational technologies, making it a perfect match
for Java, C++,COM, XML, ODBC and JDBC. www.intersystems.com/match8

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: snd_pcm_writei is stuck with EPIPE
  2004-11-13 18:19   ` Pete Zaitcev
@ 2004-11-13 21:43     ` Dirk Jagdmann
  0 siblings, 0 replies; 6+ messages in thread
From: Dirk Jagdmann @ 2004-11-13 21:43 UTC (permalink / raw)
  To: Pete Zaitcev; +Cc: alsa-devel

> Use the patch file, it is complete. The audio_alsa.c is for reference
> only, because patches are difficult to read when they get too divergent.

now it's compiling :-)

-- 
---> doj / cubic
----> http://cubic.org/~doj
-----> http://llg.cubic.org


-------------------------------------------------------
This SF.Net email is sponsored by: InterSystems CACHE
FREE OODBMS DOWNLOAD - A multidimensional database that combines
robust object and relational technologies, making it a perfect match
for Java, C++,COM, XML, ODBC and JDBC. www.intersystems.com/match8

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: snd_pcm_writei is stuck with EPIPE
  2004-11-13 17:17 ` Dirk Jagdmann
  2004-11-13 18:19   ` Pete Zaitcev
@ 2004-11-14 19:06   ` Pete Zaitcev
  2004-11-15 17:02     ` Clemens Ladisch
  1 sibling, 1 reply; 6+ messages in thread
From: Pete Zaitcev @ 2004-11-14 19:06 UTC (permalink / raw)
  To: Dirk Jagdmann; +Cc: alsa-devel, mh, perex, zaitcev

[-- Attachment #1: Type: text/plain, Size: 590 bytes --]

It looks I found it. The trick is to call snd_pcm_prepare when an underflow
is reported. Working patch is attached in case Michael is interested.
Also, there's an old patch at alsa-project.org which supports ALSA 0.5 API
and is integrated into mpg123-0.59r. Maybe Jaroslav would add this there.

The error code is documented in the Doxygen docs, but nothing was said
that the error is persistent and has to be reset, and how to reset it.
Probably worth fixing as well.

-- Pete


		
__________________________________ 
Do you Yahoo!? 
Check out the new Yahoo! Front Page. 
www.yahoo.com 
 

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: mpg123-0.59r-p3.diff --]
[-- Type: text/x-patch; name="mpg123-0.59r-p3.diff", Size: 11604 bytes --]

Support of ALSA 0.9 API shipping in Fedora Core 3.

diff -upr mpg123-0.59r/audio_alsa.c mpg123-0.59r-p3/audio_alsa.c
--- mpg123-0.59r/audio_alsa.c	1999-05-28 03:25:50.000000000 -0700
+++ mpg123-0.59r-p3/audio_alsa.c	2004-11-14 10:56:10.135657333 -0800
@@ -4,9 +4,10 @@
  *  Code by Anders Semb Hermansen <ahermans@vf.telia.no>
  *  Cleanups by Jaroslav Kysela <perex@jcu.cz>
  *              Ville Syrjala <syrjala@sci.fi>
+ *  ALSA 0.9.0 API by Pete Zaitcev <zaitcev@yahoo.com>
  *
- *  You can use -a <soundcard #>:<device #>...
- *  For example: mpg123 -a 1:0 aaa.mpg
+ *  You can use -a <soundcard name>:<device #>[,<subdevice #>]...
+ *  For example: mpg123 -a hw:0,0 aaa.mpg
  *               mpg123 -a guspnp:1 aaa.mpg
  *
  * This file comes under GPL license. 
@@ -16,97 +17,157 @@
 
 #include <stdlib.h>
 #include <ctype.h>
-#include <sys/asoundlib.h>
+#include <alsa/asoundlib.h>
 
-#ifdef SND_LITTLE_ENDIAN
-#define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_LE
-#define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_LE
-#define SND_PCM_FMT_S16_NE SND_PCM_FMT_S16_LE
-#define SND_PCM_FMT_U16_NE SND_PCM_FMT_U16_LE
-#else
-#define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_BE
-#define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_BE
-#define SND_PCM_FMT_S16_NE SND_PCM_FMT_S16_BE
-#define SND_PCM_FMT_U16_NE SND_PCM_FMT_U16_BE
-#endif
+static int audio_set_playback_params(struct audio_info_struct *ai);
 
 int audio_open(struct audio_info_struct *ai)
 {
 	int err;
-	int card=0,device=0;
-	char scard[128], sdevice[128];
+	char *device;
 
 	if(!ai)
 		return -1;
 	if(ai->device) {	/* parse ALSA device name */
-		if(strchr(ai->device,':')) {	/* card with device */
-			strncpy(scard, ai->device, sizeof(scard)-1);
-			scard[sizeof(scard)-1] = '\0';
-			if (strchr(scard,':')) *strchr(scard,':') = '\0';
-			card = snd_card_name(scard);
-			if (card < 0) {
-				fprintf(stderr, "wrong soundcard number: %s\n", scard);
-				exit(1);
-			}
-			strncpy(sdevice, strchr(ai->device, ':') + 1, sizeof(sdevice)-1);
-		} else {
-			strncpy(sdevice, ai->device, sizeof(sdevice)-1);
-		}
-		sdevice[sizeof(sdevice)-1] = '\0';
-		device = atoi(sdevice);
-		if (!isdigit(sdevice[0]) || device < 0 || device > 31) {
-			fprintf(stderr, "wrong device number: %s\n", sdevice);
-			exit(1);
-		}
+		device = ai->device;
+	} else {
+		device = "hw:0,0";
 	}
 
-	if((err=snd_pcm_open(&ai->handle, card, device, SND_PCM_OPEN_PLAYBACK)) < 0 )
+	if ((err = snd_pcm_open(&ai->handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
 	{
-		fprintf(stderr, "open failed: %s\n", snd_strerror(err));
+		fprintf(stderr, "open failed for %s: %s\n", device, snd_strerror(err));
+		/*
+		 * An exit is pretty disgusting, for a library.
+		 * We are trying to prevent perror() in mpg123 from
+		 * using a bogus errno.
+		 */
 		exit(1);
 	}
 
-	if(audio_reset_parameters(ai) < 0)
-	{
-		audio_close(ai);
+	if ((err = snd_pcm_hw_params_malloc(&ai->params)) < 0) {
+		fprintf(stderr, "params malloc failed: %s\n", snd_strerror(err));
+		snd_pcm_close(ai->handle);
 		return -1;
 	}
 
+	audio_set_playback_params(ai);	/* Probably not really needed. */
 	return 0;
 }
 
-static void audio_set_playback_params(struct audio_info_struct *ai)
+/*
+ * ALSA's setting model is a phantasmagoric nightmare. It has no notion of a
+ * current setting, but only a notion of a current set of settings. The only way
+ * to set rate and format is to start with a set which includes all settings,
+ * then narrow it down to the settings you need.
+ */
+static int audio_set_playback_params(struct audio_info_struct *ai)
 {
+	snd_pcm_hw_params_t *pp = ai->params;
 	int err;
-	snd_pcm_playback_info_t pi;
-	snd_pcm_playback_params_t pp;
+	snd_pcm_format_t format;
+	unsigned int buffer_time;
+
+	/*
+	 * First, obtain the complete set.
+	 */
+	if ((err = snd_pcm_hw_params_any(ai->handle, pp)) < 0) {
+		fprintf(stderr, "snd_pcm_hw_params_any failed: %s\n",
+		    snd_strerror(err));
+		return -1;
+	}
 
-	if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
+	/*
+	 * Narrorow access (not settable)
+	 */
+	err = snd_pcm_hw_params_set_access(ai->handle, pp, SND_PCM_ACCESS_RW_INTERLEAVED);
+	if (err < 0) {
+		fprintf(stderr, "snd_pcm_hw_params_set_access failed: %s\n",
+		    snd_strerror(err));
+		return -1;
+	}
+
+	/*
+	 * Narrow the set with mpg123 settables: channels, format, rate.
+	 */
+	if (ai->channels >= 1) {
+		err = snd_pcm_hw_params_set_channels(ai->handle, pp, ai->channels);
+		if (err < 0) {
+			fprintf(stderr,
+			    "snd_pcm_hw_params_set_channels failed: %s\n",
+			    snd_strerror(err));
+			return -1;
+		}
+	}
+
+	switch(ai->format)
 	{
-		fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
-		return;	/* not fatal error */
+	case AUDIO_FORMAT_SIGNED_16:
+	default:
+		format = SND_PCM_FORMAT_S16;
+		break;
+	case AUDIO_FORMAT_UNSIGNED_8:
+		format = SND_PCM_FORMAT_U8;
+		break;
+	case AUDIO_FORMAT_SIGNED_8:
+		format = SND_PCM_FORMAT_S8;
+		break;
+	case AUDIO_FORMAT_ULAW_8:
+		format = SND_PCM_FORMAT_MU_LAW;
+		break;
+	case AUDIO_FORMAT_ALAW_8:
+		format = SND_PCM_FORMAT_A_LAW;
+		break;
+	case AUDIO_FORMAT_UNSIGNED_16:
+		format = SND_PCM_FORMAT_U16;
+		break;
+	}
+	err = snd_pcm_hw_params_set_format(ai->handle, pp, format);
+	if (err < 0) {
+		fprintf(stderr,
+		    "snd_pcm_hw_params_set_format failed: %s\n",
+		    snd_strerror(err));
+		return -1;
 	}
 
-	bzero(&pp, sizeof(pp));
-	pp.fragment_size = pi.buffer_size/4;
-	if (pp.fragment_size > pi.max_fragment_size) pp.fragment_size = pi.max_fragment_size;
-	if (pp.fragment_size < pi.min_fragment_size) pp.fragment_size = pi.min_fragment_size;
-	pp.fragments_max = -1;
-	pp.fragments_room = 1;
+	if (ai->rate >= 0) {
+		err = snd_pcm_hw_params_set_rate(ai->handle, pp, ai->rate, 0);
+		if (err < 0) {
+			fprintf(stderr,
+			    "snd_pcm_hw_params_set_rate failed: %s\n",
+			    snd_strerror(err));
+			return -1;
+		}
+	}
 
-	if((err=snd_pcm_playback_params(ai->handle, &pp)) < 0 )
+	/*
+	 * Default in ALSA is way too interactive, skips like crazy.
+	 */
+	buffer_time = 500000;	/* Half second */
+	if ((err = snd_pcm_hw_params_set_buffer_time_near(ai->handle, pp,
+	    &buffer_time, 0)) < 0)
 	{
-		fprintf(stderr, "playback params failed: %s\n", snd_strerror(err));
-		return; /* not fatal error */
+		fprintf(stderr,
+		    "snd_pcm_hw_params_set_buffer_time_near failed: %s\n",
+		    snd_strerror(err));
 	}
+
+	/*
+	 * Finally, commit settings to the hardware.
+	 */
+	if ((err = snd_pcm_hw_params(ai->handle, pp)) < 0) {
+		fprintf(stderr, "snd_pcm_hw_params failed: %s\n", snd_strerror(err));
+		/* Not fatal for partial settings at initialization */
+		return 0;
+	}
+
+	return 0;
 }
 
 int audio_reset_parameters(struct audio_info_struct *ai)
 {
-	audio_set_format(ai);
-	audio_set_channels(ai);
-	audio_set_rate(ai);
 
+	audio_set_playback_params(ai);
 	return 0;
 }
 
@@ -117,81 +178,33 @@ int audio_rate_best_match(struct audio_i
 
 int audio_set_rate(struct audio_info_struct *ai)
 {
-	int ret;
 
 	if(!ai || ai->rate < 0)
 		return -1;
-
-	ai->alsa_format.rate=ai->rate;
-
-	if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 )
-		return -1;
-
-	audio_set_playback_params(ai);
-
-	return 0;
+	return audio_set_playback_params(ai);
 }
 
 int audio_set_channels(struct audio_info_struct *ai)
 {
-	int ret;
 
-	if(ai->alsa_format.channels < 0)
+	if(ai->channels < 0)
 		return 0;
-
-	ai->alsa_format.channels = ai->channels;
-
-	if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 )
-		return -1;
-
-	audio_set_playback_params(ai);
-
-	return 0;
+	return audio_set_playback_params(ai);
 }
 
 int audio_set_format(struct audio_info_struct *ai)
 {
-	int ret;
 
 	if(ai->format == -1)
 		return 0;
-
-	switch(ai->format)
-	{
-		case AUDIO_FORMAT_SIGNED_16:
-		default:
-			ai->alsa_format.format=SND_PCM_SFMT_S16_NE;
-			break;
-		case AUDIO_FORMAT_UNSIGNED_8:
-			ai->alsa_format.format=SND_PCM_SFMT_U8;
-			break;
-		case AUDIO_FORMAT_SIGNED_8:
-			ai->alsa_format.format=SND_PCM_SFMT_S8;
-			break;
-		case AUDIO_FORMAT_ULAW_8:
-			ai->alsa_format.format=SND_PCM_SFMT_MU_LAW;
-			break;
-		case AUDIO_FORMAT_ALAW_8:
-			ai->alsa_format.format=SND_PCM_SFMT_A_LAW;
-			break;
-		case AUDIO_FORMAT_UNSIGNED_16:
-			ai->alsa_format.format=SND_PCM_SFMT_U16_NE;
-			break;
-	}
-
-	if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 )
-		return -1;
-
-	audio_set_playback_params(ai);
-
-	return 0;
+	return audio_set_playback_params(ai);
 }
 
 int audio_get_formats(struct audio_info_struct *ai)
 {
-	int i, err;
+	snd_pcm_format_mask_t *mask;
+	int i;
 	int fmt = -1;
-	snd_pcm_playback_info_t pi;
 
 	static int fmts[] = {
 		AUDIO_FORMAT_SIGNED_16, AUDIO_FORMAT_UNSIGNED_16,
@@ -199,19 +212,17 @@ int audio_get_formats(struct audio_info_
 		AUDIO_FORMAT_ULAW_8, AUDIO_FORMAT_ALAW_8
 	};
 	static int afmts[] = {
-		SND_PCM_FMT_S16_NE, SND_PCM_FMT_U16_NE,
-		SND_PCM_FMT_U8, SND_PCM_FMT_S8,
-		SND_PCM_FMT_MU_LAW, SND_PCM_FMT_A_LAW
+		SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16,
+		SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8,
+		SND_PCM_FORMAT_MU_LAW, SND_PCM_FORMAT_A_LAW
 	};
 
-	if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
-	{
-		fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
-		return -1;
-	}
+	snd_pcm_format_mask_alloca(&mask);
 
+	snd_pcm_hw_params_any(ai->handle, ai->params);
+	snd_pcm_hw_params_get_format_mask(ai->params, mask);
 	for (i = 0; i < 6; i++) {
-		if (pi.formats & afmts[i]) {
+		if (snd_pcm_format_mask_test(mask, afmts[i])) {
 			if (fmt == -1)
 				fmt = 0;
 			fmt |= fmts[i];
@@ -223,9 +234,32 @@ int audio_get_formats(struct audio_info_
 
 int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
 {
-	ssize_t ret;
+	int ret, err;
+	unsigned int factor;
 
-	ret=snd_pcm_write(ai->handle, buf, len);
+	factor = 0;
+	if (ai->channels != 1) factor += 1;
+	if (ai->format & AUDIO_FORMAT_MASK) factor += 1;
+
+	ret = 0;
+	while (len > 0) {
+		if ((err = snd_pcm_writei(ai->handle, buf, len >> factor)) < 0) {
+			if (err == -EPIPE) {
+				snd_pcm_prepare(ai->handle);
+				return ret;
+			} else if (err == -EAGAIN) {
+				err = 0;
+			} else {
+				fprintf(stderr, "snd_pcm_writei failed: %s\n",
+				    snd_strerror(ret));
+				return err;
+			}
+		}
+		err <<= factor;
+		ret += err;
+		len -= err;
+		buf += err;
+	}
 
 	return ret;
 }
@@ -233,6 +267,8 @@ int audio_play_samples(struct audio_info
 int audio_close(struct audio_info_struct *ai)
 {
 	int ret;
+
 	ret = snd_pcm_close(ai->handle);
+	snd_pcm_hw_params_free(ai->params);
 	return ret;
 }
diff -upr mpg123-0.59r/audio.c mpg123-0.59r-p3/audio.c
--- mpg123-0.59r/audio.c	1999-04-06 08:53:05.000000000 -0700
+++ mpg123-0.59r-p3/audio.c	2004-11-10 23:04:58.000000000 -0800
@@ -17,9 +17,7 @@ void audio_info_struct_init(struct audio
   ai->output = -1;
 #ifdef ALSA
   ai->handle = NULL;
-  ai->alsa_format.format = -1;
-  ai->alsa_format.rate = -1;
-  ai->alsa_format.channels = -1;
+  ai->params = NULL;
 #endif
   ai->device = NULL;
   ai->channels = -1;
diff -upr mpg123-0.59r/audio.h mpg123-0.59r-p3/audio.h
--- mpg123-0.59r/audio.h	1999-06-15 13:22:03.000000000 -0700
+++ mpg123-0.59r-p3/audio.h	2004-11-10 22:15:16.000000000 -0800
@@ -35,9 +35,8 @@ enum { DECODE_TEST, DECODE_AUDIO, DECODE
 #include <dmedia/audio.h>
 #endif
 
-
 #ifdef ALSA
-#include <sys/asoundlib.h>
+#include <alsa/asoundlib.h>
 #endif
 
 struct audio_info_struct
@@ -53,8 +52,8 @@ struct audio_info_struct
   long gain;
   int output;
 #ifdef ALSA
-  void *handle;
-  snd_pcm_format_t alsa_format;
+  snd_pcm_t *handle;
+  snd_pcm_hw_params_t *params;
 #endif
   char *device;
   int channels;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Re: snd_pcm_writei is stuck with EPIPE
  2004-11-14 19:06   ` Pete Zaitcev
@ 2004-11-15 17:02     ` Clemens Ladisch
  0 siblings, 0 replies; 6+ messages in thread
From: Clemens Ladisch @ 2004-11-15 17:02 UTC (permalink / raw)
  To: Pete Zaitcev; +Cc: Dirk Jagdmann, alsa-devel, mh

Pete Zaitcev wrote:
> It looks I found it. The trick is to call snd_pcm_prepare when an underflow
> is reported.

To ignore underruns, set stop_threshold to the boundary value.


HTH
Clemens



-------------------------------------------------------
This SF.Net email is sponsored by: InterSystems CACHE
FREE OODBMS DOWNLOAD - A multidimensional database that combines
robust object and relational technologies, making it a perfect match
for Java, C++,COM, XML, ODBC and JDBC. www.intersystems.com/match8

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-11-15 17:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-13  6:24 snd_pcm_writei is stuck with EPIPE Pete Zaitcev
2004-11-13 17:17 ` Dirk Jagdmann
2004-11-13 18:19   ` Pete Zaitcev
2004-11-13 21:43     ` Dirk Jagdmann
2004-11-14 19:06   ` Pete Zaitcev
2004-11-15 17:02     ` Clemens Ladisch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.