From 7c952c4f4bb4272cd4082f85960eb65976286aa4 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Apr 2008 05:57:22 +0000 Subject: added ob_set_lazy() In lazy mode (previously the default), outputBuffer.c only wakes up the player when it was previously empty. That caused a deadlock when the player was waiting for buffered_before_play, since the decoder wouldn't wake up the player when buffered_before_play was reached. In non-lazy mode, always wake up the player when a new chunk was decoded. git-svn-id: https://svn.musicpd.org/mpd/trunk@7364 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/decode.c | 8 +++++++- src/outputBuffer.c | 8 +++++++- src/outputBuffer.h | 12 ++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/decode.c b/src/decode.c index c188cd286..297f6110d 100644 --- a/src/decode.c +++ b/src/decode.c @@ -400,6 +400,8 @@ static void decodeParent(void) /** the position of the first chunk in the next song */ int next = -1; + ob_set_lazy(0); + if (waitOnDecode(&decodeWaitedOn) < 0) return; @@ -421,9 +423,11 @@ static void decodeParent(void) /* not enough decoded buffer space yet */ player_sleep(); continue; - } else + } else { /* buffering is complete */ buffering = 0; + ob_set_lazy(1); + } } if (decodeWaitedOn) { @@ -513,6 +517,7 @@ static void decodeParent(void) } nextChunk = ob_absolute(crossFadeChunks); if (nextChunk >= 0) { + ob_set_lazy(1); crossFade(beginChunk, ob_get_chunk(nextChunk), &(ob.audioFormat), @@ -529,6 +534,7 @@ static void decodeParent(void) } else { /* wait for the decoder */ + ob_set_lazy(0); player_sleep(); continue; } diff --git a/src/outputBuffer.c b/src/outputBuffer.c index 6732d0e7a..b0cfc00df 100644 --- a/src/outputBuffer.c +++ b/src/outputBuffer.c @@ -31,6 +31,7 @@ void ob_init(unsigned int size) ob.size = size; ob.begin = 0; ob.end = 0; + ob.lazy = 0; ob.chunks[0].chunkSize = 0; } @@ -61,7 +62,7 @@ static inline unsigned successor(unsigned i) */ static void output_buffer_expand(unsigned i) { - int was_empty = ob_is_empty(); + int was_empty = !ob.lazy || ob_is_empty(); assert(i == (ob.end + 1) % ob.size); assert(i != ob.end); @@ -91,6 +92,11 @@ void ob_flush(void) } } +void ob_set_lazy(int lazy) +{ + ob.lazy = lazy; +} + int ob_is_empty(void) { return ob.begin == ob.end; diff --git a/src/outputBuffer.h b/src/outputBuffer.h index 6e9d7c49f..4aea59120 100644 --- a/src/outputBuffer.h +++ b/src/outputBuffer.h @@ -53,6 +53,10 @@ typedef struct _OutputBuffer { /** the index after the last decoded chunk */ unsigned int volatile end; + /** non-zero if the player thread should only we woken up if + the buffer becomes non-empty */ + int lazy; + AudioFormat audioFormat; ConvState convState; } OutputBuffer; @@ -65,6 +69,14 @@ void ob_clear(void); void ob_flush(void); +/** + * When a chunk is decoded, we wake up the player thread to tell him + * about it. In "lazy" mode, we only wake him up when the buffer was + * previously empty, i.e. when the player thread has really been + * waiting for us. + */ +void ob_set_lazy(int lazy); + /** is the buffer empty? */ int ob_is_empty(void); -- cgit v1.2.3