win32/ComWorker: make COMWorker a real class, no static members
This commit is contained in:
parent
e1fe9ebcd6
commit
90d97053a8
|
@ -44,7 +44,11 @@ public:
|
|||
void Close() noexcept override {}
|
||||
|
||||
int GetVolume() override {
|
||||
auto future = COMWorker::Async([&]() -> int {
|
||||
auto com_worker = wasapi_output_get_com_worker(output);
|
||||
if (!com_worker)
|
||||
return -1;
|
||||
|
||||
auto future = com_worker->Async([&]() -> int {
|
||||
HRESULT result;
|
||||
float volume_level;
|
||||
|
||||
|
@ -76,7 +80,11 @@ public:
|
|||
}
|
||||
|
||||
void SetVolume(unsigned volume) override {
|
||||
COMWorker::Async([&]() {
|
||||
auto com_worker = wasapi_output_get_com_worker(output);
|
||||
if (!com_worker)
|
||||
throw std::runtime_error("Cannot set WASAPI volume");
|
||||
|
||||
com_worker->Async([&]() {
|
||||
HRESULT result;
|
||||
const float volume_level = volume / 100.0f;
|
||||
|
||||
|
|
|
@ -20,10 +20,13 @@
|
|||
#ifndef MPD_WASAPI_OUTPUT_FOR_MIXER_HXX
|
||||
#define MPD_WASAPI_OUTPUT_FOR_MIXER_HXX
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct IMMDevice;
|
||||
struct IAudioClient;
|
||||
class AudioOutput;
|
||||
class WasapiOutput;
|
||||
class COMWorker;
|
||||
|
||||
[[gnu::pure]]
|
||||
WasapiOutput &
|
||||
|
@ -33,6 +36,10 @@ wasapi_output_downcast(AudioOutput &output) noexcept;
|
|||
bool
|
||||
wasapi_is_exclusive(WasapiOutput &output) noexcept;
|
||||
|
||||
[[gnu::pure]]
|
||||
std::shared_ptr<COMWorker>
|
||||
wasapi_output_get_com_worker(WasapiOutput &output) noexcept;
|
||||
|
||||
[[gnu::pure]]
|
||||
IMMDevice *
|
||||
wasapi_output_get_device(WasapiOutput &output) noexcept;
|
||||
|
|
|
@ -214,22 +214,28 @@ class WasapiOutput final : public AudioOutput {
|
|||
public:
|
||||
static AudioOutput *Create(EventLoop &, const ConfigBlock &block);
|
||||
WasapiOutput(const ConfigBlock &block);
|
||||
|
||||
auto GetComWorker() noexcept {
|
||||
// TODO: protect access to the shard_ptr
|
||||
return com_worker;
|
||||
}
|
||||
|
||||
void Enable() override {
|
||||
COMWorker::Aquire();
|
||||
com_worker = std::make_shared<COMWorker>();
|
||||
|
||||
try {
|
||||
COMWorker::Async([&]() { OpenDevice(); }).get();
|
||||
com_worker->Async([&]() { OpenDevice(); }).get();
|
||||
} catch (...) {
|
||||
COMWorker::Release();
|
||||
com_worker.reset();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
void Disable() noexcept override {
|
||||
COMWorker::Async([&]() { DoDisable(); }).get();
|
||||
COMWorker::Release();
|
||||
com_worker->Async([&]() { DoDisable(); }).get();
|
||||
com_worker.reset();
|
||||
}
|
||||
void Open(AudioFormat &audio_format) override {
|
||||
COMWorker::Async([&]() { DoOpen(audio_format); }).get();
|
||||
com_worker->Async([&]() { DoOpen(audio_format); }).get();
|
||||
}
|
||||
void Close() noexcept override;
|
||||
std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||
|
@ -253,6 +259,7 @@ private:
|
|||
bool dop_setting;
|
||||
#endif
|
||||
std::string device_config;
|
||||
std::shared_ptr<COMWorker> com_worker;
|
||||
ComPtr<IMMDeviceEnumerator> enumerator;
|
||||
ComPtr<IMMDevice> device;
|
||||
ComPtr<IAudioClient> client;
|
||||
|
@ -283,6 +290,12 @@ WasapiOutput &wasapi_output_downcast(AudioOutput &output) noexcept {
|
|||
|
||||
bool wasapi_is_exclusive(WasapiOutput &output) noexcept { return output.is_exclusive; }
|
||||
|
||||
std::shared_ptr<COMWorker>
|
||||
wasapi_output_get_com_worker(WasapiOutput &output) noexcept
|
||||
{
|
||||
return output.GetComWorker();
|
||||
}
|
||||
|
||||
IMMDevice *wasapi_output_get_device(WasapiOutput &output) noexcept {
|
||||
return output.device.get();
|
||||
}
|
||||
|
@ -524,7 +537,7 @@ void WasapiOutput::Close() noexcept {
|
|||
assert(thread);
|
||||
|
||||
try {
|
||||
COMWorker::Async([&]() {
|
||||
com_worker->Async([&]() {
|
||||
Stop(*client);
|
||||
}).get();
|
||||
thread->CheckException();
|
||||
|
@ -535,7 +548,7 @@ void WasapiOutput::Close() noexcept {
|
|||
is_started = false;
|
||||
thread->Finish();
|
||||
thread->Join();
|
||||
COMWorker::Async([&]() {
|
||||
com_worker->Async([&]() {
|
||||
thread.reset();
|
||||
client.reset();
|
||||
}).get();
|
||||
|
@ -586,7 +599,7 @@ size_t WasapiOutput::Play(const void *chunk, size_t size) {
|
|||
if (!is_started) {
|
||||
is_started = true;
|
||||
thread->Play();
|
||||
COMWorker::Async([&]() {
|
||||
com_worker->Async([&]() {
|
||||
Start(*client);
|
||||
}).wait();
|
||||
}
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
#include "Com.hxx"
|
||||
#include "thread/Name.hxx"
|
||||
|
||||
Mutex COMWorker::mutex;
|
||||
unsigned int COMWorker::reference_count = 0;
|
||||
std::optional<COMWorker::COMWorkerThread> COMWorker::thread;
|
||||
|
||||
void COMWorker::COMWorkerThread::Work() noexcept {
|
||||
SetThreadName("COM Worker");
|
||||
COM com{true};
|
||||
|
|
|
@ -22,12 +22,9 @@
|
|||
|
||||
#include "WinEvent.hxx"
|
||||
#include "thread/Future.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "thread/Thread.hxx"
|
||||
|
||||
#include <boost/lockfree/spsc_queue.hpp>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
@ -56,31 +53,25 @@ private:
|
|||
};
|
||||
|
||||
public:
|
||||
static void Aquire() {
|
||||
std::unique_lock locker(mutex);
|
||||
if (reference_count == 0) {
|
||||
thread.emplace();
|
||||
thread->Start();
|
||||
}
|
||||
++reference_count;
|
||||
}
|
||||
static void Release() noexcept {
|
||||
std::unique_lock locker(mutex);
|
||||
--reference_count;
|
||||
if (reference_count == 0) {
|
||||
thread->Finish();
|
||||
thread->Join();
|
||||
thread.reset();
|
||||
}
|
||||
COMWorker() {
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
~COMWorker() noexcept {
|
||||
thread.Finish();
|
||||
thread.Join();
|
||||
}
|
||||
|
||||
COMWorker(const COMWorker &) = delete;
|
||||
COMWorker &operator=(const COMWorker &) = delete;
|
||||
|
||||
template <typename Function, typename... Args>
|
||||
static auto Async(Function &&function, Args &&...args) {
|
||||
auto Async(Function &&function, Args &&...args) {
|
||||
using R = std::invoke_result_t<std::decay_t<Function>,
|
||||
std::decay_t<Args>...>;
|
||||
auto promise = std::make_shared<Promise<R>>();
|
||||
auto future = promise->get_future();
|
||||
thread->Push([function = std::forward<Function>(function),
|
||||
thread.Push([function = std::forward<Function>(function),
|
||||
args = std::make_tuple(std::forward<Args>(args)...),
|
||||
promise = std::move(promise)]() mutable {
|
||||
try {
|
||||
|
@ -101,9 +92,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
static Mutex mutex;
|
||||
static unsigned int reference_count;
|
||||
static std::optional<COMWorkerThread> thread;
|
||||
COMWorkerThread thread;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue