mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 23:25:34 +00:00
Fix WASAPI implementation when building in C++ mode.
This commit is contained in:
parent
699b00c427
commit
45cd6a7af2
131
src/wasapi.c
131
src/wasapi.c
|
@ -5,11 +5,94 @@
|
|||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#define INITGUID
|
||||
#define CINTERFACE
|
||||
#define COBJMACROS
|
||||
#define CONST_VTABLE
|
||||
#include <initguid.h>
|
||||
#include <audioclient.h>
|
||||
#include <endpointvolume.h>
|
||||
#include <mmdeviceapi.h>
|
||||
#include <mmreg.h>
|
||||
#include <functiondiscoverykeys_devpkey.h>
|
||||
|
||||
#include "wasapi.h"
|
||||
#include "soundio_private.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
// In C++ mode, IsEqualGUID() takes its arguments by reference
|
||||
#define IS_EQUAL_GUID(a, b) IsEqualGUID(*(a), *(b))
|
||||
#define IS_EQUAL_IID(a, b) IsEqualIID((a), *(b))
|
||||
|
||||
// And some constants are passed by reference
|
||||
#define IID_IAUDIOCLIENT (IID_IAudioClient)
|
||||
#define IID_IMMENDPOINT (IID_IMMEndpoint)
|
||||
#define IID_IAUDIOCLOCKADJUSTMENT (IID_IAudioClockAdjustment)
|
||||
#define IID_IAUDIOSESSIONCONTROL (IID_IAudioSessionControl)
|
||||
#define IID_IAUDIORENDERCLIENT (IID_IAudioRenderClient)
|
||||
#define IID_IMMDEVICEENUMERATOR (IID_IMMDeviceEnumerator)
|
||||
#define IID_IAUDIOCAPTURECLIENT (IID_IAudioCaptureClient)
|
||||
#define CLSID_MMDEVICEENUMERATOR (CLSID_MMDeviceEnumerator)
|
||||
#define PKEY_DEVICE_FRIENDLYNAME (PKEY_Device_FriendlyName)
|
||||
#define PKEY_AUDIOENGINE_DEVICEFORMAT (PKEY_AudioEngine_DeviceFormat)
|
||||
|
||||
// And some GUID are never implemented (Ignoring the INITGUID define)
|
||||
static const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
|
||||
static const IID IID_IMMDeviceEnumerator = {
|
||||
//MIDL_INTERFACE("A95664D2-9614-4F35-A746-DE8DB63617E6")
|
||||
0xa95664d2, 0x9614, 0x4f35, {0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6}
|
||||
};
|
||||
static const IID IID_IMMNotificationClient = {
|
||||
//MIDL_INTERFACE("7991EEC9-7E89-4D85-8390-6C703CEC60C0")
|
||||
0x7991eec9, 0x7e89, 0x4d85, {0x83, 0x90, 0x6c, 0x70, 0x3c, 0xec, 0x60, 0xc0}
|
||||
};
|
||||
static const IID IID_IAudioClient = {
|
||||
//MIDL_INTERFACE("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2")
|
||||
0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2}
|
||||
};
|
||||
static const IID IID_IAudioRenderClient = {
|
||||
//MIDL_INTERFACE("F294ACFC-3146-4483-A7BF-ADDCA7C260E2")
|
||||
0xf294acfc, 0x3146, 0x4483, {0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2}
|
||||
};
|
||||
static const IID IID_IAudioSessionControl = {
|
||||
//MIDL_INTERFACE("F4B1A599-7266-4319-A8CA-E70ACB11E8CD")
|
||||
0xf4b1a599, 0x7266, 0x4319, {0xa8, 0xca, 0xe7, 0x0a, 0xcb, 0x11, 0xe8, 0xcd}
|
||||
};
|
||||
static const IID IID_IAudioSessionEvents = {
|
||||
//MIDL_INTERFACE("24918ACC-64B3-37C1-8CA9-74A66E9957A8")
|
||||
0x24918acc, 0x64b3, 0x37c1, {0x8c, 0xa9, 0x74, 0xa6, 0x6e, 0x99, 0x57, 0xa8}
|
||||
};
|
||||
static const IID IID_IMMEndpoint = {
|
||||
//MIDL_INTERFACE("1BE09788-6894-4089-8586-9A2A6C265AC5")
|
||||
0x1be09788, 0x6894, 0x4089, {0x85, 0x86, 0x9a, 0x2a, 0x6c, 0x26, 0x5a, 0xc5}
|
||||
};
|
||||
static const IID IID_IAudioClockAdjustment = {
|
||||
//MIDL_INTERFACE("f6e4c0a0-46d9-4fb8-be21-57a3ef2b626c")
|
||||
0xf6e4c0a0, 0x46d9, 0x4fb8, {0xbe, 0x21, 0x57, 0xa3, 0xef, 0x2b, 0x62, 0x6c}
|
||||
};
|
||||
static const IID IID_IAudioCaptureClient = {
|
||||
//MIDL_INTERFACE("C8ADBD64-E71E-48a0-A4DE-185C395CD317")
|
||||
0xc8adbd64, 0xe71e, 0x48a0, {0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17}
|
||||
};
|
||||
|
||||
#else
|
||||
#define IS_EQUAL_GUID(a, b) IsEqualGUID((a), (b))
|
||||
#define IS_EQUAL_IID(a, b) IsEqualIID((a), (b))
|
||||
|
||||
#define IID_IAUDIOCLIENT (&IID_IAudioClient)
|
||||
#define IID_IMMENDPOINT (&IID_IMMEndpoint)
|
||||
#define PKEY_DEVICE_FRIENDLYNAME (&PKEY_Device_FriendlyName)
|
||||
#define PKEY_AUDIOENGINE_DEVICEFORMAT (&PKEY_AudioEngine_DeviceFormat)
|
||||
#define CLSID_MMDEVICEENUMERATOR (&CLSID_MMDeviceEnumerator)
|
||||
#define IID_IAUDIOCLOCKADJUSTMENT (&IID_IAudioClockAdjustment)
|
||||
#define IID_IAUDIOSESSIONCONTROL (&IID_IAudioSessionControl)
|
||||
#define IID_IAUDIORENDERCLIENT (&IID_IAudioRenderClient)
|
||||
#define IID_IMMDEVICEENUMERATOR (&IID_IMMDeviceEnumerator)
|
||||
#define IID_IAUDIOCAPTURECLIENT (&IID_IAudioCaptureClient)
|
||||
#endif
|
||||
|
||||
// Attempting to use the Windows-supplied versions of these constants resulted
|
||||
// in `undefined reference` linker errors.
|
||||
const static GUID SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {
|
||||
|
@ -204,8 +287,8 @@ static void from_wave_format_layout(WAVEFORMATEXTENSIBLE *wave_format, struct So
|
|||
|
||||
static enum SoundIoFormat from_wave_format_format(WAVEFORMATEXTENSIBLE *wave_format) {
|
||||
assert(wave_format->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE);
|
||||
bool is_pcm = IsEqualGUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_PCM);
|
||||
bool is_float = IsEqualGUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
|
||||
bool is_pcm = IS_EQUAL_GUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_PCM);
|
||||
bool is_float = IS_EQUAL_GUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
|
||||
|
||||
if (wave_format->Samples.wValidBitsPerSample == wave_format->Format.wBitsPerSample) {
|
||||
if (wave_format->Format.wBitsPerSample == 8) {
|
||||
|
@ -352,7 +435,7 @@ static double from_reference_time(REFERENCE_TIME rt) {
|
|||
}
|
||||
|
||||
static REFERENCE_TIME to_reference_time(double seconds) {
|
||||
return seconds * 10000000.0 + 0.5;
|
||||
return (REFERENCE_TIME)(seconds * 10000000.0 + 0.5);
|
||||
}
|
||||
|
||||
static void destruct_device(struct SoundIoDevicePrivate *dev) {
|
||||
|
@ -707,7 +790,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
IUnknown_Release(rd.audio_client);
|
||||
rd.audio_client = NULL;
|
||||
}
|
||||
if (FAILED(hr = IMMDevice_Activate(rd.mm_device, &IID_IAudioClient,
|
||||
if (FAILED(hr = IMMDevice_Activate(rd.mm_device, IID_IAUDIOCLIENT,
|
||||
CLSCTX_ALL, NULL, (void**)&rd.audio_client)))
|
||||
{
|
||||
deinit_refresh_devices(&rd);
|
||||
|
@ -733,7 +816,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
IMMEndpoint_Release(rd.endpoint);
|
||||
rd.endpoint = NULL;
|
||||
}
|
||||
if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, &IID_IMMEndpoint, (void**)&rd.endpoint))) {
|
||||
if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, IID_IMMENDPOINT, (void**)&rd.endpoint))) {
|
||||
deinit_refresh_devices(&rd);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
|
@ -763,7 +846,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
PropVariantInit(&rd.prop_variant_value);
|
||||
rd.prop_variant_value_inited = true;
|
||||
if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store,
|
||||
&PKEY_Device_FriendlyName, &rd.prop_variant_value)))
|
||||
PKEY_DEVICE_FRIENDLYNAME, &rd.prop_variant_value)))
|
||||
{
|
||||
deinit_refresh_devices(&rd);
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -793,7 +876,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
}
|
||||
PropVariantInit(&rd.prop_variant_value);
|
||||
rd.prop_variant_value_inited = true;
|
||||
if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store, &PKEY_AudioEngine_DeviceFormat,
|
||||
if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store, PKEY_AUDIOENGINE_DEVICEFORMAT,
|
||||
&rd.prop_variant_value)))
|
||||
{
|
||||
deinit_refresh_devices(&rd);
|
||||
|
@ -839,9 +922,9 @@ static int refresh_devices(struct SoundIoPrivate *si) {
|
|||
// Let's pick some reasonable min and max values.
|
||||
rd.device_shared->sample_rate_count = 1;
|
||||
rd.device_shared->sample_rates = &dev_shared->prealloc_sample_rate_range;
|
||||
rd.device_shared->sample_rates[0].min = min(SOUNDIO_MIN_SAMPLE_RATE,
|
||||
rd.device_shared->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE,
|
||||
rd.device_shared->sample_rate_current);
|
||||
rd.device_shared->sample_rates[0].max = max(SOUNDIO_MAX_SAMPLE_RATE,
|
||||
rd.device_shared->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE,
|
||||
rd.device_shared->sample_rate_current);
|
||||
} else {
|
||||
// Shared mode input stream: mix format is all we can do.
|
||||
|
@ -935,8 +1018,8 @@ static void device_thread_run(void *arg) {
|
|||
struct SoundIoWasapi *siw = &si->backend_data.wasapi;
|
||||
int err;
|
||||
|
||||
HRESULT hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
|
||||
CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void**)&siw->device_enumerator);
|
||||
HRESULT hr = CoCreateInstance(CLSID_MMDEVICEENUMERATOR, NULL,
|
||||
CLSCTX_ALL, IID_IMMDEVICEENUMERATOR, (void**)&siw->device_enumerator);
|
||||
if (FAILED(hr)) {
|
||||
shutdown_backend(si, SoundIoErrorSystemResources);
|
||||
return;
|
||||
|
@ -1088,7 +1171,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
struct SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
|
||||
CLSCTX_ALL, NULL, (void**)&osw->audio_client)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1135,7 +1218,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
}
|
||||
IUnknown_Release(osw->audio_client);
|
||||
osw->audio_client = NULL;
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
|
||||
CLSCTX_ALL, NULL, (void**)&osw->audio_client)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1195,7 +1278,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
return SoundIoErrorOpeningDevice;
|
||||
}
|
||||
} else if (osw->need_resample) {
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, &IID_IAudioClockAdjustment,
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAUDIOCLOCKADJUSTMENT,
|
||||
(void**)&osw->audio_clock_adjustment)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1208,7 +1291,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
}
|
||||
|
||||
if (outstream->name) {
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, &IID_IAudioSessionControl,
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAUDIOSESSIONCONTROL,
|
||||
(void **)&osw->audio_session_control)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1225,7 +1308,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
|
|||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, &IID_IAudioRenderClient,
|
||||
if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAUDIORENDERCLIENT,
|
||||
(void **)&osw->audio_render_client)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1250,7 +1333,7 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
|
|||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
int frame_count_min = max(0, (int)osw->min_padding_frames - (int)frames_used);
|
||||
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
|
||||
outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
|
||||
|
||||
if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
|
||||
|
@ -1314,7 +1397,7 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
|
|||
if (osw->writable_frame_count > 0) {
|
||||
if (frames_used == 0 && !reset_buffer)
|
||||
outstream->underflow_callback(outstream);
|
||||
int frame_count_min = max(0, (int)osw->min_padding_frames - (int)frames_used);
|
||||
int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
|
||||
outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
|
||||
}
|
||||
}
|
||||
|
@ -1609,7 +1692,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
|
|||
struct SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
|
||||
CLSCTX_ALL, NULL, (void**)&isw->audio_client)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1657,7 +1740,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
|
|||
}
|
||||
IUnknown_Release(isw->audio_client);
|
||||
isw->audio_client = NULL;
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
|
||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
|
||||
CLSCTX_ALL, NULL, (void**)&isw->audio_client)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1711,7 +1794,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
|
|||
}
|
||||
|
||||
if (instream->name) {
|
||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, &IID_IAudioSessionControl,
|
||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAUDIOSESSIONCONTROL,
|
||||
(void **)&isw->audio_session_control)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1728,7 +1811,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
|
|||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, &IID_IAudioCaptureClient,
|
||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAUDIOCAPTURECLIENT,
|
||||
(void **)&isw->audio_capture_client)))
|
||||
{
|
||||
return SoundIoErrorOpeningDevice;
|
||||
|
@ -1938,7 +2021,7 @@ static int instream_begin_read_wasapi(struct SoundIoPrivate *si, struct SoundIoI
|
|||
isw->read_buf = NULL;
|
||||
}
|
||||
|
||||
isw->read_frame_count = min(*frame_count, isw->read_buf_frames_left);
|
||||
isw->read_frame_count = soundio_int_min(*frame_count, isw->read_buf_frames_left);
|
||||
*frame_count = isw->read_frame_count;
|
||||
|
||||
if (isw->read_buf) {
|
||||
|
@ -2017,7 +2100,7 @@ static inline struct SoundIoPrivate *soundio_MMNotificationClient_si(IMMNotifica
|
|||
static STDMETHODIMP soundio_MMNotificationClient_QueryInterface(IMMNotificationClient *client,
|
||||
REFIID riid, void **ppv)
|
||||
{
|
||||
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMMNotificationClient)) {
|
||||
if (IS_EQUAL_IID(riid, &IID_IUnknown) || IS_EQUAL_IID(riid, &IID_IMMNotificationClient)) {
|
||||
*ppv = client;
|
||||
IUnknown_AddRef(client);
|
||||
return S_OK;
|
||||
|
|
Loading…
Reference in a new issue