diff --git a/plugins/systemvolume/CMakeLists.txt b/plugins/systemvolume/CMakeLists.txt index 49123497a..8614447ee 100644 --- a/plugins/systemvolume/CMakeLists.txt +++ b/plugins/systemvolume/CMakeLists.txt @@ -26,6 +26,9 @@ if(WIN32) Qt5::Core ole32 ) + target_sources(kdeconnect_systemvolume + PRIVATE + PolicyConfig.h) elseif(APPLE) target_link_libraries(kdeconnect_systemvolume kdeconnectcore diff --git a/plugins/systemvolume/PolicyConfig.h b/plugins/systemvolume/PolicyConfig.h new file mode 100644 index 000000000..ff6b2accb --- /dev/null +++ b/plugins/systemvolume/PolicyConfig.h @@ -0,0 +1,201 @@ +/* The MIT License (MIT) + +Copyright (c) 2015 DefSound + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +// ---------------------------------------------------------------------------- +// PolicyConfig.h +// Undocumented COM-interface IPolicyConfig. +// Use for set default audio render endpoint +// @author EreTIk +// ---------------------------------------------------------------------------- + + +#pragma once +#include "mmreg.h" + + +interface DECLSPEC_UUID("f8679f50-850a-41cf-9c72-430f290290c8") IPolicyConfig; +class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient; +// ---------------------------------------------------------------------------- +// class CPolicyConfigClient +// {870af99c-171d-4f9e-af0d-e63df40c2bc9} +// +// interface IPolicyConfig +// {f8679f50-850a-41cf-9c72-430f290290c8} +// +// Query interface: +// CComPtr PolicyConfig; +// PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigClient)); +// +// @compatible: Windows 7 and Later +// ---------------------------------------------------------------------------- +interface IPolicyConfig : public IUnknown +{ +public: + + virtual HRESULT GetMixFormat( + PCWSTR, + WAVEFORMATEX ** + ); + + virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( + PCWSTR, + INT, + WAVEFORMATEX ** + ); + + virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( + PCWSTR + ); + + virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( + PCWSTR, + WAVEFORMATEX *, + WAVEFORMATEX * + ); + + virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( + PCWSTR, + INT, + PINT64, + PINT64 + ); + + virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( + PCWSTR, + PINT64 + ); + + virtual HRESULT STDMETHODCALLTYPE GetShareMode( + PCWSTR, + struct DeviceShareMode * + ); + + virtual HRESULT STDMETHODCALLTYPE SetShareMode( + PCWSTR, + struct DeviceShareMode * + ); + + virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( + PCWSTR, + const PROPERTYKEY &, + PROPVARIANT * + ); + + virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( + PCWSTR, + const PROPERTYKEY &, + PROPVARIANT * + ); + + virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( + __in PCWSTR wszDeviceId, + __in ERole eRole + ); + + virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( + PCWSTR, + INT + ); +}; + +interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") IPolicyConfigVista; +class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") CPolicyConfigVistaClient; +// ---------------------------------------------------------------------------- +// class CPolicyConfigVistaClient +// {294935CE-F637-4E7C-A41B-AB255460B862} +// +// interface IPolicyConfigVista +// {568b9108-44bf-40b4-9006-86afe5b5a620} +// +// Query interface: +// CComPtr PolicyConfig; +// PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigVistaClient)); +// +// @compatible: Windows Vista and Later +// ---------------------------------------------------------------------------- +interface IPolicyConfigVista : public IUnknown +{ +public: + + virtual HRESULT GetMixFormat( + PCWSTR, + WAVEFORMATEX ** + ); // not available on Windows 7, use method from IPolicyConfig + + virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( + PCWSTR, + INT, + WAVEFORMATEX ** + ); + + virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( + PCWSTR, + WAVEFORMATEX *, + WAVEFORMATEX * + ); + + virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( + PCWSTR, + INT, + PINT64, + PINT64 + ); // not available on Windows 7, use method from IPolicyConfig + + virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( + PCWSTR, + PINT64 + ); // not available on Windows 7, use method from IPolicyConfig + + virtual HRESULT STDMETHODCALLTYPE GetShareMode( + PCWSTR, + struct DeviceShareMode * + ); // not available on Windows 7, use method from IPolicyConfig + + virtual HRESULT STDMETHODCALLTYPE SetShareMode( + PCWSTR, + struct DeviceShareMode * + ); // not available on Windows 7, use method from IPolicyConfig + + virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( + PCWSTR, + const PROPERTYKEY &, + PROPVARIANT * + ); + + virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( + PCWSTR, + const PROPERTYKEY &, + PROPVARIANT * + ); + + virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( + __in PCWSTR wszDeviceId, + __in ERole eRole + ); + + virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( + PCWSTR, + INT + ); // not available on Windows 7, use method from IPolicyConfig +}; + +// ---------------------------------------------------------------------------- diff --git a/plugins/systemvolume/systemvolumeplugin-win.cpp b/plugins/systemvolume/systemvolumeplugin-win.cpp index a076770ac..e2708e387 100644 --- a/plugins/systemvolume/systemvolumeplugin-win.cpp +++ b/plugins/systemvolume/systemvolumeplugin-win.cpp @@ -18,6 +18,7 @@ #include #include "plugin_systemvolume_debug.h" +#include "PolicyConfig.h" K_PLUGIN_CLASS_WITH_JSON(SystemvolumePlugin, "kdeconnect_systemvolume.json") @@ -353,6 +354,50 @@ void SystemvolumePlugin::connected() sendSinkList(); } +static HRESULT setDefaultAudioPlaybackDevice(PCWSTR deviceId) { + if (deviceId == nullptr) return ERROR_BAD_UNIT; + + IPolicyConfigVista *pPolicyConfig; + HRESULT hr = CoCreateInstance( + __uuidof(CPolicyConfigVistaClient), + NULL, + CLSCTX_ALL, + __uuidof(IPolicyConfigVista), + (LPVOID *)&pPolicyConfig + ); + + if (SUCCEEDED(hr)) + { + hr = pPolicyConfig->SetDefaultEndpoint(deviceId, eMultimedia); + pPolicyConfig->Release(); + } + + return hr; +} + +HRESULT SystemvolumePlugin::setDefaultAudioPlaybackDevice(QString& name, bool enabled) +{ + if (!enabled) return S_OK; + + PWSTR deviceId = nullptr; + for (auto& entry : idToNameMap.toStdMap()) { + if (entry.second == name) { + + deviceId = new WCHAR[entry.first.length()]; + wcscpy(deviceId, entry.first.toStdWString().data()); + break; + } + } + + if (deviceId == nullptr) return ERROR_BAD_UNIT; + + HRESULT hr = ::setDefaultAudioPlaybackDevice(deviceId); + + delete[] deviceId; + + return hr; +} + bool SystemvolumePlugin::receivePacket(const NetworkPacket &np) { if (!valid) @@ -376,6 +421,10 @@ bool SystemvolumePlugin::receivePacket(const NetworkPacket &np) { sinkList[name].first->SetMute(np.get(QStringLiteral("muted")), NULL); } + if (np.has(QStringLiteral("enabled"))) + { + setDefaultAudioPlaybackDevice(name, np.get(QStringLiteral("enabled"))); + } } } return true; diff --git a/plugins/systemvolume/systemvolumeplugin-win.h b/plugins/systemvolume/systemvolumeplugin-win.h index 6b33ca000..e3c58bd8a 100644 --- a/plugins/systemvolume/systemvolumeplugin-win.h +++ b/plugins/systemvolume/systemvolumeplugin-win.h @@ -44,6 +44,7 @@ class Q_DECL_EXPORT SystemvolumePlugin : public KdeConnectPlugin QMap idToNameMap; bool sendSinkList(); + HRESULT setDefaultAudioPlaybackDevice(QString& name, bool enabled); }; #endif // SYSTEMVOLUMEPLUGINWIN_H