diff --git a/modules/juce_audio_devices/juce_audio_devices.cpp b/modules/juce_audio_devices/juce_audio_devices.cpp index d42cbd73a5..789b6cf725 100644 --- a/modules/juce_audio_devices/juce_audio_devices.cpp +++ b/modules/juce_audio_devices/juce_audio_devices.cpp @@ -57,20 +57,8 @@ //============================================================================== #elif JUCE_WINDOWS - #if JUCE_MINGW && JUCE_WASAPI - #warning "WASAPI not currently implemented with mingw..." - #undef JUCE_WASAPI - #endif - #if JUCE_WASAPI - #pragma warning (push) - #pragma warning (disable: 4201) #include - #include - #include - #include - #include - #pragma warning (pop) #endif #if JUCE_ASIO diff --git a/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp b/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp index 43577bf55f..5aae539c53 100644 --- a/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp +++ b/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp @@ -91,85 +91,210 @@ bool check (HRESULT hr) } //============================================================================== -namespace +} + +#if JUCE_MINGW + #define JUCE_COMCLASS(name, guid) \ + struct name; \ + template<> struct UUIDGetter { static CLSID get() { return uuidFromString (guid); } }; \ + struct name + + #define KSDATAFORMAT_SUBTYPE_PCM uuidFromString ("00000001-0000-0010-8000-00aa00389b71") + #define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT uuidFromString ("00000003-0000-0010-8000-00aa00389b71") + + struct PROPERTYKEY + { + GUID fmtid; + DWORD pid; + }; + + WINOLEAPI PropVariantClear (PROPVARIANT*); +#else + #define JUCE_COMCLASS(name, guid) struct __declspec (uuid (guid)) name +#endif + +#define JUCE_IUNKNOWNCLASS(name, guid) JUCE_COMCLASS(name, guid) : public IUnknown +#define JUCE_COMCALL virtual HRESULT STDMETHODCALLTYPE + +enum EDataFlow { - enum EDataFlow - { - eRender = 0, - eCapture = (eRender + 1), - eAll = (eCapture + 1) - }; + eRender = 0, + eCapture = (eRender + 1), + eAll = (eCapture + 1) +}; - enum { DEVICE_STATE_ACTIVE = 1 }; +enum { DEVICE_STATE_ACTIVE = 1 }; - struct __declspec (uuid ("D666063F-1587-4E43-81F1-B948E807363F")) IMMDevice : public IUnknown - { - virtual HRESULT STDMETHODCALLTYPE Activate(REFIID, DWORD, PROPVARIANT*, void**) = 0; - virtual HRESULT STDMETHODCALLTYPE OpenPropertyStore(DWORD, IPropertyStore**) = 0; - virtual HRESULT STDMETHODCALLTYPE GetId(LPWSTR*) = 0; - virtual HRESULT STDMETHODCALLTYPE GetState(DWORD*) = 0; - }; +JUCE_IUNKNOWNCLASS (IPropertyStore, "886d8eeb-8cf2-4446-8d02-cdba1dbdcf99") +{ + JUCE_COMCALL GetCount (DWORD*) = 0; + JUCE_COMCALL GetAt (DWORD, PROPERTYKEY*) = 0; + JUCE_COMCALL GetValue (const PROPERTYKEY&, PROPVARIANT*) = 0; + JUCE_COMCALL SetValue (const PROPERTYKEY&, const PROPVARIANT&) = 0; + JUCE_COMCALL Commit() = 0; +}; - struct __declspec (uuid ("1BE09788-6894-4089-8586-9A2A6C265AC5")) IMMEndpoint : public IUnknown - { - virtual HRESULT STDMETHODCALLTYPE GetDataFlow(EDataFlow*) = 0; - }; +JUCE_IUNKNOWNCLASS (IMMDevice, "D666063F-1587-4E43-81F1-B948E807363F") +{ + JUCE_COMCALL Activate (REFIID, DWORD, PROPVARIANT*, void**) = 0; + JUCE_COMCALL OpenPropertyStore (DWORD, IPropertyStore**) = 0; + JUCE_COMCALL GetId (LPWSTR*) = 0; + JUCE_COMCALL GetState (DWORD*) = 0; +}; - struct IMMDeviceCollection : public IUnknown - { - virtual HRESULT STDMETHODCALLTYPE GetCount(UINT*) = 0; - virtual HRESULT STDMETHODCALLTYPE Item(UINT, IMMDevice**) = 0; - }; +JUCE_IUNKNOWNCLASS (IMMEndpoint, "1BE09788-6894-4089-8586-9A2A6C265AC5") +{ + JUCE_COMCALL GetDataFlow (EDataFlow*) = 0; +}; - enum ERole - { - eConsole = 0, - eMultimedia = (eConsole + 1), - eCommunications = (eMultimedia + 1) - }; +struct IMMDeviceCollection : public IUnknown +{ + JUCE_COMCALL GetCount (UINT*) = 0; + JUCE_COMCALL Item (UINT, IMMDevice**) = 0; +}; - struct __declspec (uuid ("7991EEC9-7E89-4D85-8390-6C703CEC60C0")) IMMNotificationClient : public IUnknown - { - virtual HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR, DWORD) = 0; - virtual HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR) = 0; - virtual HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR) = 0; - virtual HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow, ERole, LPCWSTR) = 0; - virtual HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR, const PROPERTYKEY) = 0; - }; +enum ERole +{ + eConsole = 0, + eMultimedia = (eConsole + 1), + eCommunications = (eMultimedia + 1) +}; - struct __declspec (uuid ("A95664D2-9614-4F35-A746-DE8DB63617E6")) IMMDeviceEnumerator : public IUnknown - { - virtual HRESULT STDMETHODCALLTYPE EnumAudioEndpoints(EDataFlow, DWORD, IMMDeviceCollection**) = 0; - virtual HRESULT STDMETHODCALLTYPE GetDefaultAudioEndpoint(EDataFlow, ERole, IMMDevice**) = 0; - virtual HRESULT STDMETHODCALLTYPE GetDevice(LPCWSTR, IMMDevice**) = 0; - virtual HRESULT STDMETHODCALLTYPE RegisterEndpointNotificationCallback(IMMNotificationClient*) = 0; - virtual HRESULT STDMETHODCALLTYPE UnregisterEndpointNotificationCallback(IMMNotificationClient*) = 0; - }; +JUCE_IUNKNOWNCLASS (IMMNotificationClient, "7991EEC9-7E89-4D85-8390-6C703CEC60C0") +{ + JUCE_COMCALL OnDeviceStateChanged (LPCWSTR, DWORD) = 0; + JUCE_COMCALL OnDeviceAdded (LPCWSTR) = 0; + JUCE_COMCALL OnDeviceRemoved (LPCWSTR) = 0; + JUCE_COMCALL OnDefaultDeviceChanged (EDataFlow, ERole, LPCWSTR) = 0; + JUCE_COMCALL OnPropertyValueChanged (LPCWSTR, const PROPERTYKEY) = 0; +}; - struct __declspec (uuid ("BCDE0395-E52F-467C-8E3D-C4579291692E")) MMDeviceEnumerator; +JUCE_IUNKNOWNCLASS (IMMDeviceEnumerator, "A95664D2-9614-4F35-A746-DE8DB63617E6") +{ + JUCE_COMCALL EnumAudioEndpoints (EDataFlow, DWORD, IMMDeviceCollection**) = 0; + JUCE_COMCALL GetDefaultAudioEndpoint (EDataFlow, ERole, IMMDevice**) = 0; + JUCE_COMCALL GetDevice (LPCWSTR, IMMDevice**) = 0; + JUCE_COMCALL RegisterEndpointNotificationCallback (IMMNotificationClient*) = 0; + JUCE_COMCALL UnregisterEndpointNotificationCallback (IMMNotificationClient*) = 0; +}; - struct __declspec (uuid ("5CDF2C82-841E-4546-9722-0CF74078229A")) IAudioEndpointVolume : public IUnknown - { - virtual HRESULT STDMETHODCALLTYPE RegisterControlChangeNotify (void*) = 0; - virtual HRESULT STDMETHODCALLTYPE UnregisterControlChangeNotify (void*) = 0; - virtual HRESULT STDMETHODCALLTYPE GetChannelCount (UINT*) = 0; - virtual HRESULT STDMETHODCALLTYPE SetMasterVolumeLevel (float, LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE SetMasterVolumeLevelScalar (float, LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE GetMasterVolumeLevel (float*) = 0; - virtual HRESULT STDMETHODCALLTYPE GetMasterVolumeLevelScalar (float*) = 0; - virtual HRESULT STDMETHODCALLTYPE SetChannelVolumeLevel (UINT, float, LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE SetChannelVolumeLevelScalar (UINT, float, LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE GetChannelVolumeLevel (UINT, float*) = 0; - virtual HRESULT STDMETHODCALLTYPE GetChannelVolumeLevelScalar (UINT, float*) = 0; - virtual HRESULT STDMETHODCALLTYPE SetMute (BOOL, LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE GetMute (BOOL*) = 0; - virtual HRESULT STDMETHODCALLTYPE GetVolumeStepInfo (UINT*, UINT*) = 0; - virtual HRESULT STDMETHODCALLTYPE VolumeStepUp (LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE VolumeStepDown (LPCGUID) = 0; - virtual HRESULT STDMETHODCALLTYPE QueryHardwareSupport (DWORD*) = 0; - virtual HRESULT STDMETHODCALLTYPE GetVolumeRange (float*, float*, float*) = 0; - }; -} +JUCE_COMCLASS (MMDeviceEnumerator, "BCDE0395-E52F-467C-8E3D-C4579291692E"); + +typedef LONGLONG REFERENCE_TIME; + +enum AVRT_PRIORITY +{ + AVRT_PRIORITY_LOW = -1, + AVRT_PRIORITY_NORMAL, + AVRT_PRIORITY_HIGH, + AVRT_PRIORITY_CRITICAL +}; + +enum AUDCLNT_SHAREMODE +{ + AUDCLNT_SHAREMODE_SHARED, + AUDCLNT_SHAREMODE_EXCLUSIVE +}; + +JUCE_IUNKNOWNCLASS (IAudioClient, "1CB9AD4C-DBFA-4c32-B178-C2F568A703B2") +{ + JUCE_COMCALL Initialize (AUDCLNT_SHAREMODE, DWORD, REFERENCE_TIME, REFERENCE_TIME, const WAVEFORMATEX*, LPCGUID) = 0; + JUCE_COMCALL GetBufferSize (UINT32*) = 0; + JUCE_COMCALL GetStreamLatency (REFERENCE_TIME*) = 0; + JUCE_COMCALL GetCurrentPadding (UINT32*) = 0; + JUCE_COMCALL IsFormatSupported (AUDCLNT_SHAREMODE, const WAVEFORMATEX*, WAVEFORMATEX**) = 0; + JUCE_COMCALL GetMixFormat (WAVEFORMATEX**) = 0; + JUCE_COMCALL GetDevicePeriod (REFERENCE_TIME*, REFERENCE_TIME*) = 0; + JUCE_COMCALL Start() = 0; + JUCE_COMCALL Stop() = 0; + JUCE_COMCALL Reset() = 0; + JUCE_COMCALL SetEventHandle (HANDLE) = 0; + JUCE_COMCALL GetService (REFIID, void**) = 0; +}; + +JUCE_IUNKNOWNCLASS (IAudioCaptureClient, "C8ADBD64-E71E-48a0-A4DE-185C395CD317") +{ + JUCE_COMCALL GetBuffer (BYTE**, UINT32*, DWORD*, UINT64*, UINT64*) = 0; + JUCE_COMCALL ReleaseBuffer (UINT32) = 0; + JUCE_COMCALL GetNextPacketSize (UINT32*) = 0; +}; + +JUCE_IUNKNOWNCLASS (IAudioRenderClient, "F294ACFC-3146-4483-A7BF-ADDCA7C260E2") +{ + JUCE_COMCALL GetBuffer (UINT32, BYTE**) = 0; + JUCE_COMCALL ReleaseBuffer (UINT32, DWORD) = 0; +}; + +JUCE_IUNKNOWNCLASS (IAudioEndpointVolume, "5CDF2C82-841E-4546-9722-0CF74078229A") +{ + JUCE_COMCALL RegisterControlChangeNotify (void*) = 0; + JUCE_COMCALL UnregisterControlChangeNotify (void*) = 0; + JUCE_COMCALL GetChannelCount (UINT*) = 0; + JUCE_COMCALL SetMasterVolumeLevel (float, LPCGUID) = 0; + JUCE_COMCALL SetMasterVolumeLevelScalar (float, LPCGUID) = 0; + JUCE_COMCALL GetMasterVolumeLevel (float*) = 0; + JUCE_COMCALL GetMasterVolumeLevelScalar (float*) = 0; + JUCE_COMCALL SetChannelVolumeLevel (UINT, float, LPCGUID) = 0; + JUCE_COMCALL SetChannelVolumeLevelScalar (UINT, float, LPCGUID) = 0; + JUCE_COMCALL GetChannelVolumeLevel (UINT, float*) = 0; + JUCE_COMCALL GetChannelVolumeLevelScalar (UINT, float*) = 0; + JUCE_COMCALL SetMute (BOOL, LPCGUID) = 0; + JUCE_COMCALL GetMute (BOOL*) = 0; + JUCE_COMCALL GetVolumeStepInfo (UINT*, UINT*) = 0; + JUCE_COMCALL VolumeStepUp (LPCGUID) = 0; + JUCE_COMCALL VolumeStepDown (LPCGUID) = 0; + JUCE_COMCALL QueryHardwareSupport (DWORD*) = 0; + JUCE_COMCALL GetVolumeRange (float*, float*, float*) = 0; +}; + +enum AudioSessionDisconnectReason +{ + DisconnectReasonDeviceRemoval = 0, + DisconnectReasonServerShutdown = 1, + DisconnectReasonFormatChanged = 2, + DisconnectReasonSessionLogoff = 3, + DisconnectReasonSessionDisconnected = 4, + DisconnectReasonExclusiveModeOverride = 5 +}; + +enum AudioSessionState +{ + AudioSessionStateInactive = 0, + AudioSessionStateActive = 1, + AudioSessionStateExpired = 2 +}; + +JUCE_IUNKNOWNCLASS (IAudioSessionEvents, "24918ACC-64B3-37C1-8CA9-74A66E9957A8") +{ + JUCE_COMCALL OnDisplayNameChanged (LPCWSTR, LPCGUID) = 0; + JUCE_COMCALL OnIconPathChanged (LPCWSTR, LPCGUID) = 0; + JUCE_COMCALL OnSimpleVolumeChanged (float, BOOL, LPCGUID) = 0; + JUCE_COMCALL OnChannelVolumeChanged (DWORD, float*, DWORD, LPCGUID) = 0; + JUCE_COMCALL OnGroupingParamChanged (LPCGUID, LPCGUID) = 0; + JUCE_COMCALL OnStateChanged (AudioSessionState) = 0; + JUCE_COMCALL OnSessionDisconnected (AudioSessionDisconnectReason) = 0; +}; + +JUCE_IUNKNOWNCLASS (IAudioSessionControl, "F4B1A599-7266-4319-A8CA-E70ACB11E8CD") +{ + JUCE_COMCALL GetState (AudioSessionState*) = 0; + JUCE_COMCALL GetDisplayName (LPWSTR*) = 0; + JUCE_COMCALL SetDisplayName (LPCWSTR, LPCGUID) = 0; + JUCE_COMCALL GetIconPath (LPWSTR*) = 0; + JUCE_COMCALL SetIconPath (LPCWSTR, LPCGUID) = 0; + JUCE_COMCALL GetGroupingParam (GUID*) = 0; + JUCE_COMCALL SetGroupingParam (LPCGUID, LPCGUID) = 0; + JUCE_COMCALL RegisterAudioSessionNotification (IAudioSessionEvents*) = 0; + JUCE_COMCALL UnregisterAudioSessionNotification (IAudioSessionEvents*) = 0; +}; + +#undef JUCE_COMCALL +#undef JUCE_COMCLASS +#undef JUCE_IUNKNOWNCLASS + +//============================================================================== +namespace WasapiClasses +{ String getDeviceID (IMMDevice* const device) { @@ -263,7 +388,7 @@ public: } } - ~WASAPIDeviceBase() + virtual ~WASAPIDeviceBase() { device = nullptr; CloseHandle (clientEvent); @@ -345,7 +470,7 @@ private: class SessionEventCallback : public ComBaseClassHelper { public: - SessionEventCallback (WASAPIDeviceBase& owner_) : owner (owner_) {} + SessionEventCallback (WASAPIDeviceBase& d) : owner (d) {} JUCE_COMRESULT OnDisplayNameChanged (LPCWSTR, LPCGUID) { return S_OK; } JUCE_COMRESULT OnIconPathChanged (LPCWSTR, LPCGUID) { return S_OK; } @@ -411,7 +536,8 @@ private: bool tryInitialisingWithFormat (const bool useFloat, const int bytesPerSampleToTry) { - WAVEFORMATEXTENSIBLE format = { 0 }; + WAVEFORMATEXTENSIBLE format; + zerostruct (format); if (numChannels <= 2 && bytesPerSampleToTry <= 2) { @@ -462,7 +588,7 @@ private: GUID session; if (hr == S_OK && check (client->Initialize (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + 0x40000 /*AUDCLNT_STREAMFLAGS_EVENTCALLBACK*/, defaultPeriod, defaultPeriod, (WAVEFORMATEX*) &format, &session))) { actualNumChannels = format.Format.nChannels; @@ -1264,7 +1390,11 @@ private: continue; PROPVARIANT value; - PropVariantInit (&value); + zerostruct (value); + + const PROPERTYKEY PKEY_Device_FriendlyName + = { { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }, 14 }; + if (check (properties->GetValue (PKEY_Device_FriendlyName, &value))) name = value.pwszVal; diff --git a/modules/juce_core/juce_module_info b/modules/juce_core/juce_module_info index 84146b857c..4c5f0e7b63 100644 --- a/modules/juce_core/juce_module_info +++ b/modules/juce_core/juce_module_info @@ -34,5 +34,5 @@ "OSXFrameworks": "Cocoa IOKit", "iOSFrameworks": "Foundation", "LinuxLibs": "rt dl pthread", - "mingwLibs": "uuid wsock32 wininet version ole32 ws2_32 oleaut32 imm32 comdlg32 shlwapi" + "mingwLibs": "uuid wsock32 wininet version ole32 ws2_32 oleaut32 imm32 comdlg32 shlwapi rpcrt4" } diff --git a/modules/juce_core/native/juce_win32_ComSmartPtr.h b/modules/juce_core/native/juce_win32_ComSmartPtr.h index cde5bad86f..1ee3f299d3 100644 --- a/modules/juce_core/native/juce_win32_ComSmartPtr.h +++ b/modules/juce_core/native/juce_win32_ComSmartPtr.h @@ -26,6 +26,17 @@ #ifndef __JUCE_WIN32_COMSMARTPTR_JUCEHEADER__ #define __JUCE_WIN32_COMSMARTPTR_JUCEHEADER__ +#ifndef _MSC_VER +template struct UUIDGetter { static CLSID get() { jassertfalse; return CLSID(); } }; +#define __uuidof(x) UUIDGetter::get() +#endif + +inline CLSID uuidFromString (const char* s) noexcept +{ + CLSID c; + UuidFromStringA ((unsigned char*) s, &c); + return c; +} //============================================================================== /** A simple COM smart pointer.