import
This commit is contained in:
20
ShitMuter.sln
Normal file
20
ShitMuter.sln
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 2012
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShitMuter", "ShitMuter\ShitMuter.vcxproj", "{F8B9EAD5-19B7-43EA-81FA-897B144BAB22}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{F8B9EAD5-19B7-43EA-81FA-897B144BAB22}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{F8B9EAD5-19B7-43EA-81FA-897B144BAB22}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{F8B9EAD5-19B7-43EA-81FA-897B144BAB22}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{F8B9EAD5-19B7-43EA-81FA-897B144BAB22}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
BIN
ShitMuter/Resource.aps
Normal file
BIN
ShitMuter/Resource.aps
Normal file
Binary file not shown.
BIN
ShitMuter/Resource.rc
Normal file
BIN
ShitMuter/Resource.rc
Normal file
Binary file not shown.
102
ShitMuter/ShitMuter.vcxproj
Normal file
102
ShitMuter/ShitMuter.vcxproj
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{F8B9EAD5-19B7-43EA-81FA-897B144BAB22}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>ShitMuter</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<Manifest>
|
||||||
|
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||||
|
</Manifest>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Source.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Image Include="icon1.ico" />
|
||||||
|
<Image Include="icon2.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="Resource.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
40
ShitMuter/ShitMuter.vcxproj.filters
Normal file
40
ShitMuter/ShitMuter.vcxproj.filters
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Source.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Image Include="icon1.ico">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Image>
|
||||||
|
<Image Include="icon2.ico">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</Image>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="Resource.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
4
ShitMuter/ShitMuter.vcxproj.user
Normal file
4
ShitMuter/ShitMuter.vcxproj.user
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup />
|
||||||
|
</Project>
|
||||||
532
ShitMuter/Source.cpp
Normal file
532
ShitMuter/Source.cpp
Normal file
@@ -0,0 +1,532 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
#include <Audiopolicy.h>
|
||||||
|
#include <mmdeviceapi.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <WinUser.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#define WM_TRAY_MENU (WM_USER)
|
||||||
|
#define WM_DIE (WM_USER+1)
|
||||||
|
#define WM_CFG (WM_USER+2)
|
||||||
|
|
||||||
|
HWND win;
|
||||||
|
NOTIFYICONDATA icondat;
|
||||||
|
UINT wmTaskbarCreated = 0;
|
||||||
|
HWINEVENTHOOK hook;
|
||||||
|
HWINEVENTHOOK hook2;
|
||||||
|
|
||||||
|
// can we register to handle new streams? new devices, new sessions
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
// Example implementation of IMMNotificationClient interface.
|
||||||
|
// When the status of audio endpoint devices change, the
|
||||||
|
// MMDevice module calls these methods to notify the client.
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
|
#define SAFE_RELEASE(punk) \
|
||||||
|
if ((punk) != NULL) \
|
||||||
|
{ (punk)->Release(); (punk) = NULL; }
|
||||||
|
|
||||||
|
class DeviceNotification : public IMMNotificationClient
|
||||||
|
{
|
||||||
|
LONG _cRef;
|
||||||
|
std::function<void(LPCWSTR)> _addCallback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeviceNotification(std::function<void(LPCWSTR)> callback) :
|
||||||
|
_addCallback(std::move(callback)),
|
||||||
|
_cRef(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~DeviceNotification()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown methods -- AddRef, Release, and QueryInterface
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&_cRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release()
|
||||||
|
{
|
||||||
|
ULONG ulRef = InterlockedDecrement(&_cRef);
|
||||||
|
if (0 == ulRef)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
return ulRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
|
REFIID riid, VOID** ppvInterface)
|
||||||
|
{
|
||||||
|
if (IID_IUnknown == riid)
|
||||||
|
{
|
||||||
|
AddRef();
|
||||||
|
*ppvInterface = (IUnknown*)this;
|
||||||
|
}
|
||||||
|
else if (__uuidof(IMMNotificationClient) == riid)
|
||||||
|
{
|
||||||
|
AddRef();
|
||||||
|
*ppvInterface = (IMMNotificationClient*)this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvInterface = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback methods for device-event notifications.
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(
|
||||||
|
EDataFlow flow, ERole role,
|
||||||
|
LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
_addCallback(pwstrDeviceId);
|
||||||
|
return S_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(
|
||||||
|
LPCWSTR pwstrDeviceId,
|
||||||
|
DWORD dwNewState)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(
|
||||||
|
LPCWSTR pwstrDeviceId,
|
||||||
|
const PROPERTYKEY key)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SessionNotification : public IAudioSessionNotification
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
LONG _ref;
|
||||||
|
std::function<void()> _addCallback;
|
||||||
|
public:
|
||||||
|
~SessionNotification() {};
|
||||||
|
SessionNotification(std::function<void()> callback) : _addCallback(std::move(callback)), _ref(1) {}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv)
|
||||||
|
{
|
||||||
|
if (IID_IUnknown == riid)
|
||||||
|
{
|
||||||
|
AddRef();
|
||||||
|
*ppv = (IUnknown*)this;
|
||||||
|
}
|
||||||
|
else if (__uuidof(IAudioSessionNotification) == riid)
|
||||||
|
{
|
||||||
|
AddRef();
|
||||||
|
*ppv = (IAudioSessionNotification*)this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppv = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release()
|
||||||
|
{
|
||||||
|
ULONG ulRef = InterlockedDecrement(&_ref);
|
||||||
|
if (0 == ulRef)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
return ulRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnSessionCreated(IAudioSessionControl* pNewSession)
|
||||||
|
{
|
||||||
|
_addCallback();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<std::string> appsToMute;
|
||||||
|
|
||||||
|
std::set<std::string> loadSettingsFile(std::string settingsFilename)
|
||||||
|
{
|
||||||
|
std::set<std::string> appLines;
|
||||||
|
std::ifstream in(settingsFilename);
|
||||||
|
std::string line;
|
||||||
|
while (!in.eof() && !in.bad() && in.is_open()) {
|
||||||
|
getline(in, line);
|
||||||
|
if (!line.empty())
|
||||||
|
appLines.insert(line);
|
||||||
|
}
|
||||||
|
return appLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveSettingsFile(std::string settingsFilename, std::set<std::string> appLines)
|
||||||
|
{
|
||||||
|
std::ofstream out(settingsFilename);
|
||||||
|
for (std::string line : appLines) {
|
||||||
|
out << line << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<IAudioSessionManager2*> CreateSessionManagers()
|
||||||
|
{
|
||||||
|
std::vector<IAudioSessionManager2*> sessionManagers;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
IMMDeviceEnumerator* pEnumerator = NULL;
|
||||||
|
IMMDeviceCollection* pDeviceCollection = NULL;
|
||||||
|
|
||||||
|
// Create the device enumerator.
|
||||||
|
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
|
||||||
|
pEnumerator->EnumAudioEndpoints(EDataFlow::eRender, DEVICE_STATE_ACTIVE, &pDeviceCollection);
|
||||||
|
UINT cDevices;
|
||||||
|
pDeviceCollection->GetCount(&cDevices);
|
||||||
|
for (UINT i = 0; i < cDevices; i++) {
|
||||||
|
IMMDevice* pDevice = NULL;
|
||||||
|
IAudioSessionManager2* pSessionManager = NULL;
|
||||||
|
pDeviceCollection->Item(i, &pDevice);
|
||||||
|
hr = pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&pSessionManager);
|
||||||
|
sessionManagers.push_back(pSessionManager);
|
||||||
|
pDevice->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the pointer to the caller.
|
||||||
|
pDeviceCollection->Release();
|
||||||
|
pEnumerator->Release();
|
||||||
|
return sessionManagers;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pidToFilename(DWORD pid) {
|
||||||
|
DWORD maxLength = MAX_PATH;
|
||||||
|
char moduleFileName[MAX_PATH] = { 0 };
|
||||||
|
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
|
||||||
|
QueryFullProcessImageName(process, 0, moduleFileName, &maxLength);
|
||||||
|
CloseHandle(process);
|
||||||
|
PathStripPath(moduleFileName);
|
||||||
|
return std::string(moduleFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto muteAllAction = [](std::string checkFilename) { return true; };
|
||||||
|
auto unmuteAllAction = [](std::string checkFilename) { return false; };
|
||||||
|
auto muteAllExcept(std::string filename)
|
||||||
|
{
|
||||||
|
return [filename](std::string checkFilename)
|
||||||
|
{
|
||||||
|
return filename != checkFilename;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
std::function<bool(std::string)> lastAction = muteAllAction;
|
||||||
|
|
||||||
|
void PerformMuteAction(std::function<bool(std::string)> mutePicker) {
|
||||||
|
lastAction = mutePicker;
|
||||||
|
for (IAudioSessionManager2* sessionManager : CreateSessionManagers()) {
|
||||||
|
IAudioSessionEnumerator* enumerator;
|
||||||
|
int sessionCount = 0;
|
||||||
|
sessionManager->GetSessionEnumerator(&enumerator);
|
||||||
|
enumerator->GetCount(&sessionCount);
|
||||||
|
for (int i = 0; i < sessionCount; i++)
|
||||||
|
{
|
||||||
|
IAudioSessionControl* control;
|
||||||
|
IAudioSessionControl2* control2;
|
||||||
|
ISimpleAudioVolume* vol;
|
||||||
|
enumerator->GetSession(i, &control);
|
||||||
|
control->QueryInterface<IAudioSessionControl2>(&control2);
|
||||||
|
control2->QueryInterface<ISimpleAudioVolume>(&vol);
|
||||||
|
DWORD pid;
|
||||||
|
control2->GetProcessId(&pid);
|
||||||
|
|
||||||
|
std::string filename = pidToFilename(pid);
|
||||||
|
if (appsToMute.find(filename) != appsToMute.end())
|
||||||
|
{
|
||||||
|
bool muted = mutePicker(filename);
|
||||||
|
vol->SetMute(muted, NULL);
|
||||||
|
}
|
||||||
|
control2->Release();
|
||||||
|
control->Release();
|
||||||
|
vol->Release();
|
||||||
|
}
|
||||||
|
enumerator->Release();
|
||||||
|
sessionManager->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CALLBACK winEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
|
||||||
|
{
|
||||||
|
if (event == EVENT_SYSTEM_FOREGROUND || event == EVENT_SYSTEM_MINIMIZEEND)
|
||||||
|
{
|
||||||
|
DWORD pid;
|
||||||
|
GetWindowThreadProcessId(hwnd, &pid);
|
||||||
|
std::string filename = pidToFilename(pid);
|
||||||
|
|
||||||
|
if (appsToMute.find(filename) != appsToMute.end())
|
||||||
|
{
|
||||||
|
PerformMuteAction(muteAllExcept(filename));
|
||||||
|
icondat.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
|
||||||
|
Shell_NotifyIcon(NIM_MODIFY, &icondat);
|
||||||
|
DestroyIcon(icondat.hIcon);
|
||||||
|
} else {
|
||||||
|
PerformMuteAction(muteAllAction);
|
||||||
|
icondat.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON2));
|
||||||
|
Shell_NotifyIcon(NIM_MODIFY, &icondat);
|
||||||
|
DestroyIcon(icondat.hIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CALLBACK CfgDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
for (std::string exe : appsToMute) {
|
||||||
|
SendDlgItemMessage(hwnd, IDC_EXELIST, LB_ADDSTRING, 0, (LPARAM)exe.c_str());
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam))
|
||||||
|
{
|
||||||
|
case IDC_ADDBUTTON:
|
||||||
|
{
|
||||||
|
int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EXEEDIT)) + 1;
|
||||||
|
auto str = std::make_unique<char[]>(len);
|
||||||
|
GetDlgItemText(hwnd, IDC_EXEEDIT, str.get(), len);
|
||||||
|
SendDlgItemMessage(hwnd, IDC_EXELIST, LB_ADDSTRING, 0, (LPARAM)str.get());
|
||||||
|
SetDlgItemText(hwnd, IDC_EXEEDIT, "");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDC_DELBUTTON:
|
||||||
|
{
|
||||||
|
LRESULT index = SendDlgItemMessage(hwnd, IDC_EXELIST, LB_GETCURSEL, NULL, NULL);
|
||||||
|
SendDlgItemMessage(hwnd, IDC_EXELIST, LB_DELETESTRING, index, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDOK:
|
||||||
|
{
|
||||||
|
LRESULT count = SendDlgItemMessage(hwnd, IDC_EXELIST, LB_GETCOUNT, NULL, NULL);
|
||||||
|
appsToMute.clear();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
unsigned int length = SendDlgItemMessage(hwnd, IDC_EXELIST, LB_GETTEXTLEN, i, NULL) + 1;
|
||||||
|
auto exeLineChars = std::make_unique<char[]>(length);
|
||||||
|
SendDlgItemMessage(hwnd, IDC_EXELIST, LB_GETTEXT, i, (LPARAM)exeLineChars.get());
|
||||||
|
std::string exeLine(exeLineChars.get());
|
||||||
|
appsToMute.insert(exeLine);
|
||||||
|
}
|
||||||
|
saveSettingsFile("mute.txt", appsToMute);
|
||||||
|
EndDialog(hwnd, IDOK);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDCANCEL:
|
||||||
|
EndDialog(hwnd, IDCANCEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (message == wmTaskbarCreated) {
|
||||||
|
Shell_NotifyIcon(NIM_ADD, &icondat);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
memset(&icondat, 0, sizeof(icondat));
|
||||||
|
icondat.cbSize = sizeof(icondat);
|
||||||
|
icondat.hWnd = hWnd;
|
||||||
|
icondat.uID = 1;
|
||||||
|
icondat.uFlags = NIF_ICON | NIF_MESSAGE;
|
||||||
|
icondat.uCallbackMessage = WM_TRAY_MENU;
|
||||||
|
icondat.uVersion = NOTIFYICON_VERSION;
|
||||||
|
icondat.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
|
||||||
|
Shell_NotifyIcon(NIM_ADD, &icondat);
|
||||||
|
DestroyIcon(icondat.hIcon);
|
||||||
|
break;
|
||||||
|
case WM_TRAY_MENU:
|
||||||
|
if (lParam == WM_RBUTTONDOWN) {
|
||||||
|
POINT pt;
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
HMENU menu = CreatePopupMenu();
|
||||||
|
InsertMenu(menu, -1, MF_BYPOSITION, WM_CFG, "Configure...");
|
||||||
|
InsertMenu(menu, -1, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
|
||||||
|
InsertMenu(menu, -1, MF_BYPOSITION, WM_DIE, "Exit");
|
||||||
|
SetForegroundWindow(hWnd);
|
||||||
|
TrackPopupMenu(menu, TPM_BOTTOMALIGN,
|
||||||
|
pt.x, pt.y, 0, hWnd, NULL);
|
||||||
|
DestroyMenu(menu);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam))
|
||||||
|
{
|
||||||
|
case WM_DIE:
|
||||||
|
PerformMuteAction(unmuteAllAction);
|
||||||
|
Shell_NotifyIcon(NIM_DELETE, &icondat);
|
||||||
|
UnhookWinEvent(hook);
|
||||||
|
UnhookWinEvent(hook2);
|
||||||
|
saveSettingsFile("mute.txt", appsToMute);
|
||||||
|
ExitProcess(0);
|
||||||
|
break;
|
||||||
|
case WM_CFG:
|
||||||
|
DialogBox(NULL, MAKEINTRESOURCE(IDD_CFGDIALOG), hWnd, CfgDlgProc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AudFucker
|
||||||
|
{
|
||||||
|
DeviceNotification* _endpointNotificationClient;
|
||||||
|
SessionNotification* _sessionNotification;
|
||||||
|
IMMDeviceEnumerator* _enumerator = NULL;
|
||||||
|
std::vector<IAudioSessionManager2*> _knownSessions;
|
||||||
|
public:
|
||||||
|
AudFucker()
|
||||||
|
{
|
||||||
|
_endpointNotificationClient = new DeviceNotification(
|
||||||
|
[this](LPCWSTR pwstrDeviceId) {
|
||||||
|
IMMDevice* pDevice = NULL;
|
||||||
|
_enumerator->GetDevice(pwstrDeviceId, &pDevice);
|
||||||
|
if (pDevice != NULL)
|
||||||
|
fuckulateDevice(pDevice);
|
||||||
|
OutputDebugString("Device added\n");
|
||||||
|
PerformMuteAction(lastAction);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
_sessionNotification = new SessionNotification(
|
||||||
|
[]() {
|
||||||
|
OutputDebugString("Session added\n");
|
||||||
|
PerformMuteAction(lastAction);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&_enumerator);
|
||||||
|
int reval = _enumerator->RegisterEndpointNotificationCallback(_endpointNotificationClient);
|
||||||
|
hookExistingDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
~AudFucker() {
|
||||||
|
_enumerator->UnregisterEndpointNotificationCallback(_endpointNotificationClient);
|
||||||
|
for (IAudioSessionManager2* session : _knownSessions) {
|
||||||
|
session->UnregisterSessionNotification(_sessionNotification);
|
||||||
|
session->Release();
|
||||||
|
}
|
||||||
|
_sessionNotification->Release();
|
||||||
|
_endpointNotificationClient->Release();
|
||||||
|
}
|
||||||
|
void fuckulateDevice(IMMDevice* device)
|
||||||
|
{
|
||||||
|
IAudioSessionManager2* pSessionManager = NULL;
|
||||||
|
device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&pSessionManager);
|
||||||
|
pSessionManager->RegisterSessionNotification(_sessionNotification);
|
||||||
|
_knownSessions.push_back(pSessionManager);
|
||||||
|
IAudioSessionEnumerator* enumerator;
|
||||||
|
// HACK: we must discard a session enumerator in order to enable the session notification.
|
||||||
|
// In a better version of this application we'd probably try to collect all known sessions and update them all without the need to rescan everything
|
||||||
|
pSessionManager->GetSessionEnumerator(&enumerator);
|
||||||
|
enumerator->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hookExistingDevices() {
|
||||||
|
|
||||||
|
|
||||||
|
IMMDeviceCollection* pDeviceCollection = NULL;
|
||||||
|
|
||||||
|
// Create the device enumerator.
|
||||||
|
_enumerator->EnumAudioEndpoints(EDataFlow::eRender, DEVICE_STATE_ACTIVE, &pDeviceCollection);
|
||||||
|
UINT cDevices;
|
||||||
|
pDeviceCollection->GetCount(&cDevices);
|
||||||
|
for (UINT i = 0; i < cDevices; i++) {
|
||||||
|
IMMDevice* pDevice = NULL;
|
||||||
|
pDeviceCollection->Item(i, &pDevice);
|
||||||
|
fuckulateDevice(pDevice);
|
||||||
|
pDevice->Release();
|
||||||
|
}
|
||||||
|
pDeviceCollection->Release();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
|
||||||
|
{
|
||||||
|
CoInitialize(NULL);
|
||||||
|
|
||||||
|
|
||||||
|
appsToMute = loadSettingsFile("mute.txt");
|
||||||
|
wmTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
|
||||||
|
|
||||||
|
hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||||
|
hook2 = SetWinEventHook(EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZEEND, NULL, winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||||
|
if (hook == 0)
|
||||||
|
{
|
||||||
|
MessageBox(0, "Failed to setwineventhook", "Fuck", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WNDCLASS wc;
|
||||||
|
memset(&wc, 0, sizeof(wc));
|
||||||
|
wc.lpfnWndProc = WndProc;
|
||||||
|
wc.hInstance = hInstance;
|
||||||
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||||
|
wc.lpszClassName = "sysTrayTest";
|
||||||
|
RegisterClass(&wc);
|
||||||
|
|
||||||
|
win = CreateWindow("sysTrayTest", "You can't see this.", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 50, 50, NULL, NULL, hInstance, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
AudFucker myFucker;
|
||||||
|
|
||||||
|
MSG msg;
|
||||||
|
while(GetMessage(&msg, NULL, 0, 0) > 0)
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
ShitMuter/icon1.ico
Normal file
BIN
ShitMuter/icon1.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
BIN
ShitMuter/icon2.ico
Normal file
BIN
ShitMuter/icon2.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
1
ShitMuter/mute.txt
Normal file
1
ShitMuter/mute.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Cemu.exe
|
||||||
BIN
ShitMuter/resource.h
Normal file
BIN
ShitMuter/resource.h
Normal file
Binary file not shown.
Reference in New Issue
Block a user