diff --git a/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp b/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp index 017bee61e8..28a102ac41 100644 --- a/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp +++ b/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp @@ -1035,8 +1035,14 @@ public: }; //============================================================================== -struct DSoundDeviceList +class DSoundDeviceList { + auto tie() const + { + return std::tie (outputDeviceNames, inputDeviceNames, outputGuids, inputGuids); + } + +public: StringArray outputDeviceNames, inputDeviceNames; Array outputGuids, inputGuids; @@ -1054,13 +1060,8 @@ struct DSoundDeviceList } } - bool operator!= (const DSoundDeviceList& other) const noexcept - { - return outputDeviceNames != other.outputDeviceNames - || inputDeviceNames != other.inputDeviceNames - || outputGuids != other.outputGuids - || inputGuids != other.inputGuids; - } + bool operator== (const DSoundDeviceList& other) const noexcept { return tie() == other.tie(); } + bool operator!= (const DSoundDeviceList& other) const noexcept { return tie() != other.tie(); } private: static BOOL enumProc (LPGUID lpGUID, String desc, StringArray& names, Array& guids) @@ -1213,13 +1214,11 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels, } //============================================================================== -class DSoundAudioIODeviceType : public AudioIODeviceType, - private DeviceChangeDetector +class DSoundAudioIODeviceType : public AudioIODeviceType { public: DSoundAudioIODeviceType() - : AudioIODeviceType ("DirectSound"), - DeviceChangeDetector (L"DirectSound") + : AudioIODeviceType ("DirectSound") { initialiseDSoundFunctions(); } @@ -1274,19 +1273,17 @@ public: } private: + DeviceChangeDetector detector { L"DirectSound", [this] { systemDeviceChanged(); } }; DSoundDeviceList deviceList; bool hasScanned = false; - void systemDeviceChanged() override + void systemDeviceChanged() { DSoundDeviceList newList; newList.scan(); - if (newList != deviceList) - { - deviceList = newList; + if (std::exchange (deviceList, newList) != newList) callDeviceChangeListeners(); - } } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODeviceType) diff --git a/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp b/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp index b516cdbba9..92122988b2 100644 --- a/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp +++ b/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp @@ -1694,13 +1694,11 @@ private: //============================================================================== -class WASAPIAudioIODeviceType : public AudioIODeviceType, - private DeviceChangeDetector +class WASAPIAudioIODeviceType : public AudioIODeviceType { public: - WASAPIAudioIODeviceType (WASAPIDeviceMode mode) + explicit WASAPIAudioIODeviceType (WASAPIDeviceMode mode) : AudioIODeviceType (getDeviceTypename (mode)), - DeviceChangeDetector (L"Windows Audio"), deviceMode (mode) { } @@ -1715,22 +1713,15 @@ public: void scanForDevices() override { hasScanned = true; - - outputDeviceNames.clear(); - inputDeviceNames.clear(); - outputDeviceIds.clear(); - inputDeviceIds.clear(); - - scan (outputDeviceNames, inputDeviceNames, - outputDeviceIds, inputDeviceIds); + devices = scan(); } StringArray getDeviceNames (bool wantInputNames) const override { jassert (hasScanned); // need to call scanForDevices() before doing this - return wantInputNames ? inputDeviceNames - : outputDeviceNames; + return wantInputNames ? devices.inputDeviceNames + : devices.outputDeviceNames; } int getDefaultDeviceIndex (bool /*forInput*/) const override @@ -1744,8 +1735,8 @@ public: jassert (hasScanned); // need to call scanForDevices() before doing this if (auto d = dynamic_cast (device)) - return asInput ? inputDeviceIds.indexOf (d->inputDeviceId) - : outputDeviceIds.indexOf (d->outputDeviceId); + return asInput ? devices.inputDeviceIds .indexOf (d->inputDeviceId) + : devices.outputDeviceIds.indexOf (d->outputDeviceId); return -1; } @@ -1759,16 +1750,16 @@ public: std::unique_ptr device; - auto outputIndex = outputDeviceNames.indexOf (outputDeviceName); - auto inputIndex = inputDeviceNames.indexOf (inputDeviceName); + auto outputIndex = devices.outputDeviceNames.indexOf (outputDeviceName); + auto inputIndex = devices.inputDeviceNames .indexOf (inputDeviceName); if (outputIndex >= 0 || inputIndex >= 0) { device.reset (new WASAPIAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName : inputDeviceName, getTypeName(), - outputDeviceIds [outputIndex], - inputDeviceIds [inputIndex], + devices.outputDeviceIds[outputIndex], + devices.inputDeviceIds [inputIndex], deviceMode)); if (! device->initialise()) @@ -1779,10 +1770,24 @@ public: } //============================================================================== - StringArray outputDeviceNames, outputDeviceIds; - StringArray inputDeviceNames, inputDeviceIds; + struct Devices + { + StringArray outputDeviceNames, outputDeviceIds; + StringArray inputDeviceNames, inputDeviceIds; + + auto tie() const + { + return std::tie (outputDeviceNames, outputDeviceIds, inputDeviceNames, inputDeviceIds); + } + + bool operator== (const Devices& other) const { return tie() == other.tie(); } + bool operator!= (const Devices& other) const { return tie() != other.tie(); } + }; + + Devices devices; private: + DeviceChangeDetector deviceChangeDetector { L"Windows Audio", [this] { systemDeviceChanged(); } }; WASAPIDeviceMode deviceMode; bool hasScanned = false; ComSmartPtr enumerator; @@ -1791,7 +1796,7 @@ private: class ChangeNotificationClient : public ComBaseClassHelper { public: - ChangeNotificationClient (WASAPIAudioIODeviceType* d) + explicit ChangeNotificationClient (WASAPIAudioIODeviceType* d) : ComBaseClassHelper (0), device (d) {} JUCE_COMRESULT OnDeviceAdded (LPCWSTR) { return notify(); } @@ -1806,7 +1811,7 @@ private: HRESULT notify() { if (device != nullptr) - device->triggerAsyncDeviceChangeCallback(); + device->deviceChangeDetector.triggerAsyncDeviceChangeCallback(); return S_OK; } @@ -1840,15 +1845,12 @@ private: } //============================================================================== - void scan (StringArray& outDeviceNames, - StringArray& inDeviceNames, - StringArray& outDeviceIds, - StringArray& inDeviceIds) + Devices scan() { if (enumerator == nullptr) { if (! check (enumerator.CoCreateInstance (__uuidof (MMDeviceEnumerator)))) - return; + return {}; notifyClient = new ChangeNotificationClient (this); enumerator->RegisterEndpointNotificationCallback (notifyClient); @@ -1862,7 +1864,9 @@ private: if (! (check (enumerator->EnumAudioEndpoints (eAll, DEVICE_STATE_ACTIVE, deviceCollection.resetAndGetPointerAddress())) && check (deviceCollection->GetCount (&numDevices)))) - return; + return {}; + + Devices result; for (UINT32 i = 0; i < numDevices; ++i) { @@ -1902,40 +1906,33 @@ private: if (flow == eRender) { const int index = (deviceId == defaultRenderer) ? 0 : -1; - outDeviceIds.insert (index, deviceId); - outDeviceNames.insert (index, name); + result.outputDeviceIds.insert (index, deviceId); + result.outputDeviceNames.insert (index, name); } else if (flow == eCapture) { const int index = (deviceId == defaultCapture) ? 0 : -1; - inDeviceIds.insert (index, deviceId); - inDeviceNames.insert (index, name); + result.inputDeviceIds.insert (index, deviceId); + result.inputDeviceNames.insert (index, name); } } - inDeviceNames.appendNumbersToDuplicates (false, false); - outDeviceNames.appendNumbersToDuplicates (false, false); + result.inputDeviceNames .appendNumbersToDuplicates (false, false); + result.outputDeviceNames.appendNumbersToDuplicates (false, false); + + return result; } //============================================================================== - void systemDeviceChanged() override + void systemDeviceChanged() { - StringArray newOutNames, newInNames, newOutIds, newInIds; - scan (newOutNames, newInNames, newOutIds, newInIds); + const auto newDevices = scan(); - if (newOutNames != outputDeviceNames - || newInNames != inputDeviceNames - || newOutIds != outputDeviceIds - || newInIds != inputDeviceIds) + if (std::exchange (devices, newDevices) != newDevices) { hasScanned = true; - outputDeviceNames = newOutNames; - inputDeviceNames = newInNames; - outputDeviceIds = newOutIds; - inputDeviceIds = newInIds; + callDeviceChangeListeners(); } - - callDeviceChangeListeners(); } //============================================================================== diff --git a/modules/juce_events/native/juce_win32_HiddenMessageWindow.h b/modules/juce_events/native/juce_win32_HiddenMessageWindow.h index e199569c27..e64271d168 100644 --- a/modules/juce_events/native/juce_win32_HiddenMessageWindow.h +++ b/modules/juce_events/native/juce_win32_HiddenMessageWindow.h @@ -91,14 +91,13 @@ private: class DeviceChangeDetector : private Timer { public: - DeviceChangeDetector (const wchar_t* const name) - : messageWindow (name, (WNDPROC) deviceChangeEventCallback) + DeviceChangeDetector (const wchar_t* const name, std::function onChangeIn) + : messageWindow (name, (WNDPROC) deviceChangeEventCallback), + onChange (std::move (onChangeIn)) { SetWindowLongPtr (messageWindow.getHWND(), GWLP_USERDATA, (LONG_PTR) this); } - virtual void systemDeviceChanged() = 0; - void triggerAsyncDeviceChangeCallback() { // We'll pause before sending a message, because on device removal, the OS hasn't always updated @@ -108,6 +107,7 @@ public: private: HiddenMessageWindow messageWindow; + std::function onChange; static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) @@ -127,7 +127,7 @@ private: void timerCallback() override { stopTimer(); - systemDeviceChanged(); + NullCheckedInvocation::invoke (onChange); } }; diff --git a/modules/juce_events/native/juce_win32_Messaging.cpp b/modules/juce_events/native/juce_win32_Messaging.cpp index 0e91c21596..b970ebb134 100644 --- a/modules/juce_events/native/juce_win32_Messaging.cpp +++ b/modules/juce_events/native/juce_win32_Messaging.cpp @@ -299,25 +299,24 @@ void MessageManager::doPlatformSpecificShutdown() } //============================================================================== -struct MountedVolumeListChangeDetector::Pimpl : private DeviceChangeDetector +struct MountedVolumeListChangeDetector::Pimpl { - Pimpl (MountedVolumeListChangeDetector& d) : DeviceChangeDetector (L"MountedVolumeList"), owner (d) + explicit Pimpl (MountedVolumeListChangeDetector& d) + : owner (d) { File::findFileSystemRoots (lastVolumeList); } - void systemDeviceChanged() override + void systemDeviceChanged() { Array newList; File::findFileSystemRoots (newList); - if (lastVolumeList != newList) - { - lastVolumeList = newList; + if (std::exchange (lastVolumeList, newList) != newList) owner.mountedVolumeListChanged(); - } } + DeviceChangeDetector detector { L"MountedVolumeList", [this] { systemDeviceChanged(); } }; MountedVolumeListChangeDetector& owner; Array lastVolumeList; };