From 21176e7f7ba7c1c04075f7248c1db535ebe0bef1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alexander=20Steinh=C3=B6fer?= Date: Thu, 7 Apr 2022 16:34:47 +0200 Subject: [PATCH] Fixed Display Suspend Detection. Added Notifications. --- WinMute/MuteControl.cpp | 31 +++++++++++++++++++++++++++---- WinMute/MuteControl.h | 13 +++++++++++-- WinMute/TrayIcon.cpp | 22 ++++++++-------------- WinMute/TrayIcon.h | 10 +++++----- WinMute/WinMute.cpp | 38 ++++++++++++++++++++++++++++---------- WinMute/WinMute.h | 11 +---------- WinMute/WinMute.rc | 20 +++++++++++--------- WinMute/common.h | 2 ++ WinMute/resource.h | 4 +++- 9 files changed, 96 insertions(+), 55 deletions(-) diff --git a/WinMute/MuteControl.cpp b/WinMute/MuteControl.cpp index af2b915..6c46fda 100644 --- a/WinMute/MuteControl.cpp +++ b/WinMute/MuteControl.cpp @@ -48,6 +48,7 @@ enum MuteType { }; MuteControl::MuteControl() + : trayIcon_(nullptr), notificationsEnabled_(false), displayWasOffOnce_(false) { MuteConfig initMuteConf; initMuteConf.active = false; @@ -61,12 +62,13 @@ MuteControl::~MuteControl() { } -bool MuteControl::Init(HWND hParent) +bool MuteControl::Init(HWND hParent, const TrayIcon *trayIcon) { winAudio_ = std::make_unique(); if (!winAudio_->Init(hParent)) { return false; } + trayIcon_ = trayIcon; return true; } @@ -92,6 +94,18 @@ void MuteControl::SaveMuteStatus() } } +void MuteControl::ShowNotification(const tstring& title, const tstring& text) +{ + if (notificationsEnabled_ && trayIcon_ != nullptr) { + trayIcon_->ShowPopup(title, text); + } +} + +void MuteControl::SetNotifications(bool enable) +{ + notificationsEnabled_ = enable; +} + void MuteControl::RestoreVolume() { WMLog& log = WMLog::GetInstance(); @@ -109,6 +123,9 @@ void MuteControl::RestoreVolume() } if (restore) { log.Write(_T("Restoring previous mute state")); + ShowNotification( + _T("Volume restored"), + _T("All endpoints have been restored to their previous configuration")); winAudio_->RestoreMuteStatus(); } } @@ -200,6 +217,9 @@ void MuteControl::NotifyRestoreCondition(int type, bool active) muteConfig_[type].active = active; if (muteConfig_[type].shouldMute) { WMLog::GetInstance().Write(_T("Muting workstation")); + ShowNotification( + _T("Muting workstation"), + _T("All endpoints have been muted")); winAudio_->SetMute(true); } } else { @@ -231,9 +251,12 @@ void MuteControl::NotifyRemoteSession(bool active) void MuteControl::NotifyDisplayStandby(bool active) { - WMLog::GetInstance().Write(_T("Mute Event: Display Standby {}"), - active ? _T("start") : _T("stop")); - NotifyRestoreCondition(MuteTypeDisplayStandby, active); + if (displayWasOffOnce_ || active) { + WMLog::GetInstance().Write(_T("Mute Event: Display Standby {}"), + active ? _T("start") : _T("stop")); + NotifyRestoreCondition(MuteTypeDisplayStandby, active); + displayWasOffOnce_ = true; + } } void MuteControl::NotifyLogout() diff --git a/WinMute/MuteControl.h b/WinMute/MuteControl.h index 4e62a1d..1d1f573 100644 --- a/WinMute/MuteControl.h +++ b/WinMute/MuteControl.h @@ -42,7 +42,10 @@ public: MuteControl(const MuteControl&) = delete; MuteControl& operator=(const MuteControl&) = delete; - bool Init(HWND hParent); + bool Init(HWND hParent, const TrayIcon* trayIcon); + + + void SetNotifications(bool enable); void SetMute(bool mute); @@ -85,10 +88,16 @@ private: }; std::vector muteConfig_; bool restoreVolume_; + bool notificationsEnabled_; std::unique_ptr winAudio_; + bool displayWasOffOnce_; // Since a power message is sent right after registering + // We skip the first "was on" message + + const TrayIcon* trayIcon_; + void NotifyRestoreCondition(int type, bool active); void SaveMuteStatus(); void RestoreVolume(); - + void ShowNotification(const tstring& title, const tstring& text); }; diff --git a/WinMute/TrayIcon.cpp b/WinMute/TrayIcon.cpp index dfbaa78..443ea60 100644 --- a/WinMute/TrayIcon.cpp +++ b/WinMute/TrayIcon.cpp @@ -39,14 +39,14 @@ TrayIcon::TrayIcon() : } TrayIcon::TrayIcon(HWND hWnd, UINT trayID, HICON hIcon, - const std::wstring& tooltip, bool show) : + const tstring& 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) + const tstring& tooltip, bool show) { if (!hIcon) { hIcon_ = LoadIcon(0, IDI_APPLICATION); @@ -115,7 +115,7 @@ void TrayIcon::ChangeIcon(HICON hNewIcon) return; } -void TrayIcon::ChangeText(const std::wstring& tooltip) +void TrayIcon::ChangeText(const tstring& tooltip) { tooltip_ = tooltip; @@ -123,9 +123,7 @@ void TrayIcon::ChangeText(const std::wstring& tooltip) ChangeText(); } -void TrayIcon::ShowPopup( - const std::wstring& title, - const std::wstring& text) +void TrayIcon::ShowPopup(const tstring& title, const tstring& text) const { NOTIFYICONDATA tnid; tnid.cbSize = sizeof(NOTIFYICONDATA); @@ -135,8 +133,8 @@ void TrayIcon::ShowPopup( tnid.dwInfoFlags = NIIF_INFO | NIIF_NOSOUND | NIIF_LARGE_ICON | NIIF_RESPECT_QUIET_TIME; tnid.uTimeout = 10 * 1000; - wcscpy_s(tnid.szInfoTitle, sizeof(tnid.szInfoTitle) / sizeof(TCHAR), title.c_str()); - wcscpy_s(tnid.szInfo, sizeof(tnid.szInfo) / sizeof(TCHAR), text.c_str()); + StringCchCopy(tnid.szInfoTitle, ARRAY_SIZE(tnid.szInfoTitle), title.c_str()); + StringCchCopy(tnid.szInfo, ARRAY_SIZE(tnid.szInfo), text.c_str()); Shell_NotifyIcon(NIM_MODIFY, &tnid); } @@ -160,9 +158,7 @@ bool TrayIcon::AddNotifyIcon() tnid.hIcon = hIcon_; tnid.uCallbackMessage = WM_TRAYICON; - if (SUCCEEDED(StringCchCopy(tnid.szTip, - sizeof(tnid.szTip) / sizeof(TCHAR), - tooltip_.c_str()))) { + if (SUCCEEDED(StringCchCopy(tnid.szTip, ARRAY_SIZE(tnid.szTip), tooltip_.c_str()))) { return Shell_NotifyIcon(NIM_ADD, &tnid) != 0; } return false; @@ -188,9 +184,7 @@ bool TrayIcon::ChangeText() tnid.uID = trayID_; tnid.uFlags = NIF_TIP; - if (SUCCEEDED(StringCchCopy(tnid.szTip, - sizeof(tnid.szTip) / sizeof(TCHAR), - tooltip_.c_str()))) { + if (SUCCEEDED(StringCchCopy(tnid.szTip, ARRAY_SIZE(tnid.szTip), tooltip_.c_str()))) { return Shell_NotifyIcon(NIM_MODIFY, &tnid) != 0; } return false; diff --git a/WinMute/TrayIcon.h b/WinMute/TrayIcon.h index f8db69c..7304306 100644 --- a/WinMute/TrayIcon.h +++ b/WinMute/TrayIcon.h @@ -40,17 +40,17 @@ POSSIBILITY OF SUCH DAMAGE. class TrayIcon { public: TrayIcon(); - TrayIcon(HWND hWnd, UINT trayID, HICON hIcon, const std::wstring& tooltip, + TrayIcon(HWND hWnd, UINT trayID, HICON hIcon, const tstring& tooltip, bool show); ~TrayIcon(); - void Init(HWND hWnd, UINT trayID, HICON hIcon, const std::wstring& tooltip, + void Init(HWND hWnd, UINT trayID, HICON hIcon, const tstring& tooltip, bool show); void Hide(); void Show(); bool IsShown() const { return iconVisible_; } void ChangeIcon(HICON hNewIcon); - void ChangeText(const std::wstring& tooltip); - void ShowPopup(const std::wstring& title, const std::wstring& text); + void ChangeText(const tstring& tooltip); + void ShowPopup(const tstring& title, const tstring& text) const; private: void DestroyTrayIcon(); @@ -62,5 +62,5 @@ private: UINT trayID_; HICON hIcon_; HWND hWnd_; - std::wstring tooltip_; + tstring tooltip_; }; diff --git a/WinMute/WinMute.cpp b/WinMute/WinMute.cpp index 636a4e1..81a4882 100644 --- a/WinMute/WinMute.cpp +++ b/WinMute/WinMute.cpp @@ -156,10 +156,9 @@ bool WinMute::InitAudio() return false; } - if (!muteCtrl_.Init(hWnd_)) { + if (!muteCtrl_.Init(hWnd_, &trayIcon_)) { return false; } - return true; } @@ -192,8 +191,11 @@ bool WinMute::Init() hAppIcon_ = LoadIcon(hglobInstance, MAKEINTRESOURCE(IDI_APP)); - if (!settings_.Init() || - !LoadDefaults()) { + if (!InitAudio()) { + return false; + } + + if (!settings_.Init() || !LoadDefaults()) { return false; } @@ -210,10 +212,6 @@ bool WinMute::Init() return false; } - if (!InitAudio()) { - return false; - } - if (!scrnSaverNoti_.Init()) { return false; } @@ -229,6 +227,11 @@ bool WinMute::Init() return false; } + if (!RegisterPowerSettingNotification(hWnd_, &GUID_CONSOLE_DISPLAY_STATE, 0)) { + PrintWindowsError(_T("RegisterPowerSettingNotification")); + return false; + } + bool isDarkMode = true; IsDarkMode(isDarkMode); hTrayIcon_ = LoadIcon( @@ -258,6 +261,10 @@ bool WinMute::LoadDefaults() muteCtrl_.SetMuteOnSuspend(!!settings_.QueryValue(SettingsKey::MUTE_ON_SUSPEND, 0)); muteCtrl_.SetMuteOnShutdown(!!settings_.QueryValue(SettingsKey::MUTE_ON_SHUTDOWN, 0)); + muteCtrl_.SetNotifications(settings_.QueryValue(SettingsKey::NOTIFICATIONS_ENABLED, 0) != 0); + + muteConfig_.showNotifications = + settings_.QueryValue(SettingsKey::NOTIFICATIONS_ENABLED, 0) != 0; muteConfig_.quietHours.enabled = settings_.QueryValue(SettingsKey::QUIETHOURS_ENABLE, 0) != 0; muteConfig_.quietHours.forceUnmute = @@ -308,14 +315,18 @@ LRESULT CALLBACK WinMute::WindowProc( case ID_TRAYMENU_EXIT: SendMessage(hWnd, WM_CLOSE, 0, 0); break; - case ID_TRAYMENU_SETTINGS: + case ID_TRAYMENU_SETTINGS: { DialogBoxParam( hglobInstance, MAKEINTRESOURCE(IDD_SETTINGS), hWnd_, SettingsDlgProc, reinterpret_cast(&settings_)); + bool notifications = settings_.QueryValue(SettingsKey::NOTIFICATIONS_ENABLED, 0) != 0; + muteConfig_.showNotifications = notifications; + muteCtrl_.SetNotifications(notifications); break; + } case ID_TRAYMENU_MUTE: { bool state = false; ToggleMenuCheck(ID_TRAYMENU_MUTE, &state); @@ -348,6 +359,13 @@ LRESULT CALLBACK WinMute::WindowProc( } break; } + case ID_TRAYMENU_SCREENSUSPEND: { + bool checked = false; + ToggleMenuCheck(ID_TRAYMENU_SCREENSUSPEND, &checked); + muteCtrl_.SetMuteOnDisplayStandby(checked); + settings_.SetValue(SettingsKey::MUTE_ON_DISPLAYSTANDBY, checked); + break; + } case ID_TRAYMENU_MUTEONSHUTDOWN: { bool checked = false; ToggleMenuCheck(ID_TRAYMENU_MUTEONSHUTDOWN, &checked); @@ -420,7 +438,7 @@ LRESULT CALLBACK WinMute::WindowProc( } } } - break; + return TRUE; case WM_QUERYENDSESSION: if (lParam == 0) { // Shutdown muteCtrl_.NotifyShutdown(); diff --git a/WinMute/WinMute.h b/WinMute/WinMute.h index 0db8eef..03f85f9 100644 --- a/WinMute/WinMute.h +++ b/WinMute/WinMute.h @@ -61,16 +61,7 @@ private: struct MuteConfig { MuteConfig(); - /*struct { - bool onLock; - bool onScreensaver; - } withRestore; - bool restoreAudio; - struct { - bool onLogoff; - bool onShutdown; - bool onSuspend; - } noRestore;*/ + bool showNotifications; struct { bool enabled; bool forceUnmute; diff --git a/WinMute/WinMute.rc b/WinMute/WinMute.rc index df11388..0831b5c 100644 --- a/WinMute/WinMute.rc +++ b/WinMute/WinMute.rc @@ -76,9 +76,10 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "Start WinMute on system startup",IDC_RUNONSTARTUP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,15,132,26 - CONTROL "Enable Logging",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,61,101,21 - CONTROL "Show notifications",IDC_SHOWNOTIFICATIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,39,86,21 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,15,187,26 + CONTROL "Enable Logging",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,61,187,21 + CONTROL "Show mute event notifications",IDC_SHOWNOTIFICATIONS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,39,187,21 PUSHBUTTON "Open Log File...",IDC_OPENLOG,22,82,58,15 END @@ -244,6 +245,7 @@ BEGIN MENUITEM "Mute when...", 40003, INACTIVE MENUITEM "... Workstation is locked", ID_TRAYMENU_MUTEONLOCK, CHECKED MENUITEM "... Screensaver starts", ID_TRAYMENU_MUTEONSCREENSAVER, CHECKED + MENUITEM "... Screen turns off", ID_TRAYMENU_SCREENSUSPEND, CHECKED MENUITEM SEPARATOR MENUITEM "Restore previous volume afterwards", ID_TRAYMENU_RESTOREAUDIO, CHECKED MENUITEM SEPARATOR @@ -267,8 +269,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,0,0 - PRODUCTVERSION 1,7,0,0 + FILEVERSION 1,9,9,9 + PRODUCTVERSION 1,9,9,9 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -285,23 +287,23 @@ BEGIN BEGIN VALUE "CompanyName", "LX-Systems" VALUE "FileDescription", "WinMute" - VALUE "FileVersion", "1.7.0.0" + VALUE "FileVersion", "1.9.9.9" VALUE "InternalName", "WinMute.exe" VALUE "LegalCopyright", "Copyright (C) 2022, Alexander Steinhöfer" VALUE "OriginalFilename", "WinMute.exe" VALUE "ProductName", "WinMute" - VALUE "ProductVersion", "1.7.0.0" + VALUE "ProductVersion", "1.9.9.9" END BLOCK "040704b0" BEGIN VALUE "CompanyName", "LX-Systems" VALUE "FileDescription", "WinMute" - VALUE "FileVersion", "1.7.0.0" + VALUE "FileVersion", "1.9.9.9" VALUE "InternalName", "WinMute.exe" VALUE "LegalCopyright", "Copyright (C) 2022, Alexander Steinhöfer" VALUE "OriginalFilename", "WinMute.exe" VALUE "ProductName", "WinMute" - VALUE "ProductVersion", "1.7.0.0" + VALUE "ProductVersion", "1.9.9.9" END END BLOCK "VarFileInfo" diff --git a/WinMute/common.h b/WinMute/common.h index 7b52dcc..0ab3349 100644 --- a/WinMute/common.h +++ b/WinMute/common.h @@ -103,3 +103,5 @@ inline void SafeRelease(Interface * *ppInterfaceToRelease) (*ppInterfaceToRelease) = nullptr; } } + +#define ARRAY_SIZE(arr) ((sizeof(arr)) / (sizeof(arr[0]))) diff --git a/WinMute/resource.h b/WinMute/resource.h index 2473a9c..8e77249 100644 --- a/WinMute/resource.h +++ b/WinMute/resource.h @@ -61,13 +61,15 @@ #define ID_TRAYMENU_MUTE 40023 #define ID_TRAYMENU_MUTEONLOCK 40024 #define ID_TRAYMENU_SETTINGS 40025 +#define ID_TRAYMENU_SCREENTURNSOFF 40026 +#define ID_TRAYMENU_SCREENSUSPEND 40027 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 123 -#define _APS_NEXT_COMMAND_VALUE 40026 +#define _APS_NEXT_COMMAND_VALUE 40028 #define _APS_NEXT_CONTROL_VALUE 1021 #define _APS_NEXT_SYMED_VALUE 101 #endif -- 2.43.0