diff options
-rw-r--r-- | alc/backends/dsound.cpp | 15 | ||||
-rw-r--r-- | alc/backends/wasapi.cpp | 67 | ||||
-rw-r--r-- | common/comptr.h | 95 |
3 files changed, 101 insertions, 76 deletions
diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index f549c0fe..51dc36f6 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -347,7 +347,7 @@ void DSoundPlayback::open(const char *name) //DirectSound Init code ComPtr<IDirectSound> ds; if(SUCCEEDED(hr)) - hr = DirectSoundCreate(guid, ds.getPtr(), nullptr); + hr = DirectSoundCreate(guid, al::out_ptr(ds), nullptr); if(SUCCEEDED(hr)) hr = ds->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY); if(FAILED(hr)) @@ -460,7 +460,7 @@ retry_open: DSBUFFERDESC DSBDescription{}; DSBDescription.dwSize = sizeof(DSBDescription); DSBDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = mDS->CreateSoundBuffer(&DSBDescription, mPrimaryBuffer.getPtr(), nullptr); + hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mPrimaryBuffer), nullptr); } if(SUCCEEDED(hr)) hr = mPrimaryBuffer->SetFormat(&OutputType.Format); @@ -480,7 +480,7 @@ retry_open: DSBDescription.dwBufferBytes = mDevice->BufferSize * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat = &OutputType.Format; - hr = mDS->CreateSoundBuffer(&DSBDescription, mBuffer.getPtr(), nullptr); + hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mBuffer), nullptr); if(FAILED(hr) && mDevice->FmtType == DevFmtFloat) { mDevice->FmtType = DevFmtShort; @@ -490,12 +490,9 @@ retry_open: if(SUCCEEDED(hr)) { - void *ptr; - hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, &ptr); + hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, al::out_ptr(mNotifies)); if(SUCCEEDED(hr)) { - mNotifies = ComPtr<IDirectSoundNotify>{static_cast<IDirectSoundNotify*>(ptr)}; - uint num_updates{mDevice->BufferSize / mDevice->UpdateSize}; assert(num_updates <= MAX_UPDATES); @@ -679,9 +676,9 @@ void DSoundCapture::open(const char *name) DSCBDescription.lpwfxFormat = &InputType.Format; //DirectSoundCapture Init code - hr = DirectSoundCaptureCreate(guid, mDSC.getPtr(), nullptr); + hr = DirectSoundCaptureCreate(guid, al::out_ptr(mDSC), nullptr); if(SUCCEEDED(hr)) - mDSC->CreateCaptureBuffer(&DSCBDescription, mDSCbuffer.getPtr(), nullptr); + mDSC->CreateCaptureBuffer(&DSCBDescription, al::out_ptr(mDSCbuffer), nullptr); if(SUCCEEDED(hr)) mRing = RingBuffer::Create(mDevice->BufferSize, InputType.Format.nBlockAlign, false); diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index e834eef4..e66656ce 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -199,7 +199,7 @@ NameGUIDPair get_device_name_and_guid(IMMDevice *device) std::string name, guid; ComPtr<IPropertyStore> ps; - HRESULT hr = device->OpenPropertyStore(STGM_READ, ps.getPtr()); + HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); @@ -242,7 +242,7 @@ NameGUIDPair get_device_name_and_guid(IMMDevice *device) EndpointFormFactor get_device_formfactor(IMMDevice *device) { ComPtr<IPropertyStore> ps; - HRESULT hr{device->OpenPropertyStore(STGM_READ, ps.getPtr())}; + HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); @@ -306,7 +306,7 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector<D al::vector<DevMap>{}.swap(list); ComPtr<IMMDeviceCollection> coll; - HRESULT hr{devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, coll.getPtr())}; + HRESULT hr{devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); @@ -319,7 +319,7 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector<D list.reserve(count); ComPtr<IMMDevice> device; - hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, device.getPtr()); + hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); if(SUCCEEDED(hr)) { if(WCHAR *devid{get_device_id(device.get())}) @@ -327,12 +327,12 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector<D add_device(device.get(), devid, list); CoTaskMemFree(devid); } - device = nullptr; } for(UINT i{0};i < count;++i) { - hr = coll->Item(i, device.getPtr()); + device = nullptr; + hr = coll->Item(i, al::out_ptr(device)); if(FAILED(hr)) continue; if(WCHAR *devid{get_device_id(device.get())}) @@ -340,7 +340,6 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector<D add_device(device.get(), devid, list); CoTaskMemFree(devid); } - device = nullptr; } } @@ -598,15 +597,13 @@ int WasapiProxy::messageHandler(std::promise<HRESULT> *promise) case MsgType::EnumeratePlayback: case MsgType::EnumerateCapture: { - void *ptr{}; + ComPtr<IMMDeviceEnumerator> devenum; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr); + IID_IMMDeviceEnumerator, al::out_ptr(devenum)); if(FAILED(hr)) msg.mPromise.set_value(hr); else { - ComPtr<IMMDeviceEnumerator> devenum{static_cast<IMMDeviceEnumerator*>(ptr)}; - if(msg.mType == MsgType::EnumeratePlayback) probe_devices(devenum.get(), eRender, PlaybackDevices); else if(msg.mType == MsgType::EnumerateCapture) @@ -841,17 +838,16 @@ HRESULT WasapiPlayback::openProxy(const char *name) devid = iter->devid.c_str(); } - void *ptr; + ComPtr<IMMDeviceEnumerator> enumerator; ComPtr<IMMDevice> mmdev; HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr)}; + IID_IMMDeviceEnumerator, al::out_ptr(enumerator))}; if(SUCCEEDED(hr)) { - ComPtr<IMMDeviceEnumerator> enumerator{static_cast<IMMDeviceEnumerator*>(ptr)}; if(!devid) - hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, mmdev.getPtr()); + hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, al::out_ptr(mmdev)); else - hr = enumerator->GetDevice(devid, mmdev.getPtr()); + hr = enumerator->GetDevice(devid, al::out_ptr(mmdev)); } if(FAILED(hr)) { @@ -886,14 +882,13 @@ HRESULT WasapiPlayback::resetProxy() { mClient = nullptr; - void *ptr; - HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr)}; + HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, + al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); return hr; } - mClient = ComPtr<IAudioClient>{static_cast<IAudioClient*>(ptr)}; WAVEFORMATEX *wfx; hr = mClient->GetMixFormat(&wfx); @@ -1242,11 +1237,9 @@ HRESULT WasapiPlayback::startProxy() return hr; } - void *ptr; - hr = mClient->GetService(IID_IAudioRenderClient, &ptr); + hr = mClient->GetService(IID_IAudioRenderClient, al::out_ptr(mRender)); if(SUCCEEDED(hr)) { - mRender = ComPtr<IAudioRenderClient>{static_cast<IAudioRenderClient*>(ptr)}; try { mKillNow.store(false, std::memory_order_release); mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerProc), this}; @@ -1516,16 +1509,15 @@ HRESULT WasapiCapture::openProxy(const char *name) devid = iter->devid.c_str(); } - void *ptr; + ComPtr<IMMDeviceEnumerator> enumerator; HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr)}; + IID_IMMDeviceEnumerator, al::out_ptr(enumerator))}; if(SUCCEEDED(hr)) { - ComPtr<IMMDeviceEnumerator> enumerator{static_cast<IMMDeviceEnumerator*>(ptr)}; if(!devid) - hr = enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, mMMDev.getPtr()); + hr = enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, al::out_ptr(mMMDev)); else - hr = enumerator->GetDevice(devid, mMMDev.getPtr()); + hr = enumerator->GetDevice(devid, al::out_ptr(mMMDev)); } if(FAILED(hr)) { @@ -1550,14 +1542,13 @@ HRESULT WasapiCapture::resetProxy() { mClient = nullptr; - void *ptr; - HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr)}; + HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, + al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); return hr; } - mClient = ComPtr<IAudioClient>{static_cast<IAudioClient*>(ptr)}; WAVEFORMATEX *wfx; hr = mClient->GetMixFormat(&wfx); @@ -1849,11 +1840,9 @@ HRESULT WasapiCapture::startProxy() return hr; } - void *ptr; - hr = mClient->GetService(IID_IAudioCaptureClient, &ptr); + hr = mClient->GetService(IID_IAudioCaptureClient, al::out_ptr(mCapture)); if(SUCCEEDED(hr)) { - mCapture = ComPtr<IAudioCaptureClient>{static_cast<IAudioCaptureClient*>(ptr)}; try { mKillNow.store(false, std::memory_order_release); mThread = std::thread{std::mem_fn(&WasapiCapture::recordProc), this}; @@ -1916,19 +1905,15 @@ bool WasapiBackendFactory::init() return hr; } - void *ptr{}; + ComPtr<IMMDeviceEnumerator> enumerator; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr); + IID_IMMDeviceEnumerator, al::out_ptr(enumerator)); if(FAILED(hr)) - { WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - CoUninitialize(); - return hr; - } - static_cast<IMMDeviceEnumerator*>(ptr)->Release(); + enumerator = nullptr; CoUninitialize(); - return S_OK; + return hr; }); InitResult = res.get(); diff --git a/common/comptr.h b/common/comptr.h index cdc6dec0..5a733ea2 100644 --- a/common/comptr.h +++ b/common/comptr.h @@ -2,49 +2,46 @@ #define COMMON_COMPTR_H #include <cstddef> +#include <memory> +#include <type_traits> #include <utility> - -#include "opthelpers.h" - +#include <variant> template<typename T> -class ComPtr { - T *mPtr{nullptr}; +struct ComPtr { + using element_type = T; + + static constexpr bool RefIsNoexcept{noexcept(std::declval<T&>().AddRef()) + && noexcept(std::declval<T&>().Release())}; -public: ComPtr() noexcept = default; - ComPtr(const ComPtr &rhs) : mPtr{rhs.mPtr} { if(mPtr) mPtr->AddRef(); } + ComPtr(const ComPtr &rhs) noexcept(RefIsNoexcept) : mPtr{rhs.mPtr} + { if(mPtr) mPtr->AddRef(); } ComPtr(ComPtr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; } ComPtr(std::nullptr_t) noexcept { } explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { } ~ComPtr() { if(mPtr) mPtr->Release(); } - ComPtr& operator=(const ComPtr &rhs) + ComPtr& operator=(const ComPtr &rhs) noexcept(RefIsNoexcept) { - if(!rhs.mPtr) + if constexpr(RefIsNoexcept) { - if(mPtr) - mPtr->Release(); - mPtr = nullptr; + if(rhs.mPtr) rhs.mPtr->AddRef(); + if(mPtr) mPtr->Release(); + mPtr = rhs.mPtr; + return *this; } else { - rhs.mPtr->AddRef(); - try { - if(mPtr) - mPtr->Release(); - mPtr = rhs.mPtr; - } - catch(...) { - rhs.mPtr->Release(); - throw; - } + ComPtr tmp{rhs}; + if(mPtr) mPtr->Release(); + mPtr = tmp.release(); + return *this; } - return *this; } - ComPtr& operator=(ComPtr&& rhs) + ComPtr& operator=(ComPtr&& rhs) noexcept(RefIsNoexcept) { - if(&rhs != this) LIKELY + if(&rhs != this) { if(mPtr) mPtr->Release(); mPtr = std::exchange(rhs.mPtr, nullptr); @@ -52,17 +49,63 @@ public: return *this; } + void reset(T *ptr=nullptr) noexcept(RefIsNoexcept) + { + if(mPtr) mPtr->Release(); + mPtr = ptr; + } + explicit operator bool() const noexcept { return mPtr != nullptr; } T& operator*() const noexcept { return *mPtr; } T* operator->() const noexcept { return mPtr; } T* get() const noexcept { return mPtr; } - T** getPtr() noexcept { return &mPtr; } T* release() noexcept { return std::exchange(mPtr, nullptr); } void swap(ComPtr &rhs) noexcept { std::swap(mPtr, rhs.mPtr); } void swap(ComPtr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); } + +private: + T *mPtr{nullptr}; }; + +namespace al { + +template<typename SP, typename PT, typename ...Args> +class out_ptr_t { + static_assert(!std::is_same_v<PT,void*>); + + SP &mRes; + std::variant<PT,void*> mPtr{}; + +public: + out_ptr_t(SP &res) : mRes{res} { } + ~out_ptr_t() + { + auto set_res = [this](auto &ptr) + { mRes.reset(static_cast<PT>(ptr)); }; + std::visit(set_res, mPtr); + } + out_ptr_t(const out_ptr_t&) = delete; + + out_ptr_t& operator=(const out_ptr_t&) = delete; + + operator PT*() noexcept + { return &std::get<PT>(mPtr); } + + operator void**() noexcept + { return &mPtr.template emplace<void*>(); } +}; + +template<typename T=void, typename SP, typename ...Args> +auto out_ptr(SP &res) +{ + using ptype = typename SP::element_type*; + return out_ptr_t<SP,ptype>{res}; +} + +} // namespace al + #endif |