diff --git a/modules/juce_audio_devices/native/juce_win32_Midi.cpp b/modules/juce_audio_devices/native/juce_win32_Midi.cpp index bb4f3d7286..480b53b6c5 100644 --- a/modules/juce_audio_devices/native/juce_win32_Midi.cpp +++ b/modules/juce_audio_devices/native/juce_win32_Midi.cpp @@ -64,10 +64,10 @@ struct MidiServiceType }; //============================================================================== -class WindowsMidiService : public MidiServiceType +class WindowsMidiService : public MidiServiceType { private: - struct WindowsInputWrapper : public InputWrapper + struct WindowsInputWrapper : public InputWrapper { class MidiInCollector { @@ -75,7 +75,7 @@ private: MidiInCollector (WindowsMidiService& s, MidiInput* const inputDevice, MidiInputCallback& cb) - : service (s), + : midiService (s), input (inputDevice), callback (cb) { @@ -124,7 +124,7 @@ private: { if (deviceHandle != 0 && ! isStarted) { - service.activeMidiCollectors.addIfNotAlreadyThere (this); + midiService.activeMidiCollectors.addIfNotAlreadyThere (this); for (int i = 0; i < (int) numHeaders; ++i) { @@ -154,7 +154,7 @@ private: isStarted = false; midiInReset (deviceHandle); midiInStop (deviceHandle); - service.activeMidiCollectors.removeFirstMatchingValue (this); + midiService.activeMidiCollectors.removeFirstMatchingValue (this); unprepareAllHeaders(); concatenator.reset(); } @@ -165,7 +165,7 @@ private: { MidiInCollector* const collector = reinterpret_cast (dwInstance); - if (collector->service.activeMidiCollectors.contains (collector)) + if (collector->midiService.activeMidiCollectors.contains (collector)) { if (uMsg == MIM_DATA) collector->handleMessage ((const uint8*) &midiMessage, (uint32) timeStamp); @@ -177,7 +177,7 @@ private: HMIDIIN deviceHandle = 0; private: - WindowsMidiService& service; + WindowsMidiService& midiService; MidiInput* input; MidiInputCallback& callback; MidiDataConcatenator concatenator { 4096 }; @@ -341,7 +341,7 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsInputWrapper) }; - struct WindowsOutputWrapper : public OutputWrapper + struct WindowsOutputWrapper : public OutputWrapper { struct MidiOutHandle { @@ -571,7 +571,7 @@ using namespace ABI::Windows::Devices::Midi; using namespace ABI::Windows::Devices::Enumeration; using namespace ABI::Windows::Storage::Streams; -class WinRTMidiService : public MidiServiceType +class WinRTMidiService : public MidiServiceType { private: template @@ -609,25 +609,49 @@ private: if (FAILED (hr)) return false; - hr = watcher->add_Added ( - Callback>( - [this] (IDeviceWatcher*, IDeviceInformation* info) { return addDevice (info); } - ).Get(), - &deviceAddedToken); - if (FAILED (hr)) - return false; + class DeviceEnumerationThread : public Thread + { + public: + DeviceEnumerationThread (String threadName, MidiIODeviceWatcher& p) + : Thread (threadName), parent (p) + {} - hr = watcher->add_Removed ( - Callback>( - [this] (IDeviceWatcher*, IDeviceInformationUpdate* info) { return removeDevice (info); } - ).Get(), - &deviceRemovedToken); - if (FAILED (hr)) - return false; + void run() override + { + parent.watcher->add_Added ( + Callback> ( + [this](IDeviceWatcher*, IDeviceInformation* info) { return parent.addDevice (info); } + ).Get(), + &parent.deviceAddedToken); + + parent.watcher->add_Removed ( + Callback> ( + [this](IDeviceWatcher*, IDeviceInformationUpdate* info) { return parent.removeDevice (info); } + ).Get(), + &parent.deviceRemovedToken); + + EventRegistrationToken deviceEnumerationCompletedToken { 0 }; + parent.watcher->add_EnumerationCompleted ( + Callback> ( + [this](IDeviceWatcher*, IInspectable*) { enumerationCompleted.signal(); return S_OK; } + ).Get(), + &deviceEnumerationCompletedToken); + + parent.watcher->Start(); + enumerationCompleted.wait(); + + if (deviceEnumerationCompletedToken.value != 0) + parent.watcher->remove_EnumerationCompleted (deviceEnumerationCompletedToken); + } - hr = watcher->Start(); - if (FAILED (hr)) - return false; + private: + MidiIODeviceWatcher& parent; + WaitableEvent enumerationCompleted; + }; + + DeviceEnumerationThread enumerationThread ("WinRT Device Enumeration Thread", *this); + enumerationThread.startThread(); + enumerationThread.waitForThreadToExit (4000); return true; } @@ -741,10 +765,8 @@ private: { auto& lastDevices = lastQueriedConnectedDevices.get(); for (int i = 0; i < lastDevices.size(); ++i) - { if (lastDevices[i].isDefault) return i; - } return 0; } @@ -770,9 +792,11 @@ private: ComSmartPtr& factory; - EventRegistrationToken deviceAddedToken { 0 }, deviceRemovedToken { 0 }; + EventRegistrationToken deviceAddedToken { 0 }, + deviceRemovedToken { 0 }; ComSmartPtr watcher; + Array connectedDevices; CriticalSection deviceChanges; ThreadLocalValue> lastQueriedConnectedDevices; @@ -781,7 +805,7 @@ private: }; template - class OpenMidiPortThread : public Thread + class OpenMidiPortThread : public Thread { public: OpenMidiPortThread (String threadName, @@ -835,7 +859,7 @@ private: WaitableEvent portOpened { true }; }; - struct WinRTInputWrapper : public InputWrapper + struct WinRTInputWrapper : public InputWrapper { WinRTInputWrapper (WinRTMidiService& service, MidiInput* const input, @@ -980,7 +1004,7 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WinRTInputWrapper); }; - struct WinRTOutputWrapper : public OutputWrapper + struct WinRTOutputWrapper : public OutputWrapper { WinRTOutputWrapper (WinRTMidiService& service, const int index) { @@ -1111,46 +1135,58 @@ public: #endif // JUCE_USE_WINRT_MIDI //============================================================================== - -class MidiService +class MidiService : public DeletedAtShutdown { public: - MidiService() - { - #if JUCE_USE_WINRT_MIDI - try - { - internal = new WinRTMidiService(); - return; - } - catch (std::runtime_error&) - { - } - #endif + ~MidiService(); - internal = new WindowsMidiService(); - } + MidiServiceType* getService(); - MidiServiceType* get() - { - return internal.get(); - } + juce_DeclareSingleton (MidiService, false) private: + MidiService(); + ScopedPointer internal; }; -static MidiService midiService; +juce_ImplementSingleton (MidiService) + +MidiService::~MidiService() +{ + clearSingletonInstance(); +} + +MidiServiceType* MidiService::getService() +{ + return internal.get(); +} + +MidiService::MidiService() +{ + #if JUCE_USE_WINRT_MIDI + try + { + internal = new WinRTMidiService(); + return; + } + catch (std::runtime_error&) + { + } + #endif + + internal = new WindowsMidiService(); +} //============================================================================== StringArray MidiInput::getDevices() { - return midiService.get()->getDevices (true); + return MidiService::getInstance()->getService()->getDevices (true); } int MidiInput::getDefaultDeviceIndex() { - return midiService.get()->getDefaultDeviceIndex (true); + return MidiService::getInstance()->getService()->getDefaultDeviceIndex (true); } MidiInput::MidiInput (const String& deviceName) @@ -1167,7 +1203,7 @@ MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const call ScopedPointer wrapper; try { - wrapper = midiService.get()->createInputWrapper (in, index, callback); + wrapper = MidiService::getInstance()->getService()->createInputWrapper (in, index, callback); } catch (std::runtime_error&) { @@ -1190,12 +1226,12 @@ void MidiInput::stop() { static_cast (interna //============================================================================== StringArray MidiOutput::getDevices() { - return midiService.get()->getDevices (false); + return MidiService::getInstance()->getService()->getDevices (false); } int MidiOutput::getDefaultDeviceIndex() { - return midiService.get()->getDefaultDeviceIndex (false); + return MidiService::getInstance()->getService()->getDefaultDeviceIndex (false); } MidiOutput* MidiOutput::openDevice (const int index) @@ -1203,7 +1239,7 @@ MidiOutput* MidiOutput::openDevice (const int index) ScopedPointer wrapper; try { - wrapper = midiService.get()->createOutputWrapper (index); + wrapper = MidiService::getInstance()->getService()->createOutputWrapper (index); } catch (std::runtime_error&) { diff --git a/modules/juce_events/native/juce_win32_WinRTWrapper.cpp b/modules/juce_events/native/juce_win32_WinRTWrapper.cpp index 824a21b19d..2e01926f54 100644 --- a/modules/juce_events/native/juce_win32_WinRTWrapper.cpp +++ b/modules/juce_events/native/juce_win32_WinRTWrapper.cpp @@ -28,4 +28,4 @@ ============================================================================== */ -juce_ImplementSingleton_SingleThreaded (WinRTWrapper) +juce_ImplementSingleton (WinRTWrapper) diff --git a/modules/juce_events/native/juce_win32_WinRTWrapper.h b/modules/juce_events/native/juce_win32_WinRTWrapper.h index 60433ca226..5e76e82c6e 100644 --- a/modules/juce_events/native/juce_win32_WinRTWrapper.h +++ b/modules/juce_events/native/juce_win32_WinRTWrapper.h @@ -33,7 +33,7 @@ class WinRTWrapper : public DeletedAtShutdown { public: - juce_DeclareSingleton_SingleThreaded (WinRTWrapper, true) + juce_DeclareSingleton (WinRTWrapper, true) class ScopedHString {