-static void play(size_t frames) {
- size_t avail_frames, avail_bytes, written_frames;
- ssize_t written_bytes;
-
- /* Make sure there's a track to play and it is not pasued */
- if(!playing || paused)
- return;
- /* Make sure the output device is open */
- if(device_state != device_open) {
- activate();
- if(device_state != device_open)
- return;
- }
- D(("play: play %zu/%zu%s %dHz %db %dc", frames, playing->used / bpf,
- playing->eof ? " EOF" : "",
- config->sample_format.rate,
- config->sample_format.bits,
- config->sample_format.channels));
- /* Figure out how many frames there are available to write */
- if(playing->start + playing->used > sizeof playing->buffer)
- /* The ring buffer is currently wrapped, only play up to the wrap point */
- avail_bytes = (sizeof playing->buffer) - playing->start;
- else
- /* The ring buffer is not wrapped, can play the lot */
- avail_bytes = playing->used;
- avail_frames = avail_bytes / bpf;
- /* Only play up to the requested amount */
- if(avail_frames > frames)
- avail_frames = frames;
- if(!avail_frames)
- return;
- /* Play it, Sam */
- written_frames = backend->play(avail_frames);
- written_bytes = written_frames * bpf;
- /* written_bytes and written_frames had better both be set and correct by
- * this point */
- playing->start += written_bytes;
- playing->used -= written_bytes;
- playing->played += written_frames;
- /* If the pointer is at the end of the buffer (or the buffer is completely
- * empty) wrap it back to the start. */
- if(!playing->used || playing->start == (sizeof playing->buffer))
- playing->start = 0;
- frames -= written_frames;
- return;