Fix bug: sound is lost after a suspend/resume cycle. http://dev.laptop.org/ticket/10168 Patch comes from squeak upstream --- Squeak-3.10-5/platforms/unix/vm-sound-ALSA/sqUnixSoundALSA.c 2008-04-21 22:48:26.000000000 +0100 +++ Squeak-3.10-5/platforms/unix/vm-sound-ALSA/sqUnixSoundALSA-100614.c 2010-06-14 12:22:13.000000000 +0100 @@ -77,6 +77,7 @@ static snd_pcm_uframes_t output_buffer_size= 0; static double max_delay_frames= 0; + static void output_callback(snd_async_handler_t *handler) { signalSemaphoreWithIndex(output_semaphore); @@ -135,7 +136,8 @@ if ((err= snd_pcm_start(output_handle)) < 0) { if (err != -EPIPE) - { +/* if ((err != -EPIPE) & (err != -ESTRPIPE)) +*/ { fprintf(stderr, "snd_pcm_start(1): %s\n", snd_strerror(err)); success(false); return 0; @@ -148,7 +150,8 @@ if ((err= snd_pcm_start(output_handle)) < 0) { if (err != -EPIPE) - { +/* if ((err != -EPIPE) & (err != -ESTRPIPE)) +*/ { fprintf(stderr, "snd_pcm_start(2): %s\n", snd_strerror(err)); success(false); return 0; @@ -199,28 +203,44 @@ static sqInt sound_PlaySamplesFromAtLength(sqInt frameCount, sqInt arrayIndex, sqInt startIndex) { - if (output_handle) - { - void *samples= (void *)arrayIndex + 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= (void *)arrayIndex + 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 recovery 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 recovery from suspend, prepare failed: %s", snd_strerror (err)); } - success(false); + return 0; + } + return 0; } @@ -306,13 +326,28 @@ 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 recovery 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 recovery from suspend, prepare failed: %s", snd_strerror (err)); + } + return 0; + } + + return 0; + } + return count * input_channels; } success(false);