| @@ -30,4 +30,3 @@ | |||
| #include <Cocoa/Cocoa.h> | |||
| #define JUCE_NPAPI_WRAPPED_IN_MM 1 | |||
| #include "juce_NPAPI_GlueCode.cpp" | |||
| @@ -608,6 +608,7 @@ | |||
| #include <MMReg.h> | |||
| #include <mmdeviceapi.h> | |||
| #include <Audioclient.h> | |||
| #include <Audiopolicy.h> | |||
| #include <Avrt.h> | |||
| #include <functiondiscoverykeys.h> | |||
| #endif | |||
| @@ -256239,7 +256240,8 @@ public: | |||
| minBufferSize (0), | |||
| defaultBufferSize (0), | |||
| latencySamples (0), | |||
| useExclusiveMode (useExclusiveMode_) | |||
| useExclusiveMode (useExclusiveMode_), | |||
| sampleRateHasChanged (false) | |||
| { | |||
| clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI")); | |||
| @@ -256306,6 +256308,8 @@ public: | |||
| && (tryInitialisingWithFormat (true, 4) || tryInitialisingWithFormat (false, 4) | |||
| || tryInitialisingWithFormat (false, 3) || tryInitialisingWithFormat (false, 2))) | |||
| { | |||
| sampleRateHasChanged = false; | |||
| channelMaps.clear(); | |||
| for (int i = 0; i <= channels.getHighestBit(); ++i) | |||
| if (channels[i]) | |||
| @@ -256317,6 +256321,8 @@ public: | |||
| (void) check (client->GetBufferSize (&actualBufferSize)); | |||
| createSessionEventCallback(); | |||
| return check (client->SetEventHandle (clientEvent)); | |||
| } | |||
| @@ -256328,10 +256334,16 @@ public: | |||
| if (client != 0) | |||
| client->Stop(); | |||
| deleteSessionEventCallback(); | |||
| client = 0; | |||
| ResetEvent (clientEvent); | |||
| } | |||
| void deviceSampleRateChanged() | |||
| { | |||
| sampleRateHasChanged = true; | |||
| } | |||
| ComSmartPtr <IMMDevice> device; | |||
| ComSmartPtr <IAudioClient> client; | |||
| double sampleRate, defaultSampleRate; | |||
| @@ -256344,10 +256356,60 @@ public: | |||
| Array <int> channelMaps; | |||
| UINT32 actualBufferSize; | |||
| int bytesPerSample; | |||
| bool sampleRateHasChanged; | |||
| virtual void updateFormat (bool isFloat) = 0; | |||
| private: | |||
| class SessionEventCallback : public ComBaseClassHelper <IAudioSessionEvents> | |||
| { | |||
| public: | |||
| SessionEventCallback (WASAPIDeviceBase& owner_) : owner (owner_) {} | |||
| HRESULT __stdcall OnDisplayNameChanged (LPCWSTR, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnIconPathChanged (LPCWSTR, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnSimpleVolumeChanged (float, BOOL, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnChannelVolumeChanged (DWORD, float*, DWORD, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnGroupingParamChanged (LPCGUID, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnStateChanged (AudioSessionState) { return S_OK; } | |||
| HRESULT __stdcall OnSessionDisconnected (AudioSessionDisconnectReason reason) | |||
| { | |||
| if (reason == DisconnectReasonFormatChanged) | |||
| owner.deviceSampleRateChanged(); | |||
| return S_OK; | |||
| } | |||
| private: | |||
| WASAPIDeviceBase& owner; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SessionEventCallback); | |||
| }; | |||
| ComSmartPtr <IAudioSessionControl> audioSessionControl; | |||
| ComSmartPtr <SessionEventCallback> sessionEventCallback; | |||
| void createSessionEventCallback() | |||
| { | |||
| deleteSessionEventCallback(); | |||
| client->GetService (__uuidof (IAudioSessionControl), | |||
| (void**) audioSessionControl.resetAndGetPointerAddress()); | |||
| if (audioSessionControl != 0) | |||
| { | |||
| sessionEventCallback = new SessionEventCallback (*this); | |||
| audioSessionControl->RegisterAudioSessionNotification (sessionEventCallback); | |||
| } | |||
| } | |||
| void deleteSessionEventCallback() | |||
| { | |||
| audioSessionControl = 0; | |||
| sessionEventCallback = 0; | |||
| } | |||
| const ComSmartPtr <IAudioClient> createClient() | |||
| { | |||
| ComSmartPtr <IAudioClient> client; | |||
| @@ -256873,9 +256935,9 @@ public: | |||
| setMMThreadPriority(); | |||
| const int bufferSize = currentBufferSizeSamples; | |||
| const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); | |||
| const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | |||
| bool sampleRateChanged = false; | |||
| AudioSampleBuffer ins (jmax (1, numInputBuffers), bufferSize + 32); | |||
| AudioSampleBuffer outs (jmax (1, numOutputBuffers), bufferSize + 32); | |||
| @@ -256891,6 +256953,9 @@ public: | |||
| if (threadShouldExit()) | |||
| break; | |||
| if (inputDevice->sampleRateHasChanged) | |||
| sampleRateChanged = true; | |||
| } | |||
| JUCE_TRY | |||
| @@ -256906,7 +256971,18 @@ public: | |||
| JUCE_CATCH_EXCEPTION | |||
| if (outputDevice != 0) | |||
| { | |||
| outputDevice->copyBuffers (const_cast <const float**> (outputBuffers), numOutputBuffers, bufferSize, *this); | |||
| if (outputDevice->sampleRateHasChanged) | |||
| sampleRateChanged = true; | |||
| } | |||
| if (sampleRateChanged) | |||
| { | |||
| // xxx one of the devices has had its sample rate changed externally.. not 100% sure how | |||
| // to handle this.. | |||
| } | |||
| } | |||
| } | |||
| @@ -26,4 +26,3 @@ | |||
| // This file just wraps juce_VSTPluginFormat.cpp in an objective-C wrapper | |||
| #define JUCE_MAC_VST_INCLUDED 1 | |||
| #include "juce_VSTPluginFormat.cpp" | |||
| @@ -147,6 +147,7 @@ | |||
| #include <MMReg.h> | |||
| #include <mmdeviceapi.h> | |||
| #include <Audioclient.h> | |||
| #include <Audiopolicy.h> | |||
| #include <Avrt.h> | |||
| #include <functiondiscoverykeys.h> | |||
| #endif | |||
| @@ -139,7 +139,8 @@ public: | |||
| minBufferSize (0), | |||
| defaultBufferSize (0), | |||
| latencySamples (0), | |||
| useExclusiveMode (useExclusiveMode_) | |||
| useExclusiveMode (useExclusiveMode_), | |||
| sampleRateHasChanged (false) | |||
| { | |||
| clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI")); | |||
| @@ -206,6 +207,8 @@ public: | |||
| && (tryInitialisingWithFormat (true, 4) || tryInitialisingWithFormat (false, 4) | |||
| || tryInitialisingWithFormat (false, 3) || tryInitialisingWithFormat (false, 2))) | |||
| { | |||
| sampleRateHasChanged = false; | |||
| channelMaps.clear(); | |||
| for (int i = 0; i <= channels.getHighestBit(); ++i) | |||
| if (channels[i]) | |||
| @@ -217,6 +220,8 @@ public: | |||
| (void) check (client->GetBufferSize (&actualBufferSize)); | |||
| createSessionEventCallback(); | |||
| return check (client->SetEventHandle (clientEvent)); | |||
| } | |||
| @@ -228,10 +233,17 @@ public: | |||
| if (client != 0) | |||
| client->Stop(); | |||
| deleteSessionEventCallback(); | |||
| client = 0; | |||
| ResetEvent (clientEvent); | |||
| } | |||
| void deviceSampleRateChanged() | |||
| { | |||
| sampleRateHasChanged = true; | |||
| } | |||
| //============================================================================== | |||
| ComSmartPtr <IMMDevice> device; | |||
| ComSmartPtr <IAudioClient> client; | |||
| double sampleRate, defaultSampleRate; | |||
| @@ -244,10 +256,61 @@ public: | |||
| Array <int> channelMaps; | |||
| UINT32 actualBufferSize; | |||
| int bytesPerSample; | |||
| bool sampleRateHasChanged; | |||
| virtual void updateFormat (bool isFloat) = 0; | |||
| private: | |||
| //============================================================================== | |||
| class SessionEventCallback : public ComBaseClassHelper <IAudioSessionEvents> | |||
| { | |||
| public: | |||
| SessionEventCallback (WASAPIDeviceBase& owner_) : owner (owner_) {} | |||
| HRESULT __stdcall OnDisplayNameChanged (LPCWSTR, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnIconPathChanged (LPCWSTR, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnSimpleVolumeChanged (float, BOOL, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnChannelVolumeChanged (DWORD, float*, DWORD, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnGroupingParamChanged (LPCGUID, LPCGUID) { return S_OK; } | |||
| HRESULT __stdcall OnStateChanged (AudioSessionState) { return S_OK; } | |||
| HRESULT __stdcall OnSessionDisconnected (AudioSessionDisconnectReason reason) | |||
| { | |||
| if (reason == DisconnectReasonFormatChanged) | |||
| owner.deviceSampleRateChanged(); | |||
| return S_OK; | |||
| } | |||
| private: | |||
| WASAPIDeviceBase& owner; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SessionEventCallback); | |||
| }; | |||
| ComSmartPtr <IAudioSessionControl> audioSessionControl; | |||
| ComSmartPtr <SessionEventCallback> sessionEventCallback; | |||
| void createSessionEventCallback() | |||
| { | |||
| deleteSessionEventCallback(); | |||
| client->GetService (__uuidof (IAudioSessionControl), | |||
| (void**) audioSessionControl.resetAndGetPointerAddress()); | |||
| if (audioSessionControl != 0) | |||
| { | |||
| sessionEventCallback = new SessionEventCallback (*this); | |||
| audioSessionControl->RegisterAudioSessionNotification (sessionEventCallback); | |||
| } | |||
| } | |||
| void deleteSessionEventCallback() | |||
| { | |||
| audioSessionControl = 0; | |||
| sessionEventCallback = 0; | |||
| } | |||
| //============================================================================== | |||
| const ComSmartPtr <IAudioClient> createClient() | |||
| { | |||
| ComSmartPtr <IAudioClient> client; | |||
| @@ -777,9 +840,9 @@ public: | |||
| setMMThreadPriority(); | |||
| const int bufferSize = currentBufferSizeSamples; | |||
| const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); | |||
| const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | |||
| bool sampleRateChanged = false; | |||
| AudioSampleBuffer ins (jmax (1, numInputBuffers), bufferSize + 32); | |||
| AudioSampleBuffer outs (jmax (1, numOutputBuffers), bufferSize + 32); | |||
| @@ -795,6 +858,9 @@ public: | |||
| if (threadShouldExit()) | |||
| break; | |||
| if (inputDevice->sampleRateHasChanged) | |||
| sampleRateChanged = true; | |||
| } | |||
| JUCE_TRY | |||
| @@ -810,7 +876,18 @@ public: | |||
| JUCE_CATCH_EXCEPTION | |||
| if (outputDevice != 0) | |||
| { | |||
| outputDevice->copyBuffers (const_cast <const float**> (outputBuffers), numOutputBuffers, bufferSize, *this); | |||
| if (outputDevice->sampleRateHasChanged) | |||
| sampleRateChanged = true; | |||
| } | |||
| if (sampleRateChanged) | |||
| { | |||
| // xxx one of the devices has had its sample rate changed externally.. not 100% sure how | |||
| // to handle this.. | |||
| } | |||
| } | |||
| } | |||