diff --git a/modules/juce_audio_devices/native/juce_win32_Midi.cpp b/modules/juce_audio_devices/native/juce_win32_Midi.cpp index f820dce806..519caf15ec 100644 --- a/modules/juce_audio_devices/native/juce_win32_Midi.cpp +++ b/modules/juce_audio_devices/native/juce_win32_Midi.cpp @@ -679,7 +679,7 @@ public: bool isDefault = false; }; - MidiIODeviceWatcher (ComSmartPtr& comFactory) : factory (comFactory) + MidiIODeviceWatcher (WinRTWrapper::ComPtr& comFactory) : factory (comFactory) { } @@ -894,12 +894,12 @@ public: return {}; } - ComSmartPtr& factory; + WinRTWrapper::ComPtr& factory; EventRegistrationToken deviceAddedToken { 0 }, deviceRemovedToken { 0 }; - ComSmartPtr watcher; + WinRTWrapper::ComPtr watcher; Array connectedDevices; CriticalSection deviceChanges; @@ -913,8 +913,8 @@ public: struct OpenMidiPortThread : public Thread { OpenMidiPortThread (String threadName, String midiDeviceID, - ComSmartPtr& comFactory, - ComSmartPtr& comPort) + WinRTWrapper::ComPtr& comFactory, + WinRTWrapper::ComPtr& comPort) : Thread (threadName), deviceID (midiDeviceID), factory (comFactory), @@ -930,7 +930,7 @@ public: void run() override { WinRTWrapper::ScopedHString hDeviceId (deviceID); - ComSmartPtr> asyncOp; + WinRTWrapper::ComPtr> asyncOp; auto hr = factory->FromIdAsync (hDeviceId.get(), asyncOp.resetAndGetPointerAddress()); if (FAILED (hr)) @@ -959,8 +959,8 @@ public: } const String deviceID; - ComSmartPtr& factory; - ComSmartPtr& port; + WinRTWrapper::ComPtr& factory; + WinRTWrapper::ComPtr& port; WaitableEvent portOpened { true }; }; @@ -1038,19 +1038,19 @@ public: if (! isStarted) return S_OK; - ComSmartPtr message; + WinRTWrapper::ComPtr message; auto hr = args->get_Message (message.resetAndGetPointerAddress()); if (FAILED (hr)) return hr; - ComSmartPtr buffer; + WinRTWrapper::ComPtr buffer; hr = message->get_RawData (buffer.resetAndGetPointerAddress()); if (FAILED (hr)) return hr; - ComSmartPtr bufferByteAccess; + WinRTWrapper::ComPtr bufferByteAccess; hr = buffer->QueryInterface (bufferByteAccess.resetAndGetPointerAddress()); if (FAILED (hr)) @@ -1101,7 +1101,7 @@ public: MidiInputCallback& callback; String deviceName; MidiDataConcatenator concatenator { 4096 }; - ComSmartPtr midiInPort; + WinRTWrapper::ComPtr midiInPort; EventRegistrationToken midiInMessageToken { 0 }; double startTime = 0; @@ -1175,16 +1175,16 @@ public: String getDeviceName() override { return deviceName; } String deviceName; - ComSmartPtr midiOutPort; - ComSmartPtr buffer; - ComSmartPtr bufferByteAccess; + WinRTWrapper::ComPtr midiOutPort; + WinRTWrapper::ComPtr buffer; + WinRTWrapper::ComPtr bufferByteAccess; uint8_t* bufferData = nullptr; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WinRTOutputWrapper); }; - ComSmartPtr midiInFactory; - ComSmartPtr midiOutFactory; + WinRTWrapper::ComPtr midiInFactory; + WinRTWrapper::ComPtr midiOutFactory; std::unique_ptr> inputDeviceWatcher; std::unique_ptr> outputDeviceWatcher; diff --git a/modules/juce_events/juce_events.h b/modules/juce_events/juce_events.h index c7c1ef9c24..bbd88b7744 100644 --- a/modules/juce_events/juce_events.h +++ b/modules/juce_events/juce_events.h @@ -59,6 +59,12 @@ #endif #if JUCE_EVENTS_INCLUDE_WINRT_WRAPPER && JUCE_WINDOWS + // If this header file is missing then you are probably attempting to use WinRT + // functionality without the WinRT libraries installed on your system. Try installing + // the latest Windows Standalone SDK and maybe also adding the path to the WinRT + // headers to your build system. This path should have the form + // "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\winrt". + #include #include #endif diff --git a/modules/juce_events/native/juce_win32_WinRTWrapper.cpp b/modules/juce_events/native/juce_win32_WinRTWrapper.cpp index 2ef390c72b..c90fdaffe0 100644 --- a/modules/juce_events/native/juce_win32_WinRTWrapper.cpp +++ b/modules/juce_events/native/juce_win32_WinRTWrapper.cpp @@ -57,6 +57,7 @@ String WinRTWrapper::hStringToString (HSTRING hstr) WinRTWrapper::WinRTWrapper() { winRTHandle = ::LoadLibraryA ("api-ms-win-core-winrt-l1-1-0"); + if (winRTHandle == nullptr) return; @@ -64,10 +65,11 @@ WinRTWrapper::WinRTWrapper() createHString = (WindowsCreateStringFuncPtr) ::GetProcAddress (winRTHandle, "WindowsCreateString"); deleteHString = (WindowsDeleteStringFuncPtr) ::GetProcAddress (winRTHandle, "WindowsDeleteString"); getHStringRawBuffer = (WindowsGetStringRawBufferFuncPtr) ::GetProcAddress (winRTHandle, "WindowsGetStringRawBuffer"); + roActivateInstance = (RoActivateInstanceFuncPtr) ::GetProcAddress (winRTHandle, "RoActivateInstance"); roGetActivationFactory = (RoGetActivationFactoryFuncPtr) ::GetProcAddress (winRTHandle, "RoGetActivationFactory"); if (roInitialize == nullptr || createHString == nullptr || deleteHString == nullptr - || getHStringRawBuffer == nullptr || roGetActivationFactory == nullptr) + || getHStringRawBuffer == nullptr || roActivateInstance == nullptr || roGetActivationFactory == nullptr) return; HRESULT status = roInitialize (1); diff --git a/modules/juce_events/native/juce_win32_WinRTWrapper.h b/modules/juce_events/native/juce_win32_WinRTWrapper.h index 70097ff9a3..db25d933a8 100644 --- a/modules/juce_events/native/juce_win32_WinRTWrapper.h +++ b/modules/juce_events/native/juce_win32_WinRTWrapper.h @@ -26,8 +26,6 @@ namespace juce class WinRTWrapper : public DeletedAtShutdown { public: - JUCE_DECLARE_SINGLETON (WinRTWrapper, true) - class ScopedHString { public: @@ -43,6 +41,48 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScopedHString) }; + template + class ComPtr + { + public: + ComPtr() noexcept {} + ComPtr (ComClass* obj) : p (obj) { if (p) p->AddRef(); } + ComPtr (const ComPtr& other) : p (other.p) { if (p) p->AddRef(); } + ~ComPtr() { release(); } + + operator ComClass*() const noexcept { return p; } + ComClass& operator*() const noexcept { return *p; } + ComClass* operator->() const noexcept { return p; } + + ComPtr& operator= (ComClass* const newP) + { + if (newP != nullptr) + newP->AddRef(); + + release(); + p = newP; + return *this; + } + + ComPtr& operator= (const ComPtr& newP) { return operator= (newP.p); } + + ComClass** resetAndGetPointerAddress() + { + release(); + p = nullptr; + return &p; + } + + private: + ComClass* p = nullptr; + + void release() { if (p != nullptr) p->Release(); } + + ComClass** operator&() noexcept; // private to avoid it being used accidentally + }; + + JUCE_DECLARE_SINGLETON (WinRTWrapper, true) + ~WinRTWrapper(); String hStringToString (HSTRING); @@ -50,9 +90,27 @@ public: bool isInitialised() const noexcept { return initialised; } template - ComSmartPtr getWRLFactory (const wchar_t* runtimeClassID) + ComPtr activateInstance (const wchar_t* runtimeClassID, REFCLSID classUUID) { - ComSmartPtr comPtr; + ComPtr result; + + if (isInitialised()) + { + ComPtr inspectable; + ScopedHString runtimeClass (runtimeClassID); + auto hr = roActivateInstance (runtimeClass.get(), inspectable.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + inspectable->QueryInterface (classUUID, (void**) result.resetAndGetPointerAddress()); + } + + return result; + } + + template + ComPtr getWRLFactory (const wchar_t* runtimeClassID) + { + ComPtr comPtr; if (isInitialised()) { @@ -75,12 +133,14 @@ private: typedef HRESULT (WINAPI* WindowsCreateStringFuncPtr) (LPCWSTR, UINT32, HSTRING*); typedef HRESULT (WINAPI* WindowsDeleteStringFuncPtr) (HSTRING); typedef PCWSTR (WINAPI* WindowsGetStringRawBufferFuncPtr) (HSTRING, UINT32*); + typedef HRESULT (WINAPI* RoActivateInstanceFuncPtr) (HSTRING, IInspectable**); typedef HRESULT (WINAPI* RoGetActivationFactoryFuncPtr) (HSTRING, REFIID, void**); RoInitializeFuncPtr roInitialize = nullptr; WindowsCreateStringFuncPtr createHString = nullptr; WindowsDeleteStringFuncPtr deleteHString = nullptr; WindowsGetStringRawBufferFuncPtr getHStringRawBuffer = nullptr; + RoActivateInstanceFuncPtr roActivateInstance = nullptr; RoGetActivationFactoryFuncPtr roGetActivationFactory = nullptr; };