[alsa-devel] snd_pcm_writei() return value
Hi,
I have an stupid doubt... The snd_pcm_writei() documentation says: "If the blocking behaviour is selected, then routine waits until all requested bytes are played or put to the playback ring buffer. The count of bytes can be less only if a signal or underrun occurred." and at the same time it says "-EPIPE an underrun occurred" is a possible return value. Then snd_pcm_recover() documentation says: "This functions handles -EINTR (interrupted system call), -EPIPE (overrun or underrun) and -ESTRPIPE (stream is suspended) error codes trying to prepare given stream for next I/O."
So if I want to write the full content of a buffer, would this be valid?:
while(buffer.length > 0) { snd_pcm_sframes_t written = snd_pcm_writei(device.handle, buffer.data, buffer.length); if(written < 0) snd_pcm_recover(device.handle, written, 1); else buffer.length = 0; }
"The count of bytes can be less only if a signal ... occurred." makes me think that if a signal interrups snd_pcm_writei() it will return a value between 0 and buffer.length, but "This functions handles -EINTR (interrupted system call)" makes me think that it will always return -EINTR.
"The count of bytes can be less only if a ... underrun occurred.", even if technically correct, also seems to be against the "-EPIPE an underrun occurred" return value.
So, in the previous code, "if(written < 0)" should be changed by "if(written < buffer.length)"? Anyway, how snd_pcm_recover() handles an -EINTR? If only half the data has been written it can't modify buffer.data to point to the last sample written+1. Perhaps I need a full:
uint32_t *buffer_ptr = buffer.data;
while(buffer.length > 0) { snd_pcm_sframes_t written = snd_pcm_writei(device.handle, buffer_ptr, buffer.length); if(written < 0) { snd_pcm_recover(device.handle, written, 1); } else if(written <= buffer.length) { buffer.length -= written; buffer_ptr += written; } }
? And still, in this case an interrupt would be handled by snd_pcm_recover() (written < 0) or by the "else" code?
Thanks.
On Thu, 21 May 2009, Cristian Morales Vega wrote:
while(buffer.length > 0) { snd_pcm_sframes_t written = snd_pcm_writei(device.handle, buffer_ptr, buffer.length); if(written < 0) { snd_pcm_recover(device.handle, written, 1); } else if(written <= buffer.length) { buffer.length -= written; buffer_ptr += written; } }
This is correct.
? And still, in this case an interrupt would be handled by snd_pcm_recover() (written < 0) or by the "else" code?
-EINTR is just noop in recover() function:
if (err == -EINTR) /* nothing to do, continue */ return 0;
Also check returned value from recover() - if it's negative, other error occured.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
2009/5/21 Jaroslav Kysela perex@perex.cz:
On Thu, 21 May 2009, Cristian Morales Vega wrote:
? And still, in this case an interrupt would be handled by snd_pcm_recover() (written < 0) or by the "else" code?
-EINTR is just noop in recover() function:
if (err == -EINTR) /* nothing to do, continue */ return 0;
But if an interrupt happened, it could be that some samples were written and others no, true? If only -EINTR is returned, how I know how many of them I still need to write? If I write them all again the sound output will be funny.
Cristian Morales Vega wrote:
But if an interrupt happened, it could be that some samples were written and others no, true? If only -EINTR is returned, how I know how many of them I still need to write?
If any samples have been written successfully, snd_pcm_writei() returns that number of samples. You get a negative result only if no samples have been written.
HTH Clemens
participants (3)
-
Clemens Ladisch
-
Cristian Morales Vega
-
Jaroslav Kysela