-/** @brief Play up to @p frames frames of audio
- *
- * It is always safe to call this function.
- * - If @ref playing is 0 then it will just return
- * - If @ref paused is non-0 then it will just return
- * - If @ref device_state != @ref device_open then it will call activate() and
- * return if it it fails.
- * - If there is not enough audio to play then it play what is available.
- *
- * If there are not enough frames to play then whatever is available is played
- * instead. It is up to mainloop() to ensure that speaker_play() is not called
- * when unreasonably only an small amounts of data is available to play.
- */
-static void speaker_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 paused */
- if(!playable())
- 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;
- /* If the buffer emptied out mark the track as unplayably */
- if(!playing->used && !playing->eof) {
- error(0, "track buffer emptied");
- playing->playable = 0;
- }
- frames -= written_frames;
- return;
-}
-
-/* Notify the server what we're up to. */