[Vm-dev] [PATCH 1/3] ALSA: correctly handle -ESTRPIPE
Daniel Drake
dsd at laptop.org
Wed Mar 27 18:11:43 UTC 2013
When ALSA produces -ESTRPIPE, it means that the sound subsystem is suspended,
and the client should resume it if it wants playback to continue. See
http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html#pcm_errors
and sample code:
http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html
Fixes a sound failure (and huge log spam) after suspend/resume with
sound playback enabled.
Index: Squeak-4.10.2.2614-src-no-mp3/unix/vm-sound-ALSA/sqUnixSoundALSA.c
===================================================================
--- Squeak-4.10.2.2614-src-no-mp3.orig/unix/vm-sound-ALSA/sqUnixSoundALSA.c
+++ Squeak-4.10.2.2614-src-no-mp3/unix/vm-sound-ALSA/sqUnixSoundALSA.c
@@ -200,28 +200,44 @@ static sqInt sound_InsertSamplesFromLea
static sqInt sound_PlaySamplesFromAtLength(sqInt frameCount, void *srcBufPtr, sqInt startIndex)
{
- if (output_handle)
- {
- void *samples= srcBufPtr + startIndex * output_channels * 2;
- int count= snd_pcm_writei(output_handle, samples, frameCount);
- if (count < frameCount / 2)
- {
- output_buffer_frames_available= 0;
- }
- if (count < 0)
- {
- if (count == -EPIPE) /* underrun */
- {
- int err;
- snd(pcm_prepare(output_handle), "sound_PlaySamples: snd_pcm_prepare");
- return 0;
- }
- fprintf(stderr, "snd_pcm_writei returned %i\n", count);
- return 0;
- }
- return count;
+ if (!output_handle)
+ {
+ success(false);
+ return 0;
+ }
+
+ void *samples= srcBufPtr + startIndex * output_channels * 2;
+ int count= snd_pcm_writei(output_handle, samples, frameCount);
+ if (count < frameCount / 2)
+ output_buffer_frames_available= 0;
+
+ if (count >= 0)
+ return count;
+
+ if (count != -EPIPE & count != -ESTRPIPE)
+ {
+ fprintf(stderr, "snd_pcm_writei returned %i\n", count);
+ return 0;
+ }
+
+ int err;
+ if (count == -EPIPE) { /* under-run */
+ err = snd_pcm_prepare (output_handle);
+ if (err < 0)
+ printf("Can't recover from underrun, prepare failed: %s", snd_strerror (err));
+ return 0;
+ } else if (count == -ESTRPIPE) {
+ while ((err = snd_pcm_resume (output_handle)) == -EAGAIN)
+ sleep(1); /* wait until the suspend flag is released */
+
+ if (err < 0) {
+ err = snd_pcm_prepare (output_handle);
+ if (err < 0)
+ printf("Can't recover from suspend, prepare failed: %s", snd_strerror (err));
}
- success(false);
+ return 0;
+ }
+
return 0;
}
@@ -307,13 +323,28 @@ static sqInt sound_RecordSamplesIntoAtLe
int frameCount= ((bufferSizeInBytes / 2) - startSliceIndex) / input_channels;
int count= snd_pcm_readi(input_handle, samples, frameCount);
if (count < 0)
- {
- if (count == -EPIPE)
- snd_pcm_prepare(input_handle);
- else if (count != -EAGAIN)
- fprintf(stderr, "snd_pcm_readi returned %i\n", count);
- return 0;
- }
+ {
+ int err;
+ if (count == -EPIPE) { /* under-run */
+ err = snd_pcm_prepare (input_handle);
+ if (err < 0)
+ printf("Can't recover from underrun, prepare failed: %s", snd_strerror (err));
+ return 0;
+ } else if (count == -ESTRPIPE) {
+ while ((err = snd_pcm_resume (input_handle)) == -EAGAIN)
+ sleep(1); /* wait until the suspend flag is released */
+
+ if (err < 0) {
+ err = snd_pcm_prepare (input_handle);
+ if (err < 0)
+ printf("Can't recover from suspend, prepare failed: %s", snd_strerror (err));
+ }
+ return 0;
+ }
+
+ return 0;
+ }
+
return count * input_channels;
}
success(false);
More information about the Vm-dev
mailing list