X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/f5a03f58e65b08478c3eca469a88a763e2e187b9..d0eff58325f88cf7b66e7e7ef92c8802a45532d5:/server/speaker.c diff --git a/server/speaker.c b/server/speaker.c index 8acd9a6..a6c5f43 100644 --- a/server/speaker.c +++ b/server/speaker.c @@ -1,6 +1,7 @@ /* * This file is part of DisOrder * Copyright (C) 2005, 2006, 2007 Richard Kettlewell + * Portions (C) 2007 Mark Wooding * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -283,6 +284,17 @@ static void maybe_finished(void) { abandon(); } +/** @brief Return nonzero if we want to play some audio + * + * We want to play audio if there is a current track; and it is not paused; and + * it is playable according to the rules for @ref track::playable. + */ +static int playable(void) { + return playing + && !paused + && playing->playable; +} + /** @brief Play up to @p frames frames of audio * * It is always safe to call this function. @@ -293,15 +305,15 @@ static void maybe_finished(void) { * - 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 play() is not called when - * unreasonably only an small amounts of data is available to play. + * 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 play(size_t frames) { +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 pasued */ - if(!playing || paused) + /* 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) { @@ -340,8 +352,10 @@ static void play(size_t frames) { if(!playing->used || playing->start == (sizeof playing->buffer)) playing->start = 0; /* If the buffer emptied out mark the track as unplayably */ - if(!playing->used) + if(!playing->used && !playing->eof) { + error(0, "track buffer emptied"); playing->playable = 0; + } frames -= written_frames; return; } @@ -395,17 +409,6 @@ static const struct speaker_backend *backends[] = { 0 }; -/** @brief Return nonzero if we want to play some audio - * - * We want to play audio if there is a current track; and it is not paused; and - * it is playable according to the rules for @ref track::playable. - */ -static int playable(void) { - return playing - && !paused - && playing->playable; -} - /** @brief Main event loop */ static void mainloop(void) { struct track *t; @@ -465,15 +468,15 @@ static void mainloop(void) { /* We want to play some audio */ if(device_state == device_open) { if(backend->ready()) - play(3 * FRAMES); + speaker_play(3 * FRAMES); } else { /* We must be in _closed or _error, and it should be the latter, but we * cope with either. * - * We most likely timed out, so now is a good time to retry. play() - * knows to re-activate the device if necessary. + * We most likely timed out, so now is a good time to retry. + * speaker_play() knows to re-activate the device if necessary. */ - play(3 * FRAMES); + speaker_play(3 * FRAMES); } } /* Perhaps a connection has arrived */ @@ -527,9 +530,9 @@ static void mainloop(void) { error(0, "cannot play track because no connection arrived"); playing = t; /* We attempt to play straight away rather than going round the loop. - * play() is clever enough to perform any activation that is + * speaker_play() is clever enough to perform any activation that is * required. */ - play(3 * FRAMES); + speaker_play(3 * FRAMES); report(); break; case SM_PAUSE: @@ -543,7 +546,7 @@ static void mainloop(void) { paused = 0; /* As for SM_PLAY we attempt to play straight away. */ if(playing) - play(3 * FRAMES); + speaker_play(3 * FRAMES); } report(); break;