summaryrefslogtreecommitdiff
path: root/src/output
diff options
context:
space:
mode:
Diffstat (limited to 'src/output')
-rw-r--r--src/output/Source.cxx8
-rw-r--r--src/output/Source.hxx5
-rw-r--r--src/output/Thread.cxx31
3 files changed, 44 insertions, 0 deletions
diff --git a/src/output/Source.cxx b/src/output/Source.cxx
index d6c110a38..fdaff77f2 100644
--- a/src/output/Source.cxx
+++ b/src/output/Source.cxx
@@ -244,3 +244,11 @@ AudioOutputSource::ConsumeData(size_t nbytes) noexcept
if (pending_data.empty())
pipe.Consume(*std::exchange(current_chunk, nullptr));
}
+
+ConstBuffer<void>
+AudioOutputSource::Flush()
+{
+ return filter
+ ? filter->Flush()
+ : nullptr;
+}
diff --git a/src/output/Source.hxx b/src/output/Source.hxx
index 1b26a3378..435ce52b2 100644
--- a/src/output/Source.hxx
+++ b/src/output/Source.hxx
@@ -195,6 +195,11 @@ public:
pipe.ClearTail(chunk);
}
+ /**
+ * Wrapper for Filter::Flush().
+ */
+ ConstBuffer<void> Flush();
+
private:
void OpenFilter(AudioFormat audio_format,
PreparedFilter *prepared_replay_gain_filter,
diff --git a/src/output/Thread.cxx b/src/output/Thread.cxx
index ac382864a..bad9e0a73 100644
--- a/src/output/Thread.cxx
+++ b/src/output/Thread.cxx
@@ -362,11 +362,42 @@ AudioOutputControl::InternalPause() noexcept
skip_delay = true;
}
+static void
+PlayFull(FilteredAudioOutput &output, ConstBuffer<void> _buffer)
+{
+ auto buffer = ConstBuffer<uint8_t>::FromVoid(_buffer);
+
+ while (!buffer.empty()) {
+ size_t nbytes = output.Play(buffer.data, buffer.size);
+ assert(nbytes > 0);
+
+ buffer.skip_front(nbytes);
+ }
+
+}
+
inline void
AudioOutputControl::InternalDrain() noexcept
{
const ScopeUnlock unlock(mutex);
+ try {
+ /* flush the filter and play its remaining output */
+
+ while (true) {
+ auto buffer = source.Flush();
+ if (buffer.IsNull())
+ break;
+
+ PlayFull(*output, buffer);
+ }
+ } catch (...) {
+ FormatError(std::current_exception(),
+ "Failed to flush filter on %s", GetLogName());
+ InternalCloseError(std::current_exception());
+ return;
+ }
+
output->Drain();
}