diff options
Diffstat (limited to 'src/output')
-rw-r--r-- | src/output/Source.cxx | 8 | ||||
-rw-r--r-- | src/output/Source.hxx | 5 | ||||
-rw-r--r-- | src/output/Thread.cxx | 31 |
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(); } |