summaryrefslogtreecommitdiff
path: root/src/output/Thread.cxx
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-01-01 19:22:45 +0100
committerMax Kellermann <max@musicpd.org>2018-01-02 23:15:51 +0100
commit6d0d8cf9cf07a5d0905f715be9a79f5de86e8b37 (patch)
tree2fd9692a25b7e80ed67320a395bf0bbed1f9f91c /src/output/Thread.cxx
parent14f669f4fbac72833e622f66f81950b4be3e3c12 (diff)
filter/Filter: add virtual method Flush()
This will be used by filters which have internal buffers which need to be flushed at the end, e.g. the "soxr" resampler.
Diffstat (limited to 'src/output/Thread.cxx')
-rw-r--r--src/output/Thread.cxx31
1 files changed, 31 insertions, 0 deletions
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();
}