aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/backends/wasapi.cpp633
1 files changed, 290 insertions, 343 deletions
diff --git a/Alc/backends/wasapi.cpp b/Alc/backends/wasapi.cpp
index 099f9886..d12fbe84 100644
--- a/Alc/backends/wasapi.cpp
+++ b/Alc/backends/wasapi.cpp
@@ -38,12 +38,15 @@
#include <ksmedia.h>
#endif
+#include <atomic>
+#include <thread>
#include <vector>
+#include <string>
+#include <algorithm>
#include "alMain.h"
#include "alu.h"
#include "ringbuffer.h"
-#include "threads.h"
#include "compat.h"
#include "alstring.h"
#include "converter.h"
@@ -73,43 +76,65 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x
/* Scales the given value using 64-bit integer math, ceiling the result. */
-static inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
+static inline ALint64 ScaleCeil(ALint64 val, ALint64 new_scale, ALint64 old_scale)
{
return (val*new_scale + old_scale-1) / old_scale;
}
-typedef struct {
- al_string name;
- al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent.
- WCHAR *devid;
-} DevMap;
-TYPEDEF_VECTOR(DevMap, vector_DevMap)
+namespace {
+
+struct DevMap {
+ std::string name;
+ std::string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent.
+ std::wstring devid;
+
+ template<typename T0, typename T1, typename T2>
+ DevMap(T0&& name_, T1&& guid_, T2&& devid_)
+ : name{std::forward<T0>(name_)}
+ , endpoint_guid{std::forward<T1>(guid_)}
+ , devid{std::forward<T2>(devid_)}
+ { }
+};
-static void clear_devlist(vector_DevMap *list)
+bool checkName(const std::vector<DevMap> &list, const std::string &name)
{
-#define CLEAR_DEVMAP(i) do { \
- AL_STRING_DEINIT((i)->name); \
- AL_STRING_DEINIT((i)->endpoint_guid); \
- free((i)->devid); \
- (i)->devid = nullptr; \
-} while(0)
- VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP);
- VECTOR_RESIZE(*list, 0, 0);
-#undef CLEAR_DEVMAP
+ return std::find_if(list.cbegin(), list.cend(),
+ [&name](const DevMap &entry) -> bool
+ { return entry.name == name; }
+ ) != list.cend();
}
-static vector_DevMap PlaybackDevices;
-static vector_DevMap CaptureDevices;
+std::vector<DevMap> PlaybackDevices;
+std::vector<DevMap> CaptureDevices;
+
+std::string wstr_to_string(const WCHAR *wstr)
+{
+ std::string ret;
-static HANDLE ThreadHdl;
-static DWORD ThreadID;
+ int len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
+ if(len > 0)
+ {
+ ret.resize(len);
+ WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &ret[0], len, nullptr, nullptr);
+ ret.pop_back();
+ }
+
+ return ret;
+}
-typedef struct {
+
+HANDLE ThreadHdl;
+DWORD ThreadID;
+
+struct ThreadRequest {
HANDLE FinishedEvt;
HRESULT result;
-} ThreadRequest;
+};
+
+} // namespace
+
#define WM_USER_First (WM_USER+0)
#define WM_USER_OpenDevice (WM_USER+0)
@@ -144,78 +169,72 @@ static HRESULT WaitForResponse(ThreadRequest *req)
}
-static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid)
+using NameGUIDPair = std::pair<std::string,std::string>;
+static NameGUIDPair get_device_name_and_guid(IMMDevice *device)
{
- IPropertyStore *ps;
- PROPVARIANT pvname;
- PROPVARIANT pvguid;
- HRESULT hr;
-
- alstr_copy_cstr(name, DEVNAME_HEAD);
+ std::string name{DEVNAME_HEAD};
- hr = device->OpenPropertyStore(STGM_READ, &ps);
+ IPropertyStore *ps;
+ HRESULT hr = device->OpenPropertyStore(STGM_READ, &ps);
if(FAILED(hr))
{
WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
- alstr_append_cstr(name, "Unknown Device Name");
- if(guid) alstr_copy_cstr(guid, "Unknown Device GUID");
- return;
+ return { name+"Unknown Device Name", "Unknown Device GUID" };
}
+ PROPVARIANT pvname;
PropVariantInit(&pvname);
hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(DEVPKEY_Device_FriendlyName), &pvname);
if(FAILED(hr))
{
WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr);
- alstr_append_cstr(name, "Unknown Device Name");
+ name += "Unknown Device Name";
}
else if(pvname.vt == VT_LPWSTR)
- alstr_append_wcstr(name, pvname.pwszVal);
+ name += wstr_to_string(pvname.pwszVal);
else
{
WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt);
- alstr_append_cstr(name, "Unknown Device Name");
+ name += "Unknown Device Name";
}
PropVariantClear(&pvname);
- if(guid)
- {
- PropVariantInit(&pvguid);
-
- hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(PKEY_AudioEndpoint_GUID), &pvguid);
- if(FAILED(hr))
- {
- WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr);
- alstr_copy_cstr(guid, "Unknown Device GUID");
- }
- else if(pvguid.vt == VT_LPWSTR)
- alstr_copy_wcstr(guid, pvguid.pwszVal);
- else
- {
- WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt);
- alstr_copy_cstr(guid, "Unknown Device GUID");
- }
+ std::string guid;
+ PROPVARIANT pvguid;
+ PropVariantInit(&pvguid);
- PropVariantClear(&pvguid);
+ hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(PKEY_AudioEndpoint_GUID), &pvguid);
+ if(FAILED(hr))
+ {
+ WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr);
+ guid = "Unknown Device GUID";
+ }
+ else if(pvname.vt == VT_LPWSTR)
+ guid = wstr_to_string(pvname.pwszVal);
+ else
+ {
+ WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt);
+ guid = "Unknown Device GUID";
}
+ PropVariantClear(&pvguid);
ps->Release();
+
+ return {name, guid};
}
static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor)
{
IPropertyStore *ps;
- PROPVARIANT pvform;
- HRESULT hr;
-
- hr = device->OpenPropertyStore(STGM_READ, &ps);
+ HRESULT hr = device->OpenPropertyStore(STGM_READ, &ps);
if(FAILED(hr))
{
WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
return;
}
+ PROPVARIANT pvform;
PropVariantInit(&pvform);
hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(PKEY_AudioEndpoint_FormFactor), &pvform);
@@ -233,50 +252,31 @@ static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfac
}
-static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *list)
+static void add_device(IMMDevice *device, const WCHAR *devid, std::vector<DevMap> &list)
{
- int count = 0;
- al_string tmpname;
- DevMap entry;
-
- AL_STRING_INIT(tmpname);
- AL_STRING_INIT(entry.name);
- AL_STRING_INIT(entry.endpoint_guid);
-
- entry.devid = strdupW(devid);
- get_device_name_and_guid(device, &tmpname, &entry.endpoint_guid);
+ std::string basename, guidstr;
+ std::tie(basename, guidstr) = get_device_name_and_guid(device);
- while(1)
+ int count{1};
+ std::string newname{basename};
+ while(checkName(PlaybackDevices, newname))
{
- const DevMap *iter;
-
- alstr_copy(&entry.name, tmpname);
- if(count != 0)
- {
- char str[64];
- snprintf(str, sizeof(str), " #%d", count+1);
- alstr_append_cstr(&entry.name, str);
- }
-
-#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY);
- if(iter == VECTOR_END(*list)) break;
-#undef MATCH_ENTRY
- count++;
+ newname = basename;
+ newname += " #";
+ newname += std::to_string(++count);
}
+ list.emplace_back(std::move(newname), std::move(guidstr), devid);
+ const DevMap &newentry = list.back();
- TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.endpoint_guid), entry.devid);
- VECTOR_PUSH_BACK(*list, entry);
-
- AL_STRING_DEINIT(tmpname);
+ TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(),
+ newentry.endpoint_guid.c_str(), newentry.devid.c_str());
}
static WCHAR *get_device_id(IMMDevice *device)
{
WCHAR *devid;
- HRESULT hr;
- hr = device->GetId(&devid);
+ HRESULT hr = device->GetId(&devid);
if(FAILED(hr))
{
ERR("Failed to get device id: %lx\n", hr);
@@ -286,28 +286,24 @@ static WCHAR *get_device_id(IMMDevice *device)
return devid;
}
-static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list)
+static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, std::vector<DevMap> &list)
{
IMMDeviceCollection *coll;
- IMMDevice *defdev = nullptr;
- WCHAR *defdevid = nullptr;
- HRESULT hr;
- UINT count;
- UINT i;
-
- hr = devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, &coll);
+ HRESULT hr = devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, &coll);
if(FAILED(hr))
{
ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr);
return hr;
}
- count = 0;
+ IMMDevice *defdev{nullptr};
+ WCHAR *defdevid{nullptr};
+ UINT count{0};
hr = coll->GetCount(&count);
if(SUCCEEDED(hr) && count > 0)
{
- clear_devlist(list);
- VECTOR_RESIZE(*list, 0, count);
+ list.clear();
+ list.reserve(count);
hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, &defdev);
}
@@ -318,15 +314,13 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve
add_device(defdev, defdevid, list);
}
- for(i = 0;i < count;++i)
+ for(UINT i{0};i < count;++i)
{
IMMDevice *device;
- WCHAR *devid;
-
hr = coll->Item(i, &device);
if(FAILED(hr)) continue;
- devid = get_device_id(device);
+ WCHAR *devid = get_device_id(device);
if(devid)
{
if(wcscmp(devid, defdevid) != 0)
@@ -381,14 +375,10 @@ static void ALCwasapiProxy_Destruct(ALCwasapiProxy* UNUSED(self)) { }
static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
{
auto req = reinterpret_cast<ThreadRequest*>(ptr);
- ALuint deviceCount = 0;
- ALCwasapiProxy *proxy;
- HRESULT hr, cohr;
- MSG msg;
TRACE("Starting message thread\n");
- cohr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ HRESULT cohr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(FAILED(cohr))
{
WARN("Failed to initialize COM: 0x%08lx\n", cohr);
@@ -396,7 +386,8 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
return 0;
}
- hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, &ptr);
+ HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IMMDeviceEnumerator, &ptr);
if(FAILED(hr))
{
WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr);
@@ -414,12 +405,14 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
* returning success, otherwise PostThreadMessage may fail if it gets
* called before GetMessage.
*/
+ MSG msg;
PeekMessage(&msg, nullptr, WM_USER, WM_USER, PM_NOREMOVE);
TRACE("Message thread initialization complete\n");
ReturnMsgResponse(req, S_OK);
TRACE("Starting message loop\n");
+ ALuint deviceCount{0};
while(GetMessage(&msg, nullptr, WM_USER_First, WM_USER_Last))
{
TRACE("Got message \"%s\" (0x%04x, lparam=%p, wparam=%p)\n",
@@ -427,6 +420,8 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
MessageStr[msg.message-WM_USER] : "Unknown",
msg.message, (void*)msg.lParam, (void*)msg.wParam
);
+
+ ALCwasapiProxy *proxy{nullptr};
switch(msg.message)
{
case WM_USER_OpenDevice:
@@ -495,9 +490,9 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
if(msg.lParam == ALL_DEVICE_PROBE)
- hr = probe_devices(Enumerator, eRender, &PlaybackDevices);
+ hr = probe_devices(Enumerator, eRender, PlaybackDevices);
else if(msg.lParam == CAPTURE_DEVICE_PROBE)
- hr = probe_devices(Enumerator, eCapture, &CaptureDevices);
+ hr = probe_devices(Enumerator, eCapture, CaptureDevices);
Enumerator->Release();
Enumerator = nullptr;
@@ -524,22 +519,22 @@ typedef struct ALCwasapiPlayback {
DERIVE_FROM_TYPE(ALCbackend);
DERIVE_FROM_TYPE(ALCwasapiProxy);
- WCHAR *devid;
+ std::wstring devid;
- IMMDevice *mmdev;
- IAudioClient *client;
- IAudioRenderClient *render;
- HANDLE NotifyEvent;
+ IMMDevice *mmdev{nullptr};
+ IAudioClient *client{nullptr};
+ IAudioRenderClient *render{nullptr};
+ HANDLE NotifyEvent{nullptr};
- HANDLE MsgEvent;
+ HANDLE MsgEvent{nullptr};
- ATOMIC(UINT32) Padding;
+ std::atomic<UINT32> Padding{0u};
- ATOMIC(int) killNow;
- althrd_t thread;
+ std::atomic<ALenum> killNow{AL_TRUE};
+ std::thread thread;
} ALCwasapiPlayback;
-static int ALCwasapiPlayback_mixerProc(void *arg);
+static int ALCwasapiPlayback_mixerProc(ALCwasapiPlayback *self);
static void ALCwasapiPlayback_Construct(ALCwasapiPlayback *self, ALCdevice *device);
static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self);
@@ -565,23 +560,11 @@ DEFINE_ALCBACKEND_VTABLE(ALCwasapiPlayback);
static void ALCwasapiPlayback_Construct(ALCwasapiPlayback *self, ALCdevice *device)
{
+ new (self) ALCwasapiPlayback{};
SET_VTABLE2(ALCwasapiPlayback, ALCbackend, self);
SET_VTABLE2(ALCwasapiPlayback, ALCwasapiProxy, self);
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
ALCwasapiProxy_Construct(STATIC_CAST(ALCwasapiProxy, self));
-
- self->devid = nullptr;
-
- self->mmdev = nullptr;
- self->client = nullptr;
- self->render = nullptr;
- self->NotifyEvent = nullptr;
-
- self->MsgEvent = nullptr;
-
- ATOMIC_INIT(&self->Padding, 0u);
-
- ATOMIC_INIT(&self->killNow, 0);
}
static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self)
@@ -600,9 +583,6 @@ static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self)
CloseHandle(self->NotifyEvent);
self->NotifyEvent = nullptr;
- free(self->devid);
- self->devid = nullptr;
-
if(self->NotifyEvent != nullptr)
CloseHandle(self->NotifyEvent);
self->NotifyEvent = nullptr;
@@ -610,26 +590,19 @@ static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self)
CloseHandle(self->MsgEvent);
self->MsgEvent = nullptr;
- free(self->devid);
- self->devid = nullptr;
-
ALCwasapiProxy_Destruct(STATIC_CAST(ALCwasapiProxy, self));
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~ALCwasapiPlayback();
}
-FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
+FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(ALCwasapiPlayback *self)
{
- auto self = reinterpret_cast<ALCwasapiPlayback*>(arg);
ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
- IAudioClient *client = self->client;
- IAudioRenderClient *render = self->render;
- UINT32 buffer_len, written;
- ALuint update_size, len;
- BYTE *buffer;
- HRESULT hr;
+ IAudioClient *client{self->client};
+ IAudioRenderClient *render{self->render};
- hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(FAILED(hr))
{
ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr);
@@ -642,10 +615,11 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- update_size = device->UpdateSize;
- buffer_len = update_size * device->NumUpdates;
- while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed))
+ ALuint update_size{device->UpdateSize};
+ UINT32 buffer_len{update_size * device->NumUpdates};
+ while(!self->killNow.load(std::memory_order_relaxed))
{
+ UINT32 written;
hr = client->GetCurrentPadding(&written);
if(FAILED(hr))
{
@@ -655,9 +629,9 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
V0(device->Backend,unlock)();
break;
}
- ATOMIC_STORE(&self->Padding, written, almemory_order_relaxed);
+ self->Padding.store(written, std::memory_order_relaxed);
- len = buffer_len - written;
+ ALuint len{buffer_len - written};
if(len < update_size)
{
DWORD res;
@@ -668,12 +642,13 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
}
len -= len%update_size;
+ BYTE *buffer;
hr = render->GetBuffer(len, &buffer);
if(SUCCEEDED(hr))
{
ALCwasapiPlayback_lock(self);
aluMixData(device, buffer, len);
- ATOMIC_STORE(&self->Padding, written + len, almemory_order_relaxed);
+ self->Padding.store(written + len, std::memory_order_relaxed);
ALCwasapiPlayback_unlock(self);
hr = render->ReleaseBuffer(len, 0);
}
@@ -686,7 +661,7 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
break;
}
}
- ATOMIC_STORE(&self->Padding, 0u, almemory_order_release);
+ self->Padding.store(0u, std::memory_order_release);
CoUninitialize();
return 0;
@@ -748,9 +723,7 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
{
if(deviceName)
{
- const DevMap *iter;
-
- if(VECTOR_SIZE(PlaybackDevices) == 0)
+ if(PlaybackDevices.empty())
{
ThreadRequest req = { self->MsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE))
@@ -758,29 +731,30 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
}
hr = E_FAIL;
-#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \
- alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(PlaybackDevices))
+ auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [deviceName](const DevMap &entry) -> bool
+ { return entry.name == deviceName || entry.endpoint_guid == deviceName; }
+ );
+ if(iter == PlaybackDevices.cend())
{
int len;
if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, nullptr, 0)) > 0)
{
std::vector<WCHAR> wname(len);
MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname.data(), len);
-#define MATCH_NAME(i) (wcscmp((i)->devid, wname.data()) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
-#undef MATCH_NAME
+ iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [&wname](const DevMap &entry) -> bool
+ { return entry.devid == wname.data(); }
+ );
}
}
- if(iter == VECTOR_END(PlaybackDevices))
+ if(iter == PlaybackDevices.cend())
WARN("Failed to find device name matching \"%s\"\n", deviceName);
else
{
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- self->devid = strdupW(iter->devid);
- alstr_copy(&device->DeviceName, iter->name);
+ self->devid = iter->devid;
+ alstr_copy_range(&device->DeviceName, &*iter->name.cbegin(), &*iter->name.cend());
hr = S_OK;
}
}
@@ -788,7 +762,7 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
if(SUCCEEDED(hr))
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
hr = E_FAIL;
if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
@@ -806,8 +780,7 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
CloseHandle(self->MsgEvent);
self->MsgEvent = nullptr;
- free(self->devid);
- self->devid = nullptr;
+ self->devid.clear();
ERR("Device init failed: 0x%08lx\n", hr);
return ALC_INVALID_VALUE;
@@ -826,10 +799,10 @@ static HRESULT ALCwasapiPlayback_openProxy(ALCwasapiPlayback *self)
if(SUCCEEDED(hr))
{
auto Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
- if(!self->devid)
+ if(self->devid.empty())
hr = Enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &self->mmdev);
else
- hr = Enumerator->GetDevice(self->devid, &self->mmdev);
+ hr = Enumerator->GetDevice(self->devid.c_str(), &self->mmdev);
Enumerator->Release();
}
if(SUCCEEDED(hr))
@@ -838,7 +811,11 @@ static HRESULT ALCwasapiPlayback_openProxy(ALCwasapiPlayback *self)
{
self->client = reinterpret_cast<IAudioClient*>(ptr);
if(alstr_empty(device->DeviceName))
- get_device_name_and_guid(self->mmdev, &device->DeviceName, nullptr);
+ {
+ std::string devname;
+ std::tie(devname, std::ignore) = get_device_name_and_guid(self->mmdev);
+ alstr_copy_range(&device->DeviceName, &*devname.cbegin(), &*devname.cend());
+ }
}
if(FAILED(hr))
@@ -866,8 +843,8 @@ static void ALCwasapiPlayback_closeProxy(ALCwasapiPlayback *self)
static ALCboolean ALCwasapiPlayback_reset(ALCwasapiPlayback *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- HRESULT hr = E_FAIL;
+ ThreadRequest req{ self->MsgEvent, 0 };
+ HRESULT hr{E_FAIL};
if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
hr = WaitForResponse(&req);
@@ -1136,8 +1113,8 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
static ALCboolean ALCwasapiPlayback_start(ALCwasapiPlayback *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- HRESULT hr = E_FAIL;
+ ThreadRequest req{ self->MsgEvent, 0 };
+ HRESULT hr{E_FAIL};
if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
hr = WaitForResponse(&req);
@@ -1153,45 +1130,48 @@ static HRESULT ALCwasapiPlayback_startProxy(ALCwasapiPlayback *self)
ResetEvent(self->NotifyEvent);
hr = self->client->Start();
if(FAILED(hr))
+ {
ERR("Failed to start audio client: 0x%08lx\n", hr);
+ return hr;
+ }
- if(SUCCEEDED(hr))
- hr = self->client->GetService(IID_IAudioRenderClient, &ptr);
+ hr = self->client->GetService(IID_IAudioRenderClient, &ptr);
if(SUCCEEDED(hr))
{
self->render = reinterpret_cast<IAudioRenderClient*>(ptr);
- ATOMIC_STORE(&self->killNow, 0, almemory_order_release);
- if(althrd_create(&self->thread, ALCwasapiPlayback_mixerProc, self) != althrd_success)
- {
- if(self->render)
- self->render->Release();
+ try {
+ self->killNow.store(AL_FALSE, std::memory_order_release);
+ self->thread = std::thread(ALCwasapiPlayback_mixerProc, self);
+ }
+ catch(...) {
+ self->render->Release();
self->render = nullptr;
- self->client->Stop();
ERR("Failed to start thread\n");
hr = E_FAIL;
}
}
+ if(FAILED(hr))
+ self->client->Stop();
+
return hr;
}
static void ALCwasapiPlayback_stop(ALCwasapiPlayback *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
(void)WaitForResponse(&req);
}
static void ALCwasapiPlayback_stopProxy(ALCwasapiPlayback *self)
{
- int res;
-
- if(!self->render)
+ if(!self->render || !self->thread.joinable())
return;
- ATOMIC_STORE_SEQ(&self->killNow, 1);
- althrd_join(self->thread, &res);
+ self->killNow.store(AL_TRUE);
+ self->thread.join();
self->render->Release();
self->render = nullptr;
@@ -1206,7 +1186,7 @@ static ClockLatency ALCwasapiPlayback_getClockLatency(ALCwasapiPlayback *self)
ALCwasapiPlayback_lock(self);
ret.ClockTime = GetDeviceClockTime(device);
- ret.Latency = ATOMIC_LOAD(&self->Padding, almemory_order_relaxed) * DEVICE_CLOCK_RES /
+ ret.Latency = self->Padding.load(std::memory_order_relaxed) * DEVICE_CLOCK_RES /
device->Frequency;
ALCwasapiPlayback_unlock(self);
@@ -1218,24 +1198,24 @@ typedef struct ALCwasapiCapture {
DERIVE_FROM_TYPE(ALCbackend);
DERIVE_FROM_TYPE(ALCwasapiProxy);
- WCHAR *devid;
+ std::wstring devid;
- IMMDevice *mmdev;
- IAudioClient *client;
- IAudioCaptureClient *capture;
- HANDLE NotifyEvent;
+ IMMDevice *mmdev{nullptr};
+ IAudioClient *client{nullptr};
+ IAudioCaptureClient *capture{nullptr};
+ HANDLE NotifyEvent{nullptr};
- HANDLE MsgEvent;
+ HANDLE MsgEvent{nullptr};
- ChannelConverter *ChannelConv;
- SampleConverter *SampleConv;
- ll_ringbuffer_t *Ring;
+ ChannelConverter *ChannelConv{nullptr};
+ SampleConverter *SampleConv{nullptr};
+ ll_ringbuffer_t *Ring{nullptr};
- ATOMIC(int) killNow;
- althrd_t thread;
+ std::atomic<int> killNow{AL_TRUE};
+ std::thread thread;
} ALCwasapiCapture;
-static int ALCwasapiCapture_recordProc(void *arg);
+static int ALCwasapiCapture_recordProc(ALCwasapiCapture *self);
static void ALCwasapiCapture_Construct(ALCwasapiCapture *self, ALCdevice *device);
static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self);
@@ -1261,32 +1241,18 @@ DEFINE_ALCBACKEND_VTABLE(ALCwasapiCapture);
static void ALCwasapiCapture_Construct(ALCwasapiCapture *self, ALCdevice *device)
{
+ new (self) ALCwasapiCapture{};
SET_VTABLE2(ALCwasapiCapture, ALCbackend, self);
SET_VTABLE2(ALCwasapiCapture, ALCwasapiProxy, self);
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
ALCwasapiProxy_Construct(STATIC_CAST(ALCwasapiProxy, self));
-
- self->devid = nullptr;
-
- self->mmdev = nullptr;
- self->client = nullptr;
- self->capture = nullptr;
- self->NotifyEvent = nullptr;
-
- self->MsgEvent = nullptr;
-
- self->ChannelConv = nullptr;
- self->SampleConv = nullptr;
- self->Ring = nullptr;
-
- ATOMIC_INIT(&self->killNow, 0);
}
static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self)
{
if(self->MsgEvent)
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
(void)WaitForResponse(&req);
@@ -1304,24 +1270,18 @@ static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self)
DestroySampleConverter(&self->SampleConv);
DestroyChannelConverter(&self->ChannelConv);
- free(self->devid);
- self->devid = nullptr;
-
ALCwasapiProxy_Destruct(STATIC_CAST(ALCwasapiProxy, self));
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~ALCwasapiCapture();
}
-FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
+FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self)
{
- auto self = reinterpret_cast<ALCwasapiCapture*>(arg);
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- IAudioCaptureClient *capture = self->capture;
- ALfloat *samples = nullptr;
- size_t samplesmax = 0;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
+ IAudioCaptureClient *capture{self->capture};
- hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(FAILED(hr))
{
ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr);
@@ -1333,7 +1293,8 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
althrd_setname(althrd_current(), RECORD_THREAD_NAME);
- while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed))
+ std::vector<float> samples;
+ while(!self->killNow.load(std::memory_order_relaxed))
{
UINT32 avail;
DWORD res;
@@ -1352,25 +1313,17 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
ERR("Failed to get capture buffer: 0x%08lx\n", hr);
else
{
- ll_ringbuffer_data_t data[2];
- size_t dstframes = 0;
-
if(self->ChannelConv)
{
- if(samplesmax < numsamples)
- {
- size_t newmax = RoundUp(numsamples, 4096);
- void *tmp = al_calloc(DEF_ALIGN, newmax*2*sizeof(ALfloat));
- al_free(samples);
- samples = reinterpret_cast<ALfloat*>(tmp);
- samplesmax = newmax;
- }
- ChannelConverterInput(self->ChannelConv, rdata, samples, numsamples);
- rdata = (BYTE*)samples;
+ samples.resize(numsamples*2);
+ ChannelConverterInput(self->ChannelConv, rdata, samples.data(), numsamples);
+ rdata = reinterpret_cast<BYTE*>(samples.data());
}
+ ll_ringbuffer_data_t data[2];
ll_ringbuffer_get_write_vector(self->Ring, data);
+ size_t dstframes;
if(self->SampleConv)
{
const ALvoid *srcdata = rdata;
@@ -1423,10 +1376,6 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
}
- al_free(samples);
- samples = nullptr;
- samplesmax = 0;
-
CoUninitialize();
return 0;
}
@@ -1434,7 +1383,7 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *deviceName)
{
- HRESULT hr = S_OK;
+ HRESULT hr{S_OK};
self->NotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
self->MsgEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
@@ -1448,39 +1397,38 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
{
if(deviceName)
{
- const DevMap *iter;
-
- if(VECTOR_SIZE(CaptureDevices) == 0)
+ if(CaptureDevices.empty())
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE))
(void)WaitForResponse(&req);
}
hr = E_FAIL;
-#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \
- alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(CaptureDevices))
+ auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [deviceName](const DevMap &entry) -> bool
+ { return entry.name == deviceName || entry.endpoint_guid == deviceName; }
+ );
+ if(iter == CaptureDevices.cend())
{
int len;
if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, nullptr, 0)) > 0)
{
std::vector<WCHAR> wname(len);
MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname.data(), len);
-#define MATCH_NAME(i) (wcscmp((i)->devid, wname.data()) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
-#undef MATCH_NAME
+ iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [&wname](const DevMap &entry) -> bool
+ { return entry.devid == wname.data(); }
+ );
}
}
- if(iter == VECTOR_END(CaptureDevices))
+ if(iter == CaptureDevices.cend())
WARN("Failed to find device name matching \"%s\"\n", deviceName);
else
{
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- self->devid = strdupW(iter->devid);
- alstr_copy(&device->DeviceName, iter->name);
+ self->devid = iter->devid;
+ alstr_copy_range(&device->DeviceName, &*iter->name.cbegin(), &*iter->name.cend());
hr = S_OK;
}
}
@@ -1488,7 +1436,7 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
if(SUCCEEDED(hr))
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
hr = E_FAIL;
if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
@@ -1506,15 +1454,14 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
CloseHandle(self->MsgEvent);
self->MsgEvent = nullptr;
- free(self->devid);
- self->devid = nullptr;
+ self->devid.clear();
ERR("Device init failed: 0x%08lx\n", hr);
return ALC_INVALID_VALUE;
}
else
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
hr = E_FAIL;
if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
@@ -1535,18 +1482,18 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
static HRESULT ALCwasapiCapture_openProxy(ALCwasapiCapture *self)
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- void *ptr;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
- hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, &ptr);
+ void *ptr;
+ HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IMMDeviceEnumerator, &ptr);
if(SUCCEEDED(hr))
{
auto Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
- if(!self->devid)
+ if(self->devid.empty())
hr = Enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &self->mmdev);
else
- hr = Enumerator->GetDevice(self->devid, &self->mmdev);
+ hr = Enumerator->GetDevice(self->devid.c_str(), &self->mmdev);
Enumerator->Release();
}
if(SUCCEEDED(hr))
@@ -1555,7 +1502,11 @@ static HRESULT ALCwasapiCapture_openProxy(ALCwasapiCapture *self)
{
self->client = reinterpret_cast<IAudioClient*>(ptr);
if(alstr_empty(device->DeviceName))
- get_device_name_and_guid(self->mmdev, &device->DeviceName, nullptr);
+ {
+ std::string devname;
+ std::tie(devname, std::ignore) = get_device_name_and_guid(self->mmdev);
+ alstr_copy_range(&device->DeviceName, &*devname.cbegin(), &*devname.cend());
+ }
}
if(FAILED(hr))
@@ -1583,34 +1534,30 @@ static void ALCwasapiCapture_closeProxy(ALCwasapiCapture *self)
static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- WAVEFORMATEXTENSIBLE OutputType;
- WAVEFORMATEX *wfx = nullptr;
- enum DevFmtType srcType;
- REFERENCE_TIME buf_time;
- UINT32 buffer_len;
- void *ptr = nullptr;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
- if(self->client)
- self->client->Release();
+ IAudioClient *client{self->client};
self->client = nullptr;
+ if(client) client->Release();
+ client = nullptr;
- hr = self->mmdev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr);
+ void *ptr;
+ HRESULT hr{self->mmdev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr)};
if(FAILED(hr))
{
ERR("Failed to reactivate audio client: 0x%08lx\n", hr);
return hr;
}
- self->client = reinterpret_cast<IAudioClient*>(ptr);
+ client = self->client = reinterpret_cast<IAudioClient*>(ptr);
- buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
- device->Frequency);
+ REFERENCE_TIME buf_time{ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
+ device->Frequency)};
// Make sure buffer is at least 100ms in size
buf_time = maxu64(buf_time, REFTIME_PER_SEC/10);
device->UpdateSize = (ALuint)ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) /
device->NumUpdates;
+ WAVEFORMATEXTENSIBLE OutputType;
OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
switch(device->FmtChans)
{
@@ -1678,7 +1625,8 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
OutputType.Format.nBlockAlign;
OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format);
- hr = self->client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx);
+ WAVEFORMATEX *wfx;
+ hr = client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx);
if(FAILED(hr))
{
ERR("Failed to check format support: 0x%08lx\n", hr);
@@ -1711,6 +1659,7 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
wfx = nullptr;
}
+ enum DevFmtType srcType;
if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_PCM))
{
if(OutputType.Format.wBitsPerSample == 8)
@@ -1785,15 +1734,16 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec);
}
- hr = self->client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- buf_time, 0, &OutputType.Format, nullptr);
+ hr = client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ buf_time, 0, &OutputType.Format, nullptr);
if(FAILED(hr))
{
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
return hr;
}
- hr = self->client->GetBufferSize(&buffer_len);
+ UINT32 buffer_len;
+ hr = client->GetBufferSize(&buffer_len);
if(FAILED(hr))
{
ERR("Failed to get buffer size: 0x%08lx\n", hr);
@@ -1812,7 +1762,7 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
return E_OUTOFMEMORY;
}
- hr = self->client->SetEventHandle(self->NotifyEvent);
+ hr = client->SetEventHandle(self->NotifyEvent);
if(FAILED(hr))
{
ERR("Failed to set event handle: 0x%08lx\n", hr);
@@ -1825,8 +1775,8 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
static ALCboolean ALCwasapiCapture_start(ALCwasapiCapture *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- HRESULT hr = E_FAIL;
+ ThreadRequest req{ self->MsgEvent, 0 };
+ HRESULT hr{E_FAIL};
if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
hr = WaitForResponse(&req);
@@ -1836,35 +1786,37 @@ static ALCboolean ALCwasapiCapture_start(ALCwasapiCapture *self)
static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self)
{
- HRESULT hr;
- void *ptr;
-
ResetEvent(self->NotifyEvent);
- hr = self->client->Start();
+
+ IAudioClient *client{self->client};
+ HRESULT hr{client->Start()};
if(FAILED(hr))
{
ERR("Failed to start audio client: 0x%08lx\n", hr);
return hr;
}
- hr = self->client->GetService(IID_IAudioCaptureClient, &ptr);
+ void *ptr;
+ hr = client->GetService(IID_IAudioCaptureClient, &ptr);
if(SUCCEEDED(hr))
{
self->capture = reinterpret_cast<IAudioCaptureClient*>(ptr);
- ATOMIC_STORE(&self->killNow, 0, almemory_order_release);
- if(althrd_create(&self->thread, ALCwasapiCapture_recordProc, self) != althrd_success)
- {
- ERR("Failed to start thread\n");
+ try {
+ self->killNow.store(AL_FALSE, std::memory_order_release);
+ self->thread = std::thread(ALCwasapiCapture_recordProc, self);
+ }
+ catch(...) {
self->capture->Release();
self->capture = nullptr;
+ ERR("Failed to start thread\n");
hr = E_FAIL;
}
}
if(FAILED(hr))
{
- self->client->Stop();
- self->client->Reset();
+ client->Stop();
+ client->Reset();
}
return hr;
@@ -1873,20 +1825,18 @@ static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self)
static void ALCwasapiCapture_stop(ALCwasapiCapture *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->MsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
(void)WaitForResponse(&req);
}
static void ALCwasapiCapture_stopProxy(ALCwasapiCapture *self)
{
- int res;
-
- if(!self->capture)
+ if(!self->capture || !self->thread.joinable())
return;
- ATOMIC_STORE_SEQ(&self->killNow, 1);
- althrd_join(self->thread, &res);
+ self->killNow.store(AL_TRUE);
+ self->thread.join();
self->capture->Release();
self->capture = nullptr;
@@ -1895,12 +1845,12 @@ static void ALCwasapiCapture_stopProxy(ALCwasapiCapture *self)
}
-ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self)
+static ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self)
{
return (ALuint)ll_ringbuffer_read_space(self->Ring);
}
-ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples)
+static ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples)
{
if(ALCwasapiCapture_availableSamples(self) < samples)
return ALC_INVALID_VALUE;
@@ -1912,7 +1862,7 @@ ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer,
typedef struct ALCwasapiBackendFactory {
DERIVE_FROM_TYPE(ALCbackendFactory);
} ALCwasapiBackendFactory;
-#define ALCWASAPIBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCwasapiBackendFactory, ALCbackendFactory) } }
+#define ALCWASAPIBACKENDFACTORY_INITIALIZER { GET_VTABLE2(ALCwasapiBackendFactory, ALCbackendFactory) }
static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory *self);
static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory *self);
@@ -1927,9 +1877,6 @@ static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory* UNUSED(s
{
static HRESULT InitResult;
- VECTOR_INIT(PlaybackDevices);
- VECTOR_INIT(CaptureDevices);
-
if(!ThreadHdl)
{
ThreadRequest req;
@@ -1952,11 +1899,8 @@ static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory* UNUSED(s
static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory* UNUSED(self))
{
- clear_devlist(&PlaybackDevices);
- VECTOR_DEINIT(PlaybackDevices);
-
- clear_devlist(&CaptureDevices);
- VECTOR_DEINIT(CaptureDevices);
+ PlaybackDevices.clear();
+ CaptureDevices.clear();
if(ThreadHdl)
{
@@ -1976,31 +1920,34 @@ static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory*
static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
{
- ThreadRequest req = { nullptr, 0 };
+ ThreadRequest req{ nullptr, 0 };
req.FinishedEvt = CreateEventW(nullptr, FALSE, FALSE, nullptr);
if(req.FinishedEvt == nullptr)
ERR("Failed to create event: %lu\n", GetLastError());
else
{
+ auto add_device = [outnames](const DevMap &entry) -> void
+ {
+ const char *name{entry.name.c_str()};
+ size_t namelen{entry.name.length()};
+ /* +1 to also append the null char (to ensure a null-separated list
+ * and double-null terminated list).
+ */
+ alstr_append_range(outnames, name, name + namelen+1);
+ };
HRESULT hr = E_FAIL;
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
hr = WaitForResponse(&req);
if(SUCCEEDED(hr)) switch(type)
{
-#define APPEND_OUTNAME(e) do { \
- if(!alstr_empty((e)->name)) \
- alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \
- VECTOR_END((e)->name)+1); \
-} while(0)
case ALL_DEVICE_PROBE:
- VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME);
+ std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
break;
case CAPTURE_DEVICE_PROBE:
- VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME);
+ std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
break;
-#undef APPEND_OUTNAME
}
CloseHandle(req.FinishedEvt);
req.FinishedEvt = nullptr;
@@ -2030,6 +1977,6 @@ static ALCbackend* ALCwasapiBackendFactory_createBackend(ALCwasapiBackendFactory
ALCbackendFactory *ALCwasapiBackendFactory_getFactory(void)
{
- static ALCwasapiBackendFactory factory = ALCWASAPIBACKENDFACTORY_INITIALIZER;
+ static ALCwasapiBackendFactory factory{ALCWASAPIBACKENDFACTORY_INITIALIZER};
return STATIC_CAST(ALCbackendFactory, &factory);
}