From 2406152576b512c6fedb4eb3b6d3849448d84e6b Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Sun, 31 Aug 2014 13:58:04 +0200
Subject: [PATCH] output/alsa: fix endless loop at end of file in dsd_usb mode

---
 NEWS                            | 2 ++
 src/output/AlsaOutputPlugin.cxx | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/NEWS b/NEWS
index 22eda0f14..2736762a4 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ ver 0.18.13 (not yet released)
   - dsdiff, dsf: fix endless loop on malformed file
   - ffmpeg: support ffmpeg/libav version 11
   - gme: fix song duration
+* output
+  - alsa: fix endless loop at end of file in dsd_usb mode
 * fix state file saver
 * fix build failure on Darwin
 
diff --git a/src/output/AlsaOutputPlugin.cxx b/src/output/AlsaOutputPlugin.cxx
index 76eea5bd6..f8aae13a1 100644
--- a/src/output/AlsaOutputPlugin.cxx
+++ b/src/output/AlsaOutputPlugin.cxx
@@ -815,7 +815,16 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
 		}
 	}
 
+	const size_t original_size = size;
 	chunk = ad->pcm_export->Export(chunk, size, size);
+	if (size == 0)
+		/* the DoP (DSD over PCM) filter converts two frames
+		   at a time and ignores the last odd frame; if there
+		   was only one frame (e.g. the last frame in the
+		   file), the result is empty; to avoid an endless
+		   loop, bail out here, and pretend the one frame has
+		   been played */
+		return original_size;
 
 	assert(size % ad->out_frame_size == 0);