aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alc/backends/dsound.cpp15
-rw-r--r--alc/backends/wasapi.cpp67
-rw-r--r--common/comptr.h95
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