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);
Dear Daniel,
Thank you *very* much indeed for your work on fixing the ALSA driver and for the three sets of patches that you sent.
Regards, Ian
On Thu, Mar 28, 2013 at 4:01 PM, Ian Piumarta piumarta@speakeasy.net wrote:
Dear Daniel,
Thank you *very* much indeed for your work on fixing the ALSA driver and for the three sets of patches that you sent.
Thanks for your note!
Just curious if you have reviewed/committed them, or if that is still pending?
I'd like to ship these in Fedora but would prefer to have the patches upstream first.
Thanks Daniel
vm-dev@lists.squeakfoundation.org