From 45cd6a7af2a809b897bf0379cbdfd27e19b5fa0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Londeix?= Date: Mon, 7 Dec 2015 03:31:14 +0100 Subject: [PATCH] Fix WASAPI implementation when building in C++ mode. --- src/wasapi.c | 131 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 24 deletions(-) diff --git a/src/wasapi.c b/src/wasapi.c index 46c2a2e..11e7c07 100644 --- a/src/wasapi.c +++ b/src/wasapi.c @@ -5,11 +5,94 @@ * See http://opensource.org/licenses/MIT */ +#define INITGUID +#define CINTERFACE +#define COBJMACROS +#define CONST_VTABLE +#include +#include +#include +#include +#include +#include + #include "wasapi.h" #include "soundio_private.h" #include +#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;