From faf2eeaa99f8fda3afffc13720cee3d65e845264 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Tue, 5 Jul 2016 19:27:40 +0200
Subject: [PATCH] decoder/flac: evaluate all possible
 FLAC__stream_decoder_get_state() values

Stop after all fatal errors.  This fixes assertion failures in
libFLAC.
---
 NEWS                                      |  2 ++
 src/decoder/plugins/FlacDecoderPlugin.cxx | 28 +++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 3260b0142..8ae416442 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,6 @@
 ver 0.19.17 (not yet released)
+* decoder
+  - flac: fix assertion failure while seeking
 * fix spurious seek error "Failed to allocate silence buffer"
 * replay gain: fix "replay_gain_handler mixer" setting
 * DSD: use 0x69 as silence pattern
diff --git a/src/decoder/plugins/FlacDecoderPlugin.cxx b/src/decoder/plugins/FlacDecoderPlugin.cxx
index eea813401..003e98975 100644
--- a/src/decoder/plugins/FlacDecoderPlugin.cxx
+++ b/src/decoder/plugins/FlacDecoderPlugin.cxx
@@ -194,10 +194,34 @@ flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec,
 				decoder_command_finished(decoder);
 			} else
 				decoder_seek_error(decoder);
-		} else if (cmd == DecoderCommand::STOP ||
-			   FLAC__stream_decoder_get_state(flac_dec) == FLAC__STREAM_DECODER_END_OF_STREAM)
+		} else if (cmd == DecoderCommand::STOP)
 			break;
 
+		switch (FLAC__stream_decoder_get_state(flac_dec)) {
+		case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
+		case FLAC__STREAM_DECODER_READ_METADATA:
+		case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
+		case FLAC__STREAM_DECODER_READ_FRAME:
+			/* continue decoding */
+			break;
+
+		case FLAC__STREAM_DECODER_END_OF_STREAM:
+			/* regular end of stream */
+			return;
+
+		case FLAC__STREAM_DECODER_OGG_ERROR:
+		case FLAC__STREAM_DECODER_SEEK_ERROR:
+		case FLAC__STREAM_DECODER_ABORTED:
+		case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
+			/* an error, fatal enough for us to abort the
+			   decoder */
+			return;
+
+		case FLAC__STREAM_DECODER_UNINITIALIZED:
+			/* we shouldn't see this, ever - bail out */
+			return;
+		}
+
 		if (t_end != 0 && data->next_frame >= t_end)
 			/* end of this sub track */
 			break;