--- /dev/null
+
+Version 1.4 (2014-07-10)
+
+ * WinMute can now also mute if the screensaver starts
+ Due to windows restrictions, unmuting the audio can take up to one second
+ after the screensaver resumes.
+
+ * Added a toggle switch to configure if WinMute should unmute at all after
+ a workstation lock or a screensaver run
+
+
+Version 1.3 (2012-02-23)
+
+ * Right-click menu is now correctly dismissed if the user clicks somewhere
+ outside of the menu.
+
+ * Embedded Visual C++ 2010 DLLs. This increases file size by about 100kb, but
+ enables the usage of this tool in workplaces that do not have deployed the
+ Visual C++ 2010 Runtime Environment yet.
+
+ * Vista/7/8: Correctly mute the new device, if the default audio endpoint
+ changes.
+
+ * XP: Greatly improved hardware detection code. WinMute now mutes all devices,
+ instead of just setting the volume of the first device it finds to zero.
+ If the Mute-Button is locked via Group Policies, WinMute will try to
+ use the Volume Slider to "emulate" sound muting.
+
+ * XP: Actively tries to prevent other programs from unmuting the system.
+
+
+Version 1.2 (2011-05-30)
+
+ * Fixed a bug where WinMute could malfunction if the audio
+ device was changed or disconnected during a windows session.
+
+
+Version 0.0 - 1.1
+
+ * These documents have been lost forever...
\ No newline at end of file
--- /dev/null
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html lang="de">
+<head>
+ <meta charset="utf-8">
+ <title>WinMute 1.4 - Readme</title>
+
+ <style type="text/css">
+ <!--
+ html, body { margin: 0; padding: 0 }
+ body { color: #000; background-color: #fff; font-family: "Segoe UI", Verdana, san-serif; font-size: 0.8em; padding: 10px 0 0 10px; line-height: 1.8; }
+ h1, h2 { font-family: "Segoe UI Light", Verdana; }
+ h1 { font-size: 1.8em; margin: 0 0 3px 0; }
+ h2 { font-size: 1.4em; margin: 20px 0 5px 0; }
+ .copyright { color: #aaa; }
+ p { color: #444; width: 600px; margin: 0 0 10px 5px; }
+ -->
+ </style>
+</head>
+<body>
+ <h1>WinMute 1.4</h1>
+ <p class="copyright">© Copyright 2014, Alexander Steinhöfer - <a href="http://www.lx-s.de">www.lx-s.de</a></p>
+
+ <h2>About</h2>
+ <p>WinMute schaltet Windows stumm, sobald sie ihren PC sperren oder sich der Screensaver einschaltet.</p>
+
+ <p>
+ Das ist vor allem in einer Büroumgebung nützlich, wenn Sie Ihren
+ Schreibtisch verlassen, aber die Kollegen nicht mit Musik oder
+ sonstigen Geräuschen aus Ihrem Computer stören möchten.
+ </p>
+
+ <a name="requirements"></a>
+ <h2>Systemvorraussetzungen</h2>
+ <ul>
+ <li>Betriebssystem:
+ <ul>
+ <li>Windows XP SP3 oder aktueller</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h2>Installation</h2>
+ <p>Einfach WinMute in ein Verzeichnis Ihrer Wahl kopieren und das war's!</p>
+ <p>
+ Wenn sie WinMute automatisch mit Windows starten möchten,
+ kopieren sie eine Verknüpfung zur WinMute.exe in den "Autostart"
+ Ordner, den sie im Startmenü unter "Programme" finden (um diesen
+ Ordner zu finden drücken sie Windows+R auf ihrer Tastatur und tippen dann
+ "Shell:Startup" in das Textfeld ein. Bestätigen sie das Fenster mit OK).
+ </p>
+
+ <h2>Deinstallation</h2>
+ <p>
+ Einfach die WinMute.exe und ScreensaverNotify.dll löschen*. Zusätzlich legt WinMute in der Registry (regedit.exe)
+ im Verzeichnis HKEY_CURRENT_USER\Software\lx-systems\WinMute ab. Sollten sie die von WinMute
+ gespeicherten Einstellungen nichtmehr benötigen, können sie diese einfach entfernen.
+ </p>
+ <p>
+ * Es kann sein, dass sich diese dll nicht sofort löschen lässt. Bei einem Fehler probieren sie es einfach
+ spätestens beim nächsten Neustart erneut. Diese Unannehmlichkeit ist leider eine Windows-Limitierung.
+ </p>
+
+ <h2>Benutzung</h2>
+ <p>Einfach starten - und fertig!</p>
+ <p>
+ Sobald das Programm läuft, wird die
+ Lautstärke automatisch auf 0 gedreht, sobald Sie den PC sperren
+ oder sich der Bildschirmschoner aktiviert.
+ Wenn Sie wieder an den PC zurückkehren, wird die Lautstärke auf den
+ ursprünglichen Wert zurückgestellt.
+ </p><p>
+ Wenn dieses Verhalten kurzzeitig deaktiviert werden soll, können
+ Sie dies über einen Rechtsklick auf das Taskbar-Icon bei der Uhr
+ erreichen, indem sie den Haken bei "Mute on Workstation lock" bzw.
+ "Mute on Screensaver start" tentfernen.
+ </p>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>WinMute 1.4 - Readme</title>
+
+ <style type="text/css">
+ <!--
+ html, body { margin: 0; padding: 0 }
+ body { color: #000; background-color: #fff; font-family: "Segoe UI", Verdana, san-serif; font-size: 0.8em; padding: 10px 0 0 10px; line-height: 1.8; }
+ h1, h2 { font-family: "Segoe UI Light", Verdana; }
+ h1 { font-size: 1.8em; margin: 0 0 3px 0; }
+ h2 { font-size: 1.4em; margin: 20px 0 5px 0; }
+ .copyright { color: #aaa; }
+ p { color: #444; width: 600px; margin: 0 0 10px 5px; }
+ -->
+ </style>
+</head>
+<body>
+ <h1>WinMute 1.3</h1>
+ <p class="copyright">© Copyright 2014, by Alexander Steinhöfer - <a href="http://www.lx-s.de">www.lx-s.de</a></p>
+
+ <h2>About</h2>
+ <p>WinMute automatically mutes your PC volume if you lock your screen or the screensaver is running.</p>
+
+ <p>
+ This is very helpful e.g. if you leave your desk and don't want
+ to annoy your co-workers with random sounds or music from
+ your computer.
+ </p>
+
+ <a name="requirements"></a>
+ <h2>Requirements</h2>
+ <ul>
+ <li>Operating System
+ <ul>
+ <li>Windows XP SP3 or newer</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h2>Installation</h2>
+ <p>Unzip it to your favourite directory and you are all set up ;)</p>
+ <p>
+ If you want WinMute to automatically start with your windows,
+ just create a shortcut to the winmute.exe file in the "Startup"
+ folder located in your Windows Startmenu (to open this folder,
+ press Win+R and enter "Shell:Startup", then click "OK").
+ </p>
+
+ <h2>Uninstalling WinMute</h2>
+ <p>
+ Just delete the WinMute.exe and ScreensaverNotify.dll* file from your hard drive.
+ If you want to also remove your personal WinMute settings, then open
+ the registry (regedit.exe) and delete the Folder located in
+ HKEY_CURRENT_USER\Software\lx-systems\WinMute.
+ </p>
+ <p>
+ * It can happen, that you cannot remove this DLL file right away.
+ If you get an error trying to remove it, just wait until your next reboot
+ and delete it afterwards. This is unfortunately a windows limitation.
+ </p>
+
+ <h2>Usage</h2>
+ <p>Start it and that's it!</p>
+ <p>
+ Whenever you lock your screen from now on or the screensaver starts,
+ WinMute will automatically mute your windows volume, and unmute it
+ right away when you come back to your pc.<br>
+ If you want to disable this behaviour temporary, right-click
+ on the taskbar notification icon and uncheck the menu item
+ "Mute on Workstationlock" / "Mute on Screensaver start".
+ </p>
+</body>
+</html>
--- /dev/null
+/*
+ ScreensaverNotify DLL
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include <SDKDDKVer.h>
+#include "ScreensaverNotify.h"
+
+
+/* =============================================================================
+ DLL Globals
+ ========================================================================== */
+
+#pragma data_seg(".shared")
+static HHOOK hook_ = NULL;
+static HWND hNotifyWnd_ = NULL;
+static UINT notifyWndMsgId_ = 0;
+#pragma data_seg()
+#pragma comment(linker, "/SECTION:.shared,RWS")
+
+static HINSTANCE hglobInstance_ = NULL;
+
+/* =============================================================================
+ Hook Function
+ ========================================================================== */
+
+LRESULT CALLBACK MsgHookProc(UINT code, WPARAM wParam, LPARAM lParam)
+{
+ if (code >= 0) {
+ const LPMSG msg = reinterpret_cast<LPMSG>(lParam);
+ if (msg->message == WM_SYSCOMMAND) {
+ if (msg->wParam == SC_SCREENSAVE) {
+ PostMessage(hNotifyWnd_, notifyWndMsgId_, wParam, lParam);
+ }
+ }
+ }
+ return CallNextHookEx(hook_, code, wParam, lParam);
+}
+
+/* =============================================================================
+ API
+ ========================================================================== */
+
+extern "C" {
+
+ WINMUTEDLL_API int RegisterScreensaverHook(HWND hNotifyWnd, UINT notifyWndMsgId)
+ {
+ if (hook_ != NULL) {
+ UnregisterScreensaverHook();
+ }
+ hNotifyWnd_ = hNotifyWnd;
+ notifyWndMsgId_ = notifyWndMsgId;
+ hook_ = SetWindowsHookEx(WH_GETMESSAGE,
+ reinterpret_cast<HOOKPROC>(MsgHookProc),
+ hglobInstance_,
+ 0);
+ return hook_ != NULL;
+ }
+
+ WINMUTEDLL_API void UnregisterScreensaverHook()
+ {
+ if (hook_ != NULL) {
+ UnhookWindowsHookEx(hook_);
+ hook_ = NULL;
+ hNotifyWnd_ = NULL;
+ notifyWndMsgId_ = 0;
+ }
+ }
+
+ BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD reason, LPVOID lpReserved)
+ {
+ UNREFERENCED_PARAMETER(lpReserved);
+
+ if ((reason == DLL_PROCESS_ATTACH) && (hglobInstance_ == NULL)) {
+ hglobInstance_ = hInstance;
+ }
+
+ return TRUE;
+ }
+
+} // extern "C"
\ No newline at end of file
--- /dev/null
+/*
+ ScreensaverNotify DLL
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include <Windows.h>
+
+#ifdef WINMUTEDLL_EXPORTS
+ #define WINMUTEDLL_API __declspec(dllexport)
+#else
+ #define WINMUTEDLL_API __declspec(dllimport)
+#endif
+
+extern "C" {
+
+ WINMUTEDLL_API int RegisterScreensaverHook(HWND hNotifyWnd, UINT notifyWndMsgId);
+
+ WINMUTEDLL_API void UnregisterScreensaverHook();
+
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.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>{A48C241D-70F5-4919-BE06-8C5BE99CCC23}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ScreensaverNotify</RootNamespace>
+ <ProjectName>ScreensaverNotify</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</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>
+ <OutDir>$(SolutionDir)Bin\</OutDir>
+ <TargetName>$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(SolutionDir)Bin\</OutDir>
+ <TargetName>$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WINMUTEDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WINMUTEDLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="ScreensaverNotify.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="ScreensaverNotify.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?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>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="ScreensaverNotify.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="ScreensaverNotify.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project>
\ No newline at end of file
--- /dev/null
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinMute", "WinMute\WinMute.vcxproj", "{488617F0-5DD3-42B5-81ED-A1E9B3117551}"
+ ProjectSection(ProjectDependencies) = postProject
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23} = {A48C241D-70F5-4919-BE06-8C5BE99CCC23}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScreensaverNotify", "ScreensaverNotify\ScreensaverNotify.vcxproj", "{A48C241D-70F5-4919-BE06-8C5BE99CCC23}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Debug|Win32.ActiveCfg = Debug|Win32
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Debug|Win32.Build.0 = Debug|Win32
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Debug|x64.ActiveCfg = Debug|x64
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Debug|x64.Build.0 = Debug|x64
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Release|Win32.ActiveCfg = Release|Win32
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Release|Win32.Build.0 = Release|Win32
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Release|x64.ActiveCfg = Release|x64
+ {488617F0-5DD3-42B5-81ED-A1E9B3117551}.Release|x64.Build.0 = Release|x64
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23}.Debug|Win32.Build.0 = Debug|Win32
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23}.Debug|x64.ActiveCfg = Debug|Win32
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23}.Release|Win32.ActiveCfg = Release|Win32
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23}.Release|Win32.Build.0 = Release|Win32
+ {A48C241D-70F5-4919-BE06-8C5BE99CCC23}.Release|x64.ActiveCfg = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+
+INT_PTR CALLBACK AboutDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ return TRUE;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK) {
+ EndDialog(hDlg, 0);
+ }
+ return 0;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case NM_CLICK:
+ case NM_RETURN: {
+ PNMLINK pNMLink = (PNMLINK)lParam;
+ LITEM item = pNMLink->item;
+ if ((((LPNMHDR)lParam)->idFrom == IDC_LINK_HOMEPAGE) &&
+ (item.iLink == 0)) {
+ ShellExecute(nullptr, _T("open"), item.szUrl, nullptr, nullptr,
+ SW_SHOW);
+ }
+ break;
+ }
+ }
+ return TRUE;
+ case WM_CLOSE:
+ EndDialog(hDlg, 0);
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include "WinAudio.h"
+#include "MMNotificationClient.h"
+
+class WinAudio;
+
+MMNotificationClient::MMNotificationClient(WinAudio* notifyParent) :
+ ref_(1), pEnumerator_(NULL), notifyParent_(notifyParent)
+{
+}
+
+MMNotificationClient::~MMNotificationClient()
+{
+ SafeRelease(&pEnumerator_);
+}
+
+ULONG STDMETHODCALLTYPE MMNotificationClient::AddRef()
+{
+ return InterlockedIncrement(&ref_);
+}
+
+ULONG STDMETHODCALLTYPE MMNotificationClient::Release()
+{
+ ULONG ref = InterlockedDecrement(&ref_);
+ if (ref == 0) {
+ delete this;
+ }
+ return ref;
+}
+
+HRESULT STDMETHODCALLTYPE MMNotificationClient::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;
+}
+
+
+HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDefaultDeviceChanged(
+ EDataFlow,
+ ERole,
+ LPCWSTR)
+{
+ if (notifyParent_) {
+ notifyParent_->ShouldReInit();
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceAdded(LPCWSTR)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceRemoved(LPCWSTR)
+{
+ if (notifyParent_) {
+ notifyParent_->ShouldReInit();
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceStateChanged(LPCWSTR,
+ DWORD)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE MMNotificationClient::OnPropertyValueChanged(
+ LPCWSTR,
+ const PROPERTYKEY)
+{
+ return S_OK;
+}
+
+
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include <Mmdeviceapi.h>
+
+class WinAudio;
+
+class MMNotificationClient : public IMMNotificationClient {
+public:
+ MMNotificationClient(WinAudio* notifyParent);
+ ~MMNotificationClient();
+
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface);
+
+ HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role,
+ LPCWSTR pwstrDeviceId);
+ HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId);
+ HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId);
+ HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId,
+ DWORD dwNewState);
+ HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId,
+ const PROPERTYKEY key);
+
+private:
+ LONG ref_;
+ IMMDeviceEnumerator *pEnumerator_;
+ WinAudio* notifyParent_;
+};
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include "ScreensaverNotifier.h"
+
+/* ========================================================================== */
+/* Globals */
+/* ========================================================================== */
+
+extern HINSTANCE hglobInstance;
+
+static LPCTSTR SCRSVER_NOTIFY_WND_CLASS = _T("ScreensaverNotify");
+
+#define SCRSV_TIMER_ID 1
+
+/* ========================================================================== */
+/* Window Helper */
+/* ========================================================================== */
+
+
+static LRESULT CALLBACK ScrsvrWndProc(HWND hWnd, UINT msg, WPARAM wParam,
+ LPARAM lParam)
+{
+ auto sn = reinterpret_cast<ScreensaverNotifier*>(
+ GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ switch (msg) {
+ case WM_NCCREATE: {
+ LPCREATESTRUCTW cs = reinterpret_cast<LPCREATESTRUCTW>(lParam);
+ SetWindowLongPtr(hWnd, GWLP_USERDATA,
+ reinterpret_cast<LONG>(cs->lpCreateParams));
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ return (sn) ? sn->WindowProc(hWnd, msg, wParam, lParam)
+ : DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+/* ========================================================================== */
+/* Construction, Destruction */
+/* ========================================================================== */
+
+ScreensaverNotifier::ScreensaverNotifier() :
+ hookDll_(nullptr),
+ regHook_(nullptr),
+ unregHook_(nullptr),
+ hookWndMsg_(0)
+{ }
+
+ScreensaverNotifier::~ScreensaverNotifier()
+{
+ Unload();
+}
+
+/* ========================================================================== */
+/* Init, Unload */
+/* ========================================================================== */
+
+bool ScreensaverNotifier::Init()
+{
+ if (hookDll_ != nullptr) {
+ return true;
+ }
+ return RegisterWindowClass() &&
+ InitWindow() &&
+ InitWindowMessage() &&
+ InitHookDll();
+}
+
+bool ScreensaverNotifier::InitWindow()
+{
+ hWnd_ = CreateWindowEx(WS_EX_TOOLWINDOW,
+ SCRSVER_NOTIFY_WND_CLASS,
+ NULL,
+ WS_POPUP,
+ 0, 0, 0, 0,
+ HWND_MESSAGE,
+ 0,
+ hglobInstance,
+ this);
+ if (hWnd_ == NULL) {
+ PrintWindowsError(_T("CreateWindow"));
+ return false;
+ }
+ return true;
+}
+
+bool ScreensaverNotifier::InitWindowMessage()
+{
+ hookWndMsg_ = RegisterWindowMessage(_T("WinMuteScreenSaveNotifyMsg"));
+ if (hookWndMsg_ == 0) {
+ PrintWindowsError(_T("RegisterWindowMessage"));
+ return false;
+ }
+ return true;
+}
+
+bool ScreensaverNotifier::InitHookDll()
+{
+ if (hookDll_ == nullptr) {
+ hookDll_ = LoadLibrary(_T("ScreensaverNotify"));
+ if (hookDll_ == nullptr) {
+ PrintWindowsError(_T("LoadLibrary"));
+ } else {
+ regHook_ = reinterpret_cast<RegisterHook>(
+ GetProcAddress(hookDll_, "RegisterScreensaverHook"));
+ unregHook_ = reinterpret_cast<UnregisterHook>(
+ GetProcAddress(hookDll_, "UnregisterScreensaverHook"));
+ if (regHook_ == NULL || unregHook_ == NULL) {
+ Unload();
+ }
+ }
+ }
+ return hookDll_ != NULL;
+
+}
+
+bool ScreensaverNotifier::RegisterWindowClass()
+{
+ WNDCLASS wc = { 0 };
+ wc.hIcon = LoadIcon(hglobInstance, MAKEINTRESOURCE(IDI_APP));
+ wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+ wc.hInstance = hglobInstance;
+ wc.lpfnWndProc = ScrsvrWndProc;
+ wc.lpszClassName = SCRSVER_NOTIFY_WND_CLASS;
+
+ if (!RegisterClass(&wc)) {
+ PrintWindowsError(_T("RegisterClass"));
+ return false;
+ }
+ return true;
+}
+
+void ScreensaverNotifier::Unload()
+{
+ if (hookDll_) {
+ FreeLibrary(hookDll_);
+ regHook_ = nullptr;
+ unregHook_ = nullptr;
+ }
+}
+
+/* ========================================================================== */
+/* Notifications */
+/* ========================================================================== */
+
+bool ScreensaverNotifier::ActivateNotifications(HWND hNotifyWnd)
+{
+ hNotifyWnd_ = hNotifyWnd;
+ if (regHook_ != nullptr) {
+ return regHook_(hWnd_, hookWndMsg_) != 0;
+ }
+ return false;
+}
+
+void ScreensaverNotifier::ClearNotifications()
+{
+ hNotifyWnd_ = nullptr;
+ if (unregHook_ != nullptr) {
+ unregHook_();
+ }
+}
+
+void ScreensaverNotifier::StartScreensaverPollTimer(bool start)
+{
+ if (start) {
+ if (SetTimer(hWnd_, SCRSV_TIMER_ID, 1000, NULL) == 0) {
+ PrintWindowsError(_T("SetTimer"));
+ }
+ } else {
+ KillTimer(hWnd_, SCRSV_TIMER_ID);
+ }
+}
+
+/* ========================================================================== */
+/* Window Proc */
+/* ========================================================================== */
+
+LRESULT CALLBACK ScreensaverNotifier::WindowProc(HWND hWnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ static UINT uTaskbarRestart = 0;
+ switch (msg) {
+ case WM_CREATE: {
+ return TRUE;
+ }
+ case WM_TIMER: {
+ if (wParam == SCRSV_TIMER_ID) {
+ BOOL isRunning = FALSE;
+ if (SystemParametersInfo(SPI_GETSCREENSAVERRUNNING,
+ 0,
+ &isRunning,
+ FALSE) == NULL) {
+ PrintWindowsError(_T("SystemParametersInfo"));
+ } else {
+ if (!isRunning) {
+ StartScreensaverPollTimer(false);
+ SendMessage(hNotifyWnd_, WM_SCRNSAVE_CHANGE, SCRNSAVE_STOP, 0);
+ }
+ }
+ }
+ return 0;
+ }
+ default:
+ if (hookWndMsg_ != 0 && msg == hookWndMsg_) {
+ SendMessage(hNotifyWnd_, WM_SCRNSAVE_CHANGE, SCRNSAVE_START, 0);
+ StartScreensaverPollTimer();
+ }
+ break;
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "StdAfx.h"
+
+#define WM_SCRNSAVE_CHANGE (WM_APP + 100)
+
+#define SCRNSAVE_START 1
+#define SCRNSAVE_STOP 2
+
+class ScreensaverNotifier {
+public:
+ ScreensaverNotifier();
+ ~ScreensaverNotifier();
+
+ ScreensaverNotifier(const ScreensaverNotifier&) = delete;
+ ScreensaverNotifier& operator= (const ScreensaverNotifier&) = delete;
+
+ bool Init();
+ void Unload();
+
+ bool ActivateNotifications(HWND hNotifyWnd);
+ void ClearNotifications();
+
+
+ LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+private:
+ typedef int(*RegisterHook)(HWND, UINT);
+ typedef void(*UnregisterHook)(void);
+
+
+ HINSTANCE hookDll_;
+ HWND hWnd_, hNotifyWnd_;
+ UINT hookWndMsg_;
+
+ RegisterHook regHook_;
+ UnregisterHook unregHook_;
+
+ void StartScreensaverPollTimer(bool start = true);
+
+ bool InitHookDll();
+ bool RegisterWindowClass();
+ bool InitWindow();
+ bool InitWindowMessage();
+};
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include "Settings.h"
+
+static const LPCWSTR LX_SYSTEMS_SUBKEY = _T("SOFTWARE\\lx-systems\\WinMute");
+
+
+static LPCWSTR KeyToStr(SettingsKey key)
+{
+ LPCWSTR keyStr = nullptr;
+ switch (key) {
+ case SettingsKey::MUTE_ON_LOCK:
+ keyStr = _T("MuteOnLock");
+ break;
+ case SettingsKey::MUTE_ON_SCREENSAVER:
+ keyStr = _T("MuteOnScreensaver");
+ break;
+ case SettingsKey::RESTORE_AUDIO:
+ keyStr = _T("RestoreAudio");
+ break;
+ }
+ return keyStr;
+}
+
+
+Settings::Settings() :
+ hRegSettingsKey_(nullptr)
+{ }
+
+Settings::~Settings()
+{
+ Unload();
+}
+
+bool Settings::Init()
+{
+ if (hRegSettingsKey_ == nullptr) {
+ DWORD regError = RegCreateKeyEx(HKEY_CURRENT_USER,
+ LX_SYSTEMS_SUBKEY,
+ 0,
+ NULL,
+ 0,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hRegSettingsKey_,
+ NULL);
+ if (regError != ERROR_SUCCESS) {
+ PrintWindowsError(_T("RegCreateKeyEx"), regError);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void Settings::Unload()
+{
+ RegCloseKey(hRegSettingsKey_);
+ hRegSettingsKey_ = nullptr;
+}
+
+DWORD Settings::QueryValue(SettingsKey key, DWORD defValue)
+{
+ auto keyStr = KeyToStr(key);
+ assert(keyStr != nullptr);
+
+ DWORD value;
+ DWORD size = sizeof(DWORD);
+ DWORD regError = RegQueryValueEx(hRegSettingsKey_,
+ keyStr,
+ 0,
+ NULL,
+ reinterpret_cast<LPBYTE>(&value),
+ &size);
+ if (regError == ERROR_FILE_NOT_FOUND) {
+ return defValue;
+ } else if (regError != ERROR_SUCCESS) {
+ PrintWindowsError(_T("RegCreateKeyEx"), regError);
+ return defValue;
+ }
+
+ return value;
+}
+
+bool Settings::SetValue(SettingsKey key, DWORD value)
+{
+ auto keyStr = KeyToStr(key);
+ assert(keyStr != nullptr);
+
+ DWORD regError = RegSetValueEx(hRegSettingsKey_,
+ keyStr,
+ 0,
+ REG_DWORD,
+ reinterpret_cast<BYTE*>(&value),
+ sizeof(DWORD));
+ if (regError != ERROR_SUCCESS) {
+ PrintWindowsError(_T("RegCreateKeyEx"), regError);
+ return false;
+ }
+ return true;
+}
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "StdAfx.h"
+
+enum class SettingsKey {
+ MUTE_ON_LOCK,
+ MUTE_ON_SCREENSAVER,
+ RESTORE_AUDIO
+};
+
+class Settings {
+public:
+ Settings();
+ ~Settings();
+
+ Settings(const Settings&) = delete;
+ Settings& operator=(const Settings&) = delete;
+
+ bool Init();
+ void Unload();
+
+ DWORD QueryValue(SettingsKey key, DWORD defValue);
+ bool SetValue(SettingsKey key, DWORD value);
+
+private:
+ HKEY hRegSettingsKey_;
+};
\ No newline at end of file
--- /dev/null
+/* WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#ifdef _UNICODE
+ #if defined _M_IX86
+ #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+ #elif defined _M_IA64
+ #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+ #elif defined _M_X64
+ #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+ #else
+ #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+ #endif
+#endif
+
+#define STRICT
+#define _WIN32_WINNT 0x0600
+#include <sdkddkver.h>
+
+#include <cassert>
+#include <string>
+#include <memory>
+#include <vector>
+#include <algorithm>
+
+#include <windows.h>
+#include <commctrl.h>
+#include <WtsApi32.h>
+#include <tchar.h>
+#include <strsafe.h>
+#include <time.h>
+
+#include "resource.h"
+
+#include "ScreensaverNotifier.h"
+#include "Settings.h"
+#include "TrayIcon.h"
+#include "WinMute.h"
+#include "VersionHelper.h"
+
+template<class Interface>
+inline void SafeRelease(Interface** ppInterfaceToRelease)
+{
+ if (*ppInterfaceToRelease) {
+ (*ppInterfaceToRelease)->Release();
+ (*ppInterfaceToRelease) = nullptr;
+ }
+}
+
+#ifdef UNICODE
+ typedef std::basic_string<wchar_t> tstring;
+#else
+ typedef std::basic_string<char> tstring;
+#endif
+
+// Utility
+void PrintWindowsError(LPTSTR lpszFunction, DWORD lastError = -1);
+
+const LPCTSTR PROGRAM_NAME = _T("WinMute");
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+
+TrayIcon::TrayIcon() :
+ hIcon_(0), trayID_(0), hWnd_(0), iconVisible_(false)
+{
+
+}
+
+TrayIcon::TrayIcon(HWND hWnd, UINT trayID, HICON hIcon,
+ const std::wstring& tooltip, bool show) :
+ iconVisible_(false)
+{
+ Init(hWnd, trayID, hIcon, tooltip, show);
+}
+
+void TrayIcon::Init(HWND hWnd, UINT trayID, HICON hIcon,
+ const std::wstring& tooltip, bool show)
+{
+ if (!hIcon) {
+ hIcon_ = LoadIcon(0, MAKEINTRESOURCE(IDI_APPLICATION));
+ } else {
+ hIcon_ = hIcon;
+ }
+
+ tooltip_ = tooltip;
+ trayID_ = trayID;
+ hWnd_ = hWnd;
+
+ if (show) {
+ Show();
+ }
+}
+
+TrayIcon::~TrayIcon()
+{
+ Hide();
+ DestroyTrayIcon();
+}
+
+void TrayIcon::Hide()
+{
+ if (iconVisible_) {
+ if (RemoveNotifyIcon()) {
+ iconVisible_ = false;
+ }
+ }
+}
+
+void TrayIcon::Show()
+{
+ if (!iconVisible_) {
+ if(AddNotifyIcon()) {
+ iconVisible_ = true;
+ }
+ }
+}
+
+void TrayIcon::ChangeIcon(HICON hNewIcon)
+{
+ if (!hNewIcon) {
+ return;
+ }
+ bool oldIconVisible = iconVisible_;
+
+ DestroyTrayIcon();
+ hIcon_ = hNewIcon;
+
+ if (oldIconVisible) {
+ NOTIFYICONDATA tnid;
+
+ tnid.cbSize = sizeof(NOTIFYICONDATA);
+ tnid.hWnd = hWnd_;
+ tnid.uID = trayID_;
+ tnid.hIcon = hIcon_;
+ tnid.uFlags = NIF_ICON;
+
+ if (!Shell_NotifyIcon(NIM_MODIFY, &tnid))
+ return;
+
+ iconVisible_ = true;
+ }
+
+ return;
+}
+
+void TrayIcon::ChangeText(const std::wstring& tooltip)
+{
+ tooltip_ = tooltip;
+
+ if (iconVisible_)
+ ChangeText();
+}
+
+void TrayIcon::DestroyTrayIcon()
+{
+ if (hIcon_) {
+ DestroyIcon(hIcon_);
+ hIcon_ = 0;
+ }
+}
+
+bool TrayIcon::AddNotifyIcon()
+{
+ NOTIFYICONDATA tnid;
+
+ tnid.cbSize = sizeof(NOTIFYICONDATA);
+ tnid.hWnd = hWnd_;
+ tnid.uID = trayID_;
+ tnid.uFlags = NIF_ICON|NIF_TIP|NIF_MESSAGE;
+ tnid.hIcon = hIcon_;
+ tnid.uCallbackMessage = WM_TRAYICON;
+ lstrcpyn(tnid.szTip, tooltip_.c_str(), sizeof(tnid.szTip) / sizeof(TCHAR));
+
+ return Shell_NotifyIcon(NIM_ADD, &tnid) != 0;
+}
+
+bool TrayIcon::RemoveNotifyIcon()
+{
+ NOTIFYICONDATA tnid;
+
+ tnid.cbSize = sizeof(NOTIFYICONDATA);
+ tnid.hWnd = hWnd_;
+ tnid.uID = trayID_;
+
+ return Shell_NotifyIcon(NIM_DELETE, &tnid) != 0;
+}
+
+bool TrayIcon::ChangeText()
+{
+ NOTIFYICONDATA tnid;
+
+ tnid.cbSize = sizeof(NOTIFYICONDATA);
+ tnid.hWnd = hWnd_;
+ tnid.uID = trayID_;
+ tnid.uFlags = NIF_TIP;
+ lstrcpyn(tnid.szTip, tooltip_.c_str(), sizeof(tnid.szTip) / sizeof(TCHAR));
+
+ return Shell_NotifyIcon(NIM_MODIFY, &tnid) != 0;
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+#include "StdAfx.h"
+
+#define WM_TRAYICON (WM_APP + 700)
+
+class TrayIcon{
+public:
+ TrayIcon();
+ TrayIcon(HWND hWnd, UINT trayID, HICON hIcon, const std::wstring& tooltip,
+ bool show);
+ ~TrayIcon();
+ void Init(HWND hWnd, UINT trayID, HICON hIcon, const std::wstring& tooltip,
+ bool show);
+ void Hide();
+ void Show();
+ bool IsShown() const { return iconVisible_; }
+ void ChangeIcon(HICON hNewIcon);
+ void ChangeText(const std::wstring& tooltip);
+
+private:
+ void DestroyTrayIcon();
+ bool AddNotifyIcon();
+ bool RemoveNotifyIcon();
+ bool ChangeText();
+
+ bool iconVisible_;
+ UINT trayID_;
+ HICON hIcon_;
+ HWND hWnd_;
+ std::wstring tooltip_;
+};
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+
+void PrintWindowsError(LPTSTR lpszFunction, DWORD lastError)
+{
+ // Retrieve the system error message for the last-error code
+ if (lastError == -1) {
+ lastError = GetLastError();
+ }
+
+ LPVOID lpMsgBuf;
+ if (FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr) != 0) {
+
+ // Display the error message and exit the process
+ LPVOID lpDisplayBuf = reinterpret_cast<LPVOID>(LocalAlloc(LMEM_ZEROINIT,
+ (lstrlen(static_cast<LPCTSTR>(lpMsgBuf)) +
+ lstrlen(static_cast<LPCTSTR>(lpszFunction)) + 40)
+ * sizeof(TCHAR)));
+ if (lpDisplayBuf) {
+ StringCchPrintf((LPTSTR)lpDisplayBuf,
+ LocalSize(lpDisplayBuf),
+ _T("%s failed with error %d: %s"),
+ lpszFunction, lastError, lpMsgBuf);
+
+ MessageBox(nullptr, static_cast<LPCTSTR>(lpDisplayBuf), _T("Error"),
+ MB_ICONERROR | MB_OK);
+
+ LocalFree(lpDisplayBuf);
+ }
+ LocalFree(lpMsgBuf);
+ }
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "StdAfx.h"
+
+#ifndef _versionhelpers_H_INCLUDED_ // avoid conflict with MS versionhelpers
+
+inline bool IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
+{
+ OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0 };
+ DWORDLONG const dwlConditionMask = VerSetConditionMask(
+ VerSetConditionMask(
+ VerSetConditionMask(
+ 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
+ VER_MINORVERSION, VER_GREATER_EQUAL),
+ VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+
+ osvi.dwMajorVersion = wMajorVersion;
+ osvi.dwMinorVersion = wMinorVersion;
+ osvi.wServicePackMajor = wServicePackMajor;
+
+ return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
+}
+
+inline bool IsWindowsXPOrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
+}
+
+inline bool IsWindowsVistaOrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include <mmdeviceapi.h>
+
+#pragma warning(disable : 4201)
+# include <endpointvolume.h>
+#pragma warning(default : 4201)
+
+#include "WinAudio.h"
+#include "VistaAudioSessionEvents.h"
+#include "MMNotificationClient.h"
+
+VistaAudio::VistaAudio() :
+ endpointVolume_(nullptr), sessionControl_(nullptr),
+ wasapiAudioEvents_(nullptr), mmnAudioEvents_(nullptr),
+ deviceEnumerator_(nullptr), reInit_(false)
+{
+ CoInitialize(nullptr);
+}
+
+VistaAudio::~VistaAudio()
+{
+ Uninit();
+ CoUninitialize();
+}
+
+bool VistaAudio::Init(HWND hParent)
+{
+ hParent_ = hParent;
+ reInit_ = false;
+
+ if(FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator),
+ nullptr, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&deviceEnumerator_)))) {
+ return false;
+ }
+
+ IMMDevice *defaultDevice = nullptr;
+ if(FAILED(deviceEnumerator_->GetDefaultAudioEndpoint(eRender, eConsole,
+ &defaultDevice))) {
+ MessageBox(0, _T("Failed to get default audio endpoint device"),
+ PROGRAM_NAME, MB_ICONERROR);
+ return false;
+ }
+
+
+ IAudioSessionManager2* sessionManager2 = nullptr;
+ if (FAILED(defaultDevice->Activate(__uuidof(IAudioSessionManager2),
+ CLSCTX_INPROC_SERVER, nullptr,
+ reinterpret_cast<LPVOID*>(&sessionManager2)))) {
+ MessageBox(0, _T("Failed to retrieve audio session manager."),
+ PROGRAM_NAME, MB_ICONERROR);
+ SafeRelease(&defaultDevice);
+ return false;
+ }
+
+ if (FAILED(sessionManager2->GetAudioSessionControl(nullptr, 0,
+ &sessionControl_))) {
+ MessageBox(0, _T("Failed to retrieve session control."), PROGRAM_NAME,
+ MB_ICONERROR);
+ SafeRelease(&sessionManager2);
+ return false;
+ }
+ SafeRelease(&sessionManager2);
+
+ wasapiAudioEvents_ = new VistaAudioSessionEvents(this);
+ if (wasapiAudioEvents_) {
+ sessionControl_->RegisterAudioSessionNotification(wasapiAudioEvents_);
+ }
+ mmnAudioEvents_ = new MMNotificationClient(this);
+ if (mmnAudioEvents_) {
+ deviceEnumerator_->RegisterEndpointNotificationCallback(mmnAudioEvents_);
+ }
+
+ if (FAILED(defaultDevice->Activate(__uuidof(IAudioEndpointVolume),
+ CLSCTX_INPROC_SERVER, nullptr,
+ reinterpret_cast<LPVOID*>(&endpointVolume_)))) {
+ MessageBox(0, _T("Failed to activate default audio device."),
+ PROGRAM_NAME, MB_ICONERROR);
+ SafeRelease(&defaultDevice);
+ return false;
+ }
+ defaultDevice->Release();
+
+ return true;
+}
+
+void VistaAudio::Uninit()
+{
+ if (sessionControl_ && wasapiAudioEvents_) {
+ sessionControl_->UnregisterAudioSessionNotification(wasapiAudioEvents_);
+ }
+ if (deviceEnumerator_ && mmnAudioEvents_) {
+ deviceEnumerator_->UnregisterEndpointNotificationCallback(mmnAudioEvents_);
+ }
+
+ SafeRelease(&wasapiAudioEvents_);
+ SafeRelease(&mmnAudioEvents_);
+ SafeRelease(&sessionControl_);
+ SafeRelease(&endpointVolume_);
+ SafeRelease(&deviceEnumerator_);
+}
+
+void VistaAudio::ShouldReInit()
+{
+ reInit_ = true;
+}
+
+bool VistaAudio::CheckForReInit()
+{
+ bool ok = true;
+ if (reInit_) {
+ Uninit();
+ ok = Init(hParent_);
+ }
+ return ok;
+}
+
+bool VistaAudio::IsMuted()
+{
+ if (CheckForReInit()) {
+ BOOL isMuted = FALSE;
+ endpointVolume_->GetMute(&isMuted);
+ return isMuted == TRUE;
+ }
+ return false;
+}
+
+void VistaAudio::Mute()
+{
+ if (CheckForReInit()) {
+ BOOL isMuted = FALSE;
+ endpointVolume_->GetMute(&isMuted);
+ if (!isMuted) {
+ endpointVolume_->SetMute(TRUE, nullptr);
+ }
+ }
+}
+
+void VistaAudio::UnMute()
+{
+ if (CheckForReInit()) {
+ BOOL isMuted = TRUE;
+ endpointVolume_->GetMute(&isMuted);
+ if (isMuted) {
+ endpointVolume_->SetMute(FALSE, nullptr);
+ }
+ }
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include "WinAudio.h"
+#include "VistaAudioSessionEvents.h"
+
+
+VistaAudioSessionEvents::VistaAudioSessionEvents(WinAudio* notifyParent) :
+ ref_(1)
+{
+ notifyParent_ = notifyParent;
+}
+
+VistaAudioSessionEvents::~VistaAudioSessionEvents()
+{
+}
+
+ULONG STDMETHODCALLTYPE VistaAudioSessionEvents::AddRef()
+{
+ return InterlockedIncrement(&ref_);
+}
+
+ULONG STDMETHODCALLTYPE VistaAudioSessionEvents::Release()
+{
+ ULONG ref = InterlockedDecrement(&ref_);
+ if (ref == 0) {
+ delete this;
+ }
+ return ref;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::QueryInterface(
+ REFIID riid,
+ VOID **ppvInterface)
+{
+ if (riid == IID_IUnknown) {
+ AddRef();
+ *ppvInterface = reinterpret_cast<IUnknown*>(this);
+ } else if (riid == __uuidof(IAudioSessionEvents)) {
+ AddRef();
+ *ppvInterface = reinterpret_cast<IAudioSessionEvents*>(this);
+ } else {
+ *ppvInterface = nullptr;
+ return E_NOINTERFACE;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnDisplayNameChanged(
+ LPCWSTR /*newDisplayName*/,
+ LPCGUID /*eventContext*/)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnIconPathChanged(
+ LPCWSTR /*newIconPath*/,
+ LPCGUID /*eventContext*/)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnSimpleVolumeChanged(
+ float /*newVolume*/,
+ BOOL /*newMute*/,
+ LPCGUID /*eventContext*/)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnChannelVolumeChanged(
+ DWORD /*channelCount*/,
+ float* /*newChannelVolumeArray[]*/,
+ DWORD /*changedChannel*/,
+ LPCGUID /*eventContext*/)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnGroupingParamChanged(
+ LPCGUID /*newGroupingParam*/,
+ LPCGUID /*eventContext*/)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnStateChanged(
+ AudioSessionState /*newState*/)
+{
+ return S_OK;
+}
+
+/* See
+ * http://blogs.msdn.com/b/larryosterman/archive/2007/10/31/what-happens-when-audio-rendering-fails.aspx
+ * for detailed information about each of these entries */
+HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnSessionDisconnected(
+ AudioSessionDisconnectReason disconnectReason)
+{
+
+ switch (disconnectReason) {
+ case DisconnectReasonDeviceRemoval:
+ case DisconnectReasonFormatChanged:
+ case DisconnectReasonSessionDisconnected:
+ notifyParent_->ShouldReInit();
+ break;
+ case DisconnectReasonServerShutdown:
+ MessageBox(0, _T("The audio service has been shut down. ")
+ _T("WinMute is not able to recover from that condition.\n")
+ _T("Please try restarting the program"), PROGRAM_NAME,
+ MB_ICONWARNING | MB_OK);
+ break;
+ case DisconnectReasonSessionLogoff:
+ break;
+ case DisconnectReasonExclusiveModeOverride:
+ break;
+ }
+ return S_OK;
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include <audiopolicy.h>
+
+class WinAudio;
+
+class VistaAudioSessionEvents : public IAudioSessionEvents {
+public:
+ VistaAudioSessionEvents(WinAudio* notifyParent);
+ ~VistaAudioSessionEvents();
+
+ // IUnknown methods -- AddRef, Release, and QueryInterface
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface);
+
+ // Notification methods for audio session events
+ HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(
+ LPCWSTR newDisplayName,
+ LPCGUID eventContext);
+
+ HRESULT STDMETHODCALLTYPE OnIconPathChanged(
+ LPCWSTR newIconPath,
+ LPCGUID eventContext);
+
+ HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(
+ float newVolume,
+ BOOL newMute,
+ LPCGUID eventContext);
+
+ HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(
+ DWORD channelCount,
+ float newChannelVolumeArray[],
+ DWORD changedChannel,
+ LPCGUID eventContext);
+
+ HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(
+ LPCGUID newGroupingParam,
+ LPCGUID eventContext);
+
+ HRESULT STDMETHODCALLTYPE OnStateChanged(AudioSessionState newState);
+
+ HRESULT STDMETHODCALLTYPE OnSessionDisconnected(
+ AudioSessionDisconnectReason disconnectReason);
+
+private:
+ LONG ref_;
+ WinAudio* notifyParent_;
+};
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "StdAfx.h"
+
+class WinAudio {
+public:
+ virtual bool Init(HWND hParent) = 0;
+ virtual void ShouldReInit() = 0;
+ virtual bool IsMuted() = 0;
+ virtual void Mute() = 0;
+ virtual void UnMute() = 0;
+ virtual ~WinAudio() { };
+};
+
+class XPAudio : public WinAudio {
+public:
+ XPAudio();
+ ~XPAudio();
+
+ bool Init(HWND hParent);
+ void ShouldReInit();
+ bool IsMuted();
+ void Mute();
+ void UnMute();
+
+ LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
+private:
+ struct MixerDevice {
+ HMIXER hMixer;
+ bool useMute;
+ DWORD volCtrlID;
+ DWORD muteCtrlID;
+ DWORD oldValue;
+ };
+ bool InitNotifyWindow(HWND hParent);
+ bool GetMuteControl(MixerDevice& md);
+ DWORD GetOldControlValue(const MixerDevice& md);
+ void MuteDevice(MixerDevice& md, bool saveOldValue);
+ void SetDeviceValue(MixerDevice& md, DWORD val);
+
+ std::vector<MixerDevice> mixers_;
+ HWND hNotifyWnd_;
+ bool currentlyMuted_;
+ time_t muteTime_;
+
+ // non copy-able
+ XPAudio(const XPAudio& other);
+ XPAudio& operator=(const XPAudio& other);
+};
+
+// Forwards
+struct IAudioEndpointVolume;
+struct IAudioSessionControl;
+struct IMMDeviceEnumerator;
+class VistaAudioSessionEvents;
+class MMNotificationClient;
+
+class VistaAudio : public WinAudio {
+public:
+ VistaAudio();
+ ~VistaAudio();
+
+ bool Init(HWND hParent);
+ void ShouldReInit();
+ bool IsMuted();
+ void Mute();
+ void UnMute();
+private:
+ void Uninit();
+ bool CheckForReInit();
+
+ IAudioEndpointVolume* endpointVolume_;
+ IAudioSessionControl* sessionControl_;
+ IMMDeviceEnumerator *deviceEnumerator_;
+ VistaAudioSessionEvents* wasapiAudioEvents_;
+ MMNotificationClient* mmnAudioEvents_;
+
+ bool reInit_;
+ float oldVolume_;
+ HWND hParent_;
+
+ // non copy-able
+ VistaAudio(const VistaAudio& other);
+ VistaAudio& operator=(const VistaAudio& other);
+};
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+
+HINSTANCE hglobInstance;
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
+{
+ HANDLE hMutex = CreateMutex(nullptr, TRUE, _T("BinaryStudiosWinMute"));
+ if (hMutex == NULL) {
+ return FALSE;
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS) {
+ ReleaseMutex(hMutex);
+ MessageBox(0, _T("WinMute is already running."), PROGRAM_NAME,
+ MB_ICONINFORMATION);
+ return FALSE;
+ }
+
+ hglobInstance = hInstance;
+
+ HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
+
+ // <Init Common Controls>
+ INITCOMMONCONTROLSEX initComCtrl;
+ initComCtrl.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ initComCtrl.dwICC = ICC_LINK_CLASS;
+ if (InitCommonControlsEx(&initComCtrl) == FALSE){
+ MessageBox(0, _T("Fatal Error:\n")
+ _T("Failed to register extended window controls"),
+ PROGRAM_NAME, MB_ICONSTOP);
+ ReleaseMutex(hMutex);
+ return FALSE;
+ }
+ // </Init Common Controls>
+
+ // <Init COM>
+ if (CoInitializeEx(0, COINIT_APARTMENTTHREADED) != S_OK) {
+ MessageBox(0, _T("Fatal Error:\nFailed to initialize COM library."),
+ PROGRAM_NAME, MB_ICONERROR);
+ ReleaseMutex(hMutex);
+ return FALSE;
+ }
+
+ MSG msg = {0};
+ WinMute program;
+ if (program.Init()) {
+ while (GetMessage(&msg, nullptr, 0, 0)) {
+ HWND hwnd = GetForegroundWindow();
+ if (!IsWindow(hwnd) || !IsDialogMessage(hwnd, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+
+ CoUninitialize();
+ ReleaseMutex(hMutex);
+ return static_cast<int>(msg.wParam);
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include "WinMute.h"
+#include "WinAudio.h"
+
+extern HINSTANCE hglobInstance;
+extern INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
+
+static LPCTSTR WINMUTE_CLASS_NAME = _T("WinMute");
+
+static LRESULT CALLBACK WinMuteWndProc(HWND hWnd, UINT msg, WPARAM wParam,
+ LPARAM lParam)
+{
+ auto wm = reinterpret_cast<WinMute*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ switch (msg) {
+ case WM_NCCREATE: {
+ LPCREATESTRUCTW cs = reinterpret_cast<LPCREATESTRUCTW>(lParam);
+ SetWindowLongPtr(hWnd, GWLP_USERDATA,
+ reinterpret_cast<LONG>(cs->lpCreateParams));
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ return (wm) ? wm->WindowProc(hWnd, msg, wParam, lParam)
+ : DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+WinMute::WinMute() :
+ muteOnLock_(true),
+ muteOnScreensaver_(true),
+ restoreAudio_(true)
+{ }
+
+WinMute::~WinMute()
+{
+ Unload();
+}
+
+bool WinMute::RegisterWindowClass()
+{
+ WNDCLASS wc={0};
+ wc.hIcon = LoadIcon(hglobInstance, MAKEINTRESOURCE(IDI_APP));
+ wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+ wc.hInstance = hglobInstance;
+ wc.lpfnWndProc = WinMuteWndProc;
+ wc.lpszClassName = WINMUTE_CLASS_NAME;
+
+ if (!RegisterClass(&wc)) {
+ PrintWindowsError(_T("RegisterClass"));
+ return false;
+ }
+ return true;
+}
+
+bool WinMute::InitWindow()
+{
+ hWnd_ = CreateWindowEx(WS_EX_TOOLWINDOW, WINMUTE_CLASS_NAME, PROGRAM_NAME,
+ WS_POPUP, 0, 0, 0, 0, HWND_MESSAGE, 0, hglobInstance,
+ this);
+ if (hWnd_ == nullptr) {
+ PrintWindowsError(_T("CreateWindowEx"));
+ return false;
+ }
+ return true;
+}
+
+bool WinMute::InitAudio()
+{
+ if (IsWindowsVistaOrGreater()) {
+ audio_ = std::unique_ptr<WinAudio>(new VistaAudio);
+ } else if (IsWindowsXPOrGreater()) {
+ audio_ = std::unique_ptr<XPAudio>(new XPAudio);
+ } else {
+ MessageBox(0, _T("Only Windows versions XP and newer are supported"),
+ 0, MB_ICONERROR);
+ return false;
+ }
+
+ if (!audio_->Init(hWnd_)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool WinMute::InitTrayMenu()
+{
+ hTrayMenu_ = LoadMenu(hglobInstance, MAKEINTRESOURCE(IDR_TRAYMENU));
+ if (!hTrayMenu_) {
+ PrintWindowsError(_T("LoadMenu"));
+ return false;
+ } else if (CheckMenuItem(hTrayMenu_, ID_TRAYMENU_MUTEONLOCK,
+ muteOnLock_ ? MF_CHECKED : MF_UNCHECKED) == -1 ||
+ CheckMenuItem(hTrayMenu_, ID_TRAYMENU_MUTEONSCREENSAVER,
+ muteOnScreensaver_ ? MF_CHECKED : MF_UNCHECKED) == -1 ||
+ CheckMenuItem(hTrayMenu_, ID_TRAYMENU_RESTOREAUDIO,
+ restoreAudio_ ? MF_CHECKED : MF_UNCHECKED) == -1) {
+ return false;
+ }
+ return true;
+}
+
+bool WinMute::Init()
+{
+ hAppIcon_ = LoadIcon(hglobInstance, MAKEINTRESOURCE(IDI_APP));
+
+ if (!settings_.Init() ||
+ !LoadDefaults()) {
+ return false;
+ }
+
+ if (!RegisterWindowClass() ||
+ !InitWindow() ||
+ !InitTrayMenu()) {
+ return false;
+ }
+
+ if (!scrnSaverNoti_.Init()) {
+ return false;
+ }
+
+ if (muteOnScreensaver_) {
+ if (!scrnSaverNoti_.ActivateNotifications(hWnd_)) {
+ return false;
+ }
+ }
+
+ if (!WTSRegisterSessionNotification(hWnd_, NOTIFY_FOR_THIS_SESSION)) {
+ PrintWindowsError(_T("WTSRegisterSessionNotification"));
+ return false;
+ }
+
+ if (!InitAudio()) {
+ return false;
+ }
+
+ trayIcon_.Init(hWnd_, 0, hAppIcon_, _T("WinMute"), true);
+ return true;
+}
+
+bool WinMute::LoadDefaults()
+{
+ muteOnLock_ =
+ settings_.QueryValue(SettingsKey::MUTE_ON_LOCK, 1) != 0;
+ muteOnScreensaver_ =
+ settings_.QueryValue(SettingsKey::MUTE_ON_SCREENSAVER, 1) != 0;
+ restoreAudio_ =
+ settings_.QueryValue(SettingsKey::RESTORE_AUDIO, 1) != 0;
+ return true;
+}
+
+void WinMute::CheckOrUncheckMenu(UINT item, bool* setting)
+{
+ UINT state = GetMenuState(hTrayMenu_, item, MF_BYCOMMAND);
+ if (state & MF_CHECKED) {
+ *setting = false;
+ CheckMenuItem(hTrayMenu_, item, MF_UNCHECKED);
+ } else {
+ *setting = true;
+ CheckMenuItem(hTrayMenu_, item, MF_CHECKED);
+ }
+}
+
+LRESULT CALLBACK WinMute::WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
+ LPARAM lParam)
+{
+ static UINT uTaskbarRestart = 0;
+ switch (msg) {
+ case WM_CREATE: {
+ uTaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));
+ return TRUE;
+ }
+ case WM_COMMAND: {
+ switch (LOWORD(wParam)) {
+ case ID_TRAYMENU_INFO:
+ DialogBox(hglobInstance,
+ MAKEINTRESOURCE(IDD_ABOUT),
+ hWnd_,
+ AboutDlgProc);
+ break;
+ case ID_TRAYMENU_EXIT:
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ case ID_TRAYMENU_MUTEONLOCK:
+ CheckOrUncheckMenu(ID_TRAYMENU_MUTEONLOCK, &muteOnLock_);
+ settings_.SetValue(SettingsKey::MUTE_ON_LOCK, muteOnLock_);
+ break;
+ case ID_TRAYMENU_RESTOREAUDIO:
+ CheckOrUncheckMenu(ID_TRAYMENU_RESTOREAUDIO, &restoreAudio_);
+ settings_.SetValue(SettingsKey::RESTORE_AUDIO, restoreAudio_);
+ break;
+ case ID_TRAYMENU_MUTEONSCREENSAVER:
+ CheckOrUncheckMenu(ID_TRAYMENU_MUTEONSCREENSAVER, &muteOnScreensaver_);
+ settings_.SetValue(SettingsKey::MUTE_ON_SCREENSAVER, muteOnScreensaver_);
+ if (muteOnScreensaver_) {
+ scrnSaverNoti_.ActivateNotifications(hWnd_);
+ } else {
+ scrnSaverNoti_.ClearNotifications();
+ }
+ break;
+ case ID_TRAYMENU_MUTE: {
+ bool state = false;
+ CheckOrUncheckMenu(ID_TRAYMENU_MUTE, &state);
+ if (!state) {
+ audio_->UnMute();
+ } else {
+ audio_->Mute();
+ }
+ break;
+ } default:
+ __assume(0);
+ }
+ return 0;
+ }
+ case WM_TRAYICON: {
+ switch (lParam) {
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP: {
+ POINT p = {0};
+ GetCursorPos(&p);
+ SetForegroundWindow(hWnd);
+ TrackPopupMenuEx(GetSubMenu(hTrayMenu_, 0), TPM_NONOTIFY | TPM_TOPALIGN
+ | TPM_LEFTALIGN, p.x, p.y, hWnd_, nullptr);
+ PostMessage(hWnd, WM_NULL, 0, 0);
+ break;
+ }
+ default:
+ break;
+ }
+ return TRUE;
+ }
+ case WM_CLOSE: {
+ Close();
+ return 0;
+ }
+ case WM_WTSSESSION_CHANGE: {
+ static bool wasAlreadyMuted = false;
+ if (wParam == WTS_SESSION_LOCK) {
+ wasAlreadyMuted = audio_->IsMuted();
+ if (!wasAlreadyMuted && muteOnLock_) {
+ audio_->Mute();
+ }
+ } else if (wParam == WTS_SESSION_UNLOCK) {
+ if (!wasAlreadyMuted && muteOnLock_ && restoreAudio_) {
+ audio_->UnMute();
+ }
+ }
+ return 0;
+ }
+ case WM_SCRNSAVE_CHANGE: {
+ static bool wasAlreadyMuted = false;
+ if (wParam == SCRNSAVE_START) {
+ wasAlreadyMuted = audio_->IsMuted();
+ if (!wasAlreadyMuted && muteOnScreensaver_) {
+ audio_->Mute();
+ }
+ } else if (wParam == SCRNSAVE_STOP) {
+ if (!wasAlreadyMuted && muteOnScreensaver_ && restoreAudio_) {
+ audio_->UnMute();
+ }
+ }
+ return 0;
+ }
+ default:
+ if (msg == uTaskbarRestart) { // restore trayicon if explorer.exe crashes
+ trayIcon_.Hide();
+ trayIcon_.Show();
+ }
+ break;
+ }
+
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+void WinMute::Unload()
+{
+ scrnSaverNoti_.Unload();
+ settings_.Unload();
+}
+
+void WinMute::Close()
+{
+ Unload();
+ PostQuitMessage(0);
+}
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "StdAfx.h"
+
+class WinAudio;
+
+class WinMute {
+public:
+ WinMute();
+ ~WinMute();
+
+ bool Init();
+ void Close();
+
+ HWND GetWnd();
+
+ // for internal use
+ LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+private:
+ HWND hWnd_;
+ HMENU hTrayMenu_;
+ HICON hAppIcon_;
+ bool muteOnLock_,
+ muteOnScreensaver_,
+ restoreAudio_;
+
+ TrayIcon trayIcon_;
+ std::unique_ptr<WinAudio> audio_;
+ ScreensaverNotifier scrnSaverNoti_;
+ Settings settings_;
+
+ bool RegisterWindowClass();
+ bool InitWindow();
+ bool InitAudio();
+ bool InitTrayMenu();
+ bool LoadDefaults();
+
+ void Unload();
+
+ void CheckOrUncheckMenu(UINT item, bool* setting);
+
+
+ // Disable copying
+ WinMute(const WinMute&);
+ WinMute& operator=(const WinMute&);
+};
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.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="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{488617F0-5DD3-42B5-81ED-A1E9B3117551}</ProjectGuid>
+ <RootNamespace>WinMute</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)Bin\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)Bin\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Configuration) (x64)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)Bin\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)Bin\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Configuration) (x64)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName) (x64)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName) (x64)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(SolutionDir)\Bin\$(ProjectName).exe</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="AboutDlg.cpp" />
+ <ClCompile Include="MMNotificationClient.cpp" />
+ <ClCompile Include="ScreensaverNotifier.cpp" />
+ <ClCompile Include="Settings.cpp" />
+ <ClCompile Include="StdAfx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="TrayIcon.cpp" />
+ <ClCompile Include="Utility.cpp" />
+ <ClCompile Include="VistaAudio.cpp" />
+ <ClCompile Include="VistaAudioSessionEvents.cpp" />
+ <ClCompile Include="WinMain.cpp" />
+ <ClCompile Include="WinMute.cpp" />
+ <ClCompile Include="XPAudio.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="MMNotificationClient.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="ScreensaverNotifier.h" />
+ <ClInclude Include="Settings.h" />
+ <ClInclude Include="StdAfx.h" />
+ <ClInclude Include="TrayIcon.h" />
+ <ClInclude Include="VersionHelper.h" />
+ <ClInclude Include="VistaAudioSessionEvents.h" />
+ <ClInclude Include="WinAudio.h" />
+ <ClInclude Include="WinMute.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?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="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</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Audio">
+ <UniqueIdentifier>{065a6082-9732-43e4-ad7b-714757809908}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\UI">
+ <UniqueIdentifier>{19d0b819-b48e-4418-917c-f92abc4c2160}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Audio\Vista Notification">
+ <UniqueIdentifier>{4ea37611-be22-4541-bfcb-ca9d271b5166}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Helper">
+ <UniqueIdentifier>{aca601be-bf13-4396-89b2-8252b3fd2703}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Settings">
+ <UniqueIdentifier>{f9c118fc-0a72-4278-a710-841604aeb3e3}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="StdAfx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="WinMain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="WinMute.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="VistaAudio.cpp">
+ <Filter>Source Files\Audio</Filter>
+ </ClCompile>
+ <ClCompile Include="XPAudio.cpp">
+ <Filter>Source Files\Audio</Filter>
+ </ClCompile>
+ <ClCompile Include="TrayIcon.cpp">
+ <Filter>Source Files\UI</Filter>
+ </ClCompile>
+ <ClCompile Include="AboutDlg.cpp">
+ <Filter>Source Files\UI</Filter>
+ </ClCompile>
+ <ClCompile Include="VistaAudioSessionEvents.cpp">
+ <Filter>Source Files\Audio\Vista Notification</Filter>
+ </ClCompile>
+ <ClCompile Include="MMNotificationClient.cpp">
+ <Filter>Source Files\Audio\Vista Notification</Filter>
+ </ClCompile>
+ <ClCompile Include="ScreensaverNotifier.cpp">
+ <Filter>Source Files\Helper</Filter>
+ </ClCompile>
+ <ClCompile Include="Utility.cpp">
+ <Filter>Source Files\Helper</Filter>
+ </ClCompile>
+ <ClCompile Include="Settings.cpp">
+ <Filter>Source Files\Settings</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="resource.h">
+ <Filter>Source Files\UI</Filter>
+ </ClInclude>
+ <ClInclude Include="StdAfx.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="TrayIcon.h">
+ <Filter>Source Files\UI</Filter>
+ </ClInclude>
+ <ClInclude Include="WinAudio.h">
+ <Filter>Source Files\Audio</Filter>
+ </ClInclude>
+ <ClInclude Include="WinMute.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="VistaAudioSessionEvents.h">
+ <Filter>Source Files\Audio\Vista Notification</Filter>
+ </ClInclude>
+ <ClInclude Include="MMNotificationClient.h">
+ <Filter>Source Files\Audio\Vista Notification</Filter>
+ </ClInclude>
+ <ClInclude Include="ScreensaverNotifier.h">
+ <Filter>Source Files\Helper</Filter>
+ </ClInclude>
+ <ClInclude Include="VersionHelper.h">
+ <Filter>Source Files\Helper</Filter>
+ </ClInclude>
+ <ClInclude Include="Settings.h">
+ <Filter>Source Files\Settings</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
--- /dev/null
+/*
+ WinMute
+ Copyright (c) 2014 Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "StdAfx.h"
+#include <sstream>
+#include "WinAudio.h"
+
+static const TCHAR* MIXER_NOTIFY_WND_CLASS = _T("WinMuteMixerNotifyWnd");
+extern HINSTANCE hglobInstance;
+
+LRESULT CALLBACK MixerWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ XPAudio* xpa =
+ reinterpret_cast<XPAudio*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ switch (msg) {
+ case WM_NCCREATE: {
+ LPCREATESTRUCTW cs = reinterpret_cast<LPCREATESTRUCTW>(lParam);
+ SetWindowLongPtr(hWnd, GWLP_USERDATA,
+ reinterpret_cast<LONG>(cs->lpCreateParams));
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ return (xpa) ? xpa->WindowProc(hWnd, msg, wParam, lParam)
+ : DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+static void PrintMixerError(const tstring& funcName, MMRESULT err)
+{
+//#ifdef _DEBUG
+ std::basic_string<TCHAR> error = funcName + L" failed with: ";
+ switch (err) {
+ case MIXERR_INVALCONTROL:
+ error += _T("The control reference is invalid.");
+ break;
+ case MIXERR_INVALLINE:
+ error += _T("The audio line reference is invalid.");
+ break;
+ case MMSYSERR_BADDEVICEID:
+ error += _T("The hmxobj parameter specifies an invalid device")
+ _T(" identifier.");
+ break;
+ case MMSYSERR_INVALFLAG:
+ error += _T("One or more flags are invalid.");
+ break;
+ case MMSYSERR_INVALHANDLE:
+ error += _T("The hmxobj parameter specifies an invalid handle.");
+ break;
+ case MMSYSERR_INVALPARAM:
+ error += _T("One or more parameters are invalid.");
+ break;
+ case MMSYSERR_NODRIVER:
+ error += _T("No mixer device is available for the object specified")
+ _T(" by hmxobj.");
+ break;
+ default: {
+ error += _T("An unknown error: ");
+ std::wstringstream s;
+ s << err;
+ error += s.str();
+
+ break;
+ }
+ }
+ MessageBox(0, error.c_str(), 0, MB_ICONERROR);
+//#else
+// UNREFERENCED_PARAMETER(funcName);
+// UNREFERENCED_PARAMETER(err);
+//#endif
+}
+
+XPAudio::XPAudio() :
+ hNotifyWnd_(nullptr), currentlyMuted_(false), muteTime_(0)
+{
+}
+
+XPAudio::~XPAudio()
+{
+ std::for_each(mixers_.begin(), mixers_.end(), [](XPAudio::MixerDevice& md) {
+ mixerClose(md.hMixer);
+ });
+ mixers_.clear();
+ DestroyWindow(hNotifyWnd_);
+}
+
+/* -----------------------------------------------------------------------------
+ Init
+ -------------------------------------------------------------------------- */
+
+bool XPAudio::Init(HWND hParent)
+{
+ if (!InitNotifyWindow(hParent))
+ return false;
+
+ UINT numMixers = mixerGetNumDevs();
+ for (UINT i = 0; i < numMixers; ++i) {
+ MixerDevice md;
+ if (mixerOpen(&md.hMixer, i, reinterpret_cast<DWORD_PTR>(hNotifyWnd_),
+ 0, CALLBACK_WINDOW) == MMSYSERR_NOERROR) {
+ MIXERCAPS mixcaps;
+ mixerGetDevCaps(i, &mixcaps, sizeof(MIXERCAPS));
+ if (GetMuteControl(md)) {
+ mixers_.push_back(md);
+ } else {
+ mixerClose(md.hMixer);
+ }
+ }
+ }
+ return !mixers_.empty();
+}
+
+bool XPAudio::InitNotifyWindow(HWND hParent)
+{
+ WNDCLASS wc={0};
+ wc.hInstance = hglobInstance;
+ wc.lpfnWndProc = MixerWndProc;
+ wc.lpszClassName = MIXER_NOTIFY_WND_CLASS;
+
+ if (!RegisterClass(&wc)) {
+ PrintWindowsError(_T("RegisterClass"));
+ return false;
+ }
+ hNotifyWnd_ = CreateWindow(MIXER_NOTIFY_WND_CLASS, 0, 0, 0, 0, 0, 0,
+ hParent, 0, hglobInstance, this);
+ if (hNotifyWnd_ == nullptr) {
+ PrintWindowsError(_T("CreateWindow"));
+ return false;
+ }
+ return true;
+}
+
+void XPAudio::ShouldReInit()
+{
+}
+
+bool XPAudio::GetMuteControl(XPAudio::MixerDevice& md)
+{
+ MIXERLINE mxl = {0};
+ mxl.cbStruct = sizeof(MIXERLINE);
+ mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
+
+ MMRESULT mmrErr = mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(md.hMixer),
+ &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);
+ if (mmrErr != MMSYSERR_NOERROR) {
+ return false;
+ }
+
+ // At first: Try to optain the Mute-Control.
+ MIXERCONTROL mxCtrl = {0};
+ MIXERLINECONTROLS mxLineCtrls = {0};
+ mxLineCtrls.cbStruct = sizeof(MIXERLINECONTROLS);
+ mxLineCtrls.cControls = 1;
+ mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
+ mxLineCtrls.dwLineID = mxl.dwLineID;
+ mxLineCtrls.pamxctrl = &mxCtrl;
+ mxLineCtrls.cbmxctrl = sizeof(MIXERCONTROL);
+
+ mmrErr = mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(md.hMixer),
+ &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
+
+ if (mmrErr != MMSYSERR_NOERROR) {
+ // If this doesn't work, get the volume slider
+ mxLineCtrls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
+ mmrErr = mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(md.hMixer),
+ &mxLineCtrls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
+ if (mmrErr != MMSYSERR_NOERROR) {
+ return false;
+ }
+ md.volCtrlID = mxCtrl.dwControlID;
+ md.useMute = false;
+ } else {
+ md.muteCtrlID = mxCtrl.dwControlID;
+ md.useMute = true;
+ }
+
+ return true;
+}
+
+/* -----------------------------------------------------------------------------
+ Window Proc
+ -------------------------------------------------------------------------- */
+
+LRESULT CALLBACK XPAudio::WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
+ LPARAM lParam)
+{
+ static bool muteLock = false;
+ if (msg == MM_MIXM_CONTROL_CHANGE) {
+ if (!muteLock && currentlyMuted_ && time(0) - muteTime_ > 1) {
+ muteLock = true;
+ for (auto md = mixers_.begin(); md != mixers_.end(); ++md) {
+ if (reinterpret_cast<HMIXER>(wParam) == md->hMixer) {
+ DWORD notifyID = static_cast<DWORD>(lParam);
+ if (notifyID == md->muteCtrlID || notifyID == md->volCtrlID) {
+ MuteDevice(*md, false);
+ }
+ }
+ }
+ SetTimer(hWnd, 5, 200, NULL);
+ }
+ return 0;
+ } else if (msg == WM_TIMER) {
+ if (wParam == 5 && muteLock) {
+ KillTimer(hWnd, 5);
+ muteLock = false;
+ }
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+
+/* -----------------------------------------------------------------------------
+ Mute Logic
+ -------------------------------------------------------------------------- */
+
+bool XPAudio::IsMuted()
+{
+ return currentlyMuted_;
+}
+
+DWORD XPAudio::GetOldControlValue(const MixerDevice& md)
+{
+ MMRESULT err;
+ MIXERCONTROLDETAILS mxcd = {0};
+ mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
+ mxcd.cChannels = 1;
+ DWORD oldVal;
+ if (md.useMute) { // Mute control
+ MIXERCONTROLDETAILS_BOOLEAN mxCtrlDetMuted = { 0 };
+ mxcd.dwControlID = md.muteCtrlID;
+ mxcd.paDetails = &mxCtrlDetMuted;
+ mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
+
+ err = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(md.hMixer),
+ &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
+ oldVal = mxCtrlDetMuted.fValue;
+ } else { // Volume Slider control
+ MIXERCONTROLDETAILS_UNSIGNED mxCtrlVolume = { 0 };
+
+ mxcd.dwControlID = md.volCtrlID;
+ mxcd.paDetails = &mxCtrlVolume;
+ mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
+
+ err = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(md.hMixer),
+ &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
+ oldVal = mxCtrlVolume.dwValue;
+ }
+
+ if (err != MMSYSERR_NOERROR) {
+ PrintMixerError(L"mixerGetControlDetails", err);
+ return 0;
+ }
+
+ return oldVal;
+}
+
+void XPAudio::SetDeviceValue(XPAudio::MixerDevice& md, DWORD val)
+{
+ MIXERCONTROLDETAILS mxcd = {0};
+ mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
+ mxcd.cChannels = 1;
+
+ MIXERCONTROLDETAILS_UNSIGNED mxCtrlDetVolume = { val };
+ MIXERCONTROLDETAILS_BOOLEAN mxCtrlDetMuted = { val };
+
+ if (md.useMute) {
+ mxcd.dwControlID = md.muteCtrlID;
+ mxcd.paDetails = &mxCtrlDetMuted;
+ mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
+ } else { // Volume Slider
+ mxcd.dwControlID = md.volCtrlID;
+ mxcd.paDetails = &mxCtrlDetVolume;
+ mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
+ }
+
+ MMRESULT mmrErr = mixerSetControlDetails(
+ reinterpret_cast<HMIXEROBJ>(md.hMixer), &mxcd,
+ MIXER_OBJECTF_MIXER | MIXER_SETCONTROLDETAILSF_VALUE);
+
+ if (mmrErr != MMSYSERR_NOERROR) {
+ PrintMixerError(_T("mixerSetControlDetails"), mmrErr);
+ }
+}
+
+void XPAudio::MuteDevice(XPAudio::MixerDevice& md, bool saveOldValue)
+{
+ if (saveOldValue) {
+ md.oldValue = GetOldControlValue(md);
+ }
+ SetDeviceValue(md, md.useMute ? 1 : 0);
+}
+
+void XPAudio::Mute()
+{
+ for (auto md = mixers_.begin(); md != mixers_.end(); ++md) {
+ MuteDevice(*md, true);
+ }
+ currentlyMuted_ = true;
+ muteTime_ = time(0);
+}
+
+void XPAudio::UnMute()
+{
+ muteTime_ = 0;
+ currentlyMuted_ = false; // Order important (s. WindowProc notification)
+ for (auto md = mixers_.begin(); md != mixers_.end(); ++md) {
+ SetDeviceValue(*md, md->oldValue);
+ }
+}
--- /dev/null
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_TRAYMENU MENU
+BEGIN
+ POPUP "TrayMenu"
+ BEGIN
+ MENUITEM "Info", ID_TRAYMENU_INFO
+ MENUITEM SEPARATOR
+ MENUITEM "Mute on ...", ID_TRAYMENU_MUTEON, INACTIVE
+ MENUITEM "... Workstation lock", ID_TRAYMENU_MUTEONLOCK, CHECKED
+ MENUITEM "... Screensaver start", ID_TRAYMENU_MUTEONSCREENSAVER, CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "Restore Audio", ID_TRAYMENU_RESTOREAUDIO, CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "Mute now", ID_TRAYMENU_MUTE
+ MENUITEM SEPARATOR
+ MENUITEM "Exit", ID_TRAYMENU_EXIT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUT DIALOGEX 0, 0, 251, 52
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "About WinMute"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,194,7,50,14
+ LTEXT "WinMute v1.4",IDC_STATIC,43,9,67,11
+ CONTROL "<a href=""http://lx-s.de"">lx-systems - lx-s.de</a>",IDC_LINK_HOMEPAGE,
+ "SysLink",WS_TABSTOP,43,31,69,13
+ LTEXT "Copyright © 2014 Alexander Steinhöfer",IDC_STATIC,43,20,148,12
+ ICON IDI_APP,IDC_STATIC,13,7,20,20
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ABOUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 244
+ VERTGUIDE, 43
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 45
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,4,0,0
+ PRODUCTVERSION 1,4,0,0
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "lx-s"
+ VALUE "FileDescription", "Automatic sound muter."
+ VALUE "FileVersion", "1.4.0.0"
+ VALUE "InternalName", "WinMute"
+ VALUE "LegalCopyright", "Copyright (C) 2013 Alexander Steinhöfer"
+ VALUE "OriginalFilename", "WinMute.exe"
+ VALUE "ProductName", "WinMute"
+ VALUE "ProductVersion", "1.4.0.0"
+ END
+ BLOCK "040704b0"
+ BEGIN
+ VALUE "CompanyName", "lx-s"
+ VALUE "FileDescription", "Automatisches Stummschalten bei PC Sperre."
+ VALUE "FileVersion", "1.4.0.0"
+ VALUE "InternalName", "WinMute"
+ VALUE "LegalCopyright", "Copyright (C) 2013 Alexander Steinhöfer"
+ VALUE "OriginalFilename", "WinMute.exe"
+ VALUE "ProductName", "WinMute"
+ VALUE "ProductVersion", "1.4.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200, 0x407, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP ICON "app.ico"
+#endif // German (Germany) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by res.rc
+//
+#define IDR_TRAYMENU 101
+#define IDD_ABOUT 102
+#define IDI_APP 106
+#define IDC_LINK_HOMEPAGE 1001
+#define ID_TRAYMENU_INFO 40001
+#define ID_TRAYMENU_EXIT 40002
+#define ID_TRAYMENU_MUTEONLOCK 40003
+#define ID_TRAYMENU_MUTEONSCREENSAVER 40004
+#define ID_TRAYMENU_ 40005
+#define ID_TRAYMENU_MUTEONMONITOROFF 40006
+#define ID_TRAYMENU_MUTE 40007
+#define ID_TRAYMENU_MUTEONSCREENSAVER40008 40008
+#define ID_TRAYMENU_RESTOREAUDIO 40009
+#define ID_TRAYMENU_40010 40010
+#define ID_TRAYMENU_40011 40011
+#define ID_TRAYMENU_MUTEON 40012
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40013
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif