diff options
-rw-r--r-- | src/output/plugins/wasapi/WasapiOutputPlugin.cxx | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx index 203896c7a..fed16fbee 100644 --- a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx +++ b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx @@ -181,6 +181,8 @@ class WasapiOutputThread { std::atomic_bool cancel = false; + std::atomic_bool empty = true; + enum class Status : uint32_t { FINISH, PLAY, PAUSE }; alignas(BOOST_LOCKFREE_CACHELINE_BYTES) std::atomic<Status> status = @@ -224,6 +226,8 @@ public: } std::size_t Push(ConstBuffer<void> input) noexcept { + empty.store(false); + std::size_t consumed = spsc_buffer.push(static_cast<const BYTE *>(input.data), input.size); @@ -237,6 +241,24 @@ public: } /** + * Check if the buffer is empty, and if not, wait a bit. + * + * Throws on error. + * + * @return true if the buffer is now empty + */ + bool Drain() { + if (empty) + return true; + + CheckException(); + Wait(); + CheckException(); + + return empty; + } + + /** * Instruct the thread to discard the buffer (and wait for * completion). This needs to be done inside this thread, * because only the consumer thread is allowed to do that. @@ -417,6 +439,7 @@ try { if (cancel.load()) { spsc_buffer.consume_all([](auto &&) {}); cancel.store(false); + empty.store(true); InterruptWaiter(); } @@ -475,6 +498,9 @@ try { const UINT32 write_size = write_in_frames * frame_size; UINT32 new_data_size = 0; new_data_size = spsc_buffer.pop(data, write_size); + if (new_data_size == 0) + empty.store(true); + std::fill_n(data + new_data_size, write_size - new_data_size, 0); InterruptWaiter(); @@ -741,9 +767,15 @@ WasapiOutput::Drain() { assert(thread); - // TODO implement + not_interrupted.test_and_set(); - thread->CheckException(); + while (!thread->Drain()) { + if (!not_interrupted.test_and_set()) + throw AudioOutputInterrupted{}; + } + + /* TODO: this needs to wait until the hardware has really + finished playing */ } void |