diff options
author | Antoine Aflalo <antoine@aaflalo.me> | 2015-09-08 13:36:56 +0300 |
---|---|---|
committer | Antoine Aflalo <antoine@aaflalo.me> | 2015-09-08 14:19:02 +0300 |
commit | ae77a37ba10fa2d1caa6b3960aff80891a58125e (patch) | |
tree | 8ef89b25072800e0f9035cda157ab00a1af6c583 | |
parent | 8afb5197935386ebee8b8c7380190041c3caaa82 (diff) |
Make Sanear listen to Default Audio Change.
-rw-r--r-- | dll/src/sanear-dll/OuterFilter.cpp | 14 | ||||
-rw-r--r-- | dll/src/sanear-dll/OuterFilter.h | 2 | ||||
-rw-r--r-- | sanear.vcxproj | 2 | ||||
-rw-r--r-- | sanear.vcxproj.filters | 6 | ||||
-rw-r--r-- | src/Factory.cpp | 32 | ||||
-rw-r--r-- | src/Factory.h | 3 | ||||
-rw-r--r-- | src/MMNotificationClient.cpp | 99 | ||||
-rw-r--r-- | src/MMNotificationClient.h | 28 |
8 files changed, 186 insertions, 0 deletions
diff --git a/dll/src/sanear-dll/OuterFilter.cpp b/dll/src/sanear-dll/OuterFilter.cpp index fdd6b73..9daeb19 100644 --- a/dll/src/sanear-dll/OuterFilter.cpp +++ b/dll/src/sanear-dll/OuterFilter.cpp @@ -46,6 +46,13 @@ namespace SaneAudioRenderer m_settings->GetCrossfeedSettings(&uintValue1, &uintValue2);
m_registryKey.SetUint(CrossfeedCutoffFrequency, uintValue1);
m_registryKey.SetUint(CrossfeedLevel, uintValue2);
+
+ //Unregister Notifications
+ IMMDeviceEnumeratorPtr pDeviceEnumerator;
+ if (SUCCEEDED(pDeviceEnumerator.CreateInstance(__uuidof(MMDeviceEnumerator))))
+ {
+ pDeviceEnumerator->UnregisterEndpointNotificationCallback(m_notification);
+ }
}
STDMETHODIMP OuterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
@@ -70,6 +77,13 @@ namespace SaneAudioRenderer ReturnIfFailed(Factory::CreateFilterAggregated(GetOwner(), m_guid, m_settings, &m_innerFilter));
ReturnIfFailed(m_registryKey.Open(HKEY_CURRENT_USER, L"Software\\sanear"));
ReturnIfFailed(m_trayWindow.Init(m_settings));
+ ReturnIfFailed(Factory::CreateNotificationClient(m_settings, &m_notification));
+
+ //Register Notifications
+ IMMDeviceEnumeratorPtr pDeviceEnumerator;
+ ReturnIfFailed(pDeviceEnumerator.CreateInstance(__uuidof(MMDeviceEnumerator)));
+
+ pDeviceEnumerator->RegisterEndpointNotificationCallback(m_notification);
m_initialized = true;
diff --git a/dll/src/sanear-dll/OuterFilter.h b/dll/src/sanear-dll/OuterFilter.h index cf4de20..e5ec79d 100644 --- a/dll/src/sanear-dll/OuterFilter.h +++ b/dll/src/sanear-dll/OuterFilter.h @@ -4,6 +4,7 @@ #include "TrayWindow.h"
#include "../../../src/Interfaces.h"
+#include "../../../src/MMNotificationClient.h"
namespace SaneAudioRenderer
{
@@ -31,5 +32,6 @@ namespace SaneAudioRenderer ISettingsPtr m_settings;
IUnknownPtr m_innerFilter;
TrayWindow m_trayWindow;
+ IMMNotificationClientPtr m_notification;
};
}
diff --git a/sanear.vcxproj b/sanear.vcxproj index eb6d000..bb7fa47 100644 --- a/sanear.vcxproj +++ b/sanear.vcxproj @@ -113,6 +113,7 @@ <ClInclude Include="src\DspRealtimeRate.h" />
<ClInclude Include="src\DspVolume.h" />
<ClInclude Include="src\Interfaces.h" />
+ <ClInclude Include="src\MMNotificationClient.h" />
<ClInclude Include="src\MyBasicAudio.h" />
<ClInclude Include="src\MyPropertyPage.h" />
<ClInclude Include="src\MyTestClock.h" />
@@ -138,6 +139,7 @@ <ClCompile Include="src\DspTempo.cpp" />
<ClCompile Include="src\DspRealtimeRate.cpp" />
<ClCompile Include="src\DspVolume.cpp" />
+ <ClCompile Include="src\MMNotificationClient.cpp" />
<ClCompile Include="src\MyBasicAudio.cpp" />
<ClCompile Include="src\MyFilter.cpp" />
<ClCompile Include="src\MyClock.cpp" />
diff --git a/sanear.vcxproj.filters b/sanear.vcxproj.filters index aa707a8..4cb7f94 100644 --- a/sanear.vcxproj.filters +++ b/sanear.vcxproj.filters @@ -68,6 +68,9 @@ <ClCompile Include="src\DspRealtimeRate.cpp">
<Filter>Processors</Filter>
</ClCompile>
+ <ClCompile Include="src\MMNotificationClient.cpp">
+ <Filter>Renderer</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\DspMatrix.h">
@@ -147,6 +150,9 @@ <ClInclude Include="src\DspRealtimeRate.h">
<Filter>Processors</Filter>
</ClInclude>
+ <ClInclude Include="src\MMNotificationClient.h">
+ <Filter>Renderer</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="DirectShow">
diff --git a/src/Factory.cpp b/src/Factory.cpp index a93ebf7..12d2db4 100644 --- a/src/Factory.cpp +++ b/src/Factory.cpp @@ -3,6 +3,7 @@ #include "MyFilter.h"
#include "Settings.h"
+#include "MMNotificationClient.h"
namespace SaneAudioRenderer
{
@@ -33,6 +34,37 @@ namespace SaneAudioRenderer return result;
}
+ HRESULT Factory::CreateNotificationClient(ISettings* pSettings, IMMNotificationClient** ppOut)
+ {
+ IUnknownPtr unknown;
+ ReturnIfFailed(CreateNotificationClientAggregated(pSettings, &unknown));
+ return unknown->QueryInterface(IID_PPV_ARGS(ppOut));
+ }
+
+ HRESULT Factory::CreateNotificationClientAggregated(ISettings* pSettings, IUnknown** ppOut)
+ {
+ CheckPointer(ppOut, E_POINTER);
+ CheckPointer(pSettings, E_POINTER);
+
+ *ppOut = nullptr;
+
+ auto pNotifclient = new(std::nothrow) CMMNotificationClient;
+
+ if (!pNotifclient)
+ return E_OUTOFMEMORY;
+
+ pNotifclient->AddRef();
+
+ HRESULT result = pNotifclient->Init(pSettings);
+
+ if (SUCCEEDED(result))
+ result = pNotifclient->QueryInterface(IID_PPV_ARGS(ppOut));
+
+ pNotifclient->Release();
+
+ return result;
+ }
+
HRESULT Factory::CreateFilter(ISettings* pSettings, IBaseFilter** ppOut)
{
IUnknownPtr unknown;
diff --git a/src/Factory.h b/src/Factory.h index 178620b..d12cc5d 100644 --- a/src/Factory.h +++ b/src/Factory.h @@ -16,6 +16,9 @@ namespace SaneAudioRenderer static HRESULT CreateSettings(ISettings** ppOut);
static HRESULT CreateSettingsAggregated(IUnknown* pOwner, IUnknown** ppOut);
+ static HRESULT CreateNotificationClient(__in ISettings* pSettings, __out IMMNotificationClient** ppOut);
+ static HRESULT CreateNotificationClientAggregated(__in ISettings* pSettings, __out IUnknown** ppOut);
+
static HRESULT CreateFilter(ISettings* pSettings, IBaseFilter** ppOut);
static HRESULT CreateFilterAggregated(IUnknown* pOwner, const GUID& guid,
ISettings* pSettings, IUnknown** ppOut);
diff --git a/src/MMNotificationClient.cpp b/src/MMNotificationClient.cpp new file mode 100644 index 0000000..d8cb896 --- /dev/null +++ b/src/MMNotificationClient.cpp @@ -0,0 +1,99 @@ +#include "pch.h" +#include "MMNotificationClient.h" + +namespace SaneAudioRenderer +{ + HRESULT CMMNotificationClient::QueryInterface(const IID& riid, void** ppvInterface) + { + if (IID_IUnknown == riid) + { + AddRef(); + *ppvInterface = static_cast<IUnknown*>(this); + } + else if (__uuidof(IMMNotificationClient) == riid) + { + AddRef(); + *ppvInterface = static_cast<IMMNotificationClient*>(this); + } + else + { + *ppvInterface = nullptr; + return E_NOINTERFACE; + } + return S_OK; + } + + ULONG CMMNotificationClient::AddRef() + { + return InterlockedIncrement(&m_cRef); + } + + ULONG CMMNotificationClient::Release() + { + ULONG ulRef = InterlockedDecrement(&m_cRef); + if (0 == ulRef) + { + delete this; + } + return ulRef; + } + + HRESULT CMMNotificationClient::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) + { + return S_OK; + } + + HRESULT CMMNotificationClient::OnDeviceAdded(LPCWSTR pwstrDeviceId) + { + return S_OK; + } + + HRESULT CMMNotificationClient::OnDeviceRemoved(LPCWSTR pwstrDeviceId) + { + return S_OK; + } + + HRESULT CMMNotificationClient::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) + { + //Not interested in Recording devices + if (flow == eCapture) + return S_FALSE; + //Not interested in Communications devices, only Multimedia and Console + if (role == ::eCommunications) + return S_FALSE; + + LPWSTR pDeviceId = nullptr; + BOOL exclusive; + UINT32 buffer; + m_settings->GetOuputDevice(&pDeviceId, &exclusive, &buffer); + std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(pDeviceId); + + if (!pDeviceId || pwstrDefaultDeviceId != pDeviceId) + { + m_settings->SetOuputDevice(pwstrDefaultDeviceId, exclusive, buffer); + return S_OK; + } + return S_FALSE; + } + + HRESULT CMMNotificationClient::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) + { + return S_OK; + } + + HRESULT CMMNotificationClient::Init(ISettings* pSettings) + { + CheckPointer(pSettings, E_POINTER); + ReturnIfFailed(pSettings->QueryInterface(IID_PPV_ARGS(&m_settings))); + return S_OK; + } + + CMMNotificationClient::CMMNotificationClient() : m_cRef(0) + { + } + + + CMMNotificationClient::~CMMNotificationClient() + { + } +} diff --git a/src/MMNotificationClient.h b/src/MMNotificationClient.h new file mode 100644 index 0000000..349657a --- /dev/null +++ b/src/MMNotificationClient.h @@ -0,0 +1,28 @@ +#pragma once +#include <comdef.h> +#include "../../../src/Settings.h" + +namespace SaneAudioRenderer +{ + _COM_SMARTPTR_TYPEDEF(IMMDeviceEnumerator, __uuidof(IMMDeviceEnumerator)); + _COM_SMARTPTR_TYPEDEF(IMMNotificationClient, __uuidof(IMMNotificationClient)); + + class CMMNotificationClient : public IMMNotificationClient + { + public: + HRESULT STDMETHODCALLTYPE QueryInterface(const IID& riid, void** ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef() override; + ULONG STDMETHODCALLTYPE Release() override; + HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override; + HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) override; + HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) override; + HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) override; + HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override; + HRESULT Init(ISettings* pSettings); + CMMNotificationClient(); + virtual ~CMMNotificationClient(); + private: + LONG m_cRef; + ISettingsPtr m_settings; + }; +} |