};
MuteControl::MuteControl()
+ : trayIcon_(nullptr), notificationsEnabled_(false), displayWasOffOnce_(false)
{
MuteConfig initMuteConf;
initMuteConf.active = false;
{
}
-bool MuteControl::Init(HWND hParent)
+bool MuteControl::Init(HWND hParent, const TrayIcon *trayIcon)
{
winAudio_ = std::make_unique<VistaAudio>();
if (!winAudio_->Init(hParent)) {
return false;
}
+ trayIcon_ = trayIcon;
return true;
}
}
}
+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();
}
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();
}
}
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 {
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()
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);
};
std::vector<MuteConfig> muteConfig_;
bool restoreVolume_;
+ bool notificationsEnabled_;
std::unique_ptr<WinAudio> 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);
};
}
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);
return;
}
-void TrayIcon::ChangeText(const std::wstring& tooltip)
+void TrayIcon::ChangeText(const tstring& tooltip)
{
tooltip_ = 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);
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);
}
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;
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;
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();
UINT trayID_;
HICON hIcon_;
HWND hWnd_;
- std::wstring tooltip_;
+ tstring tooltip_;
};
return false;
}
- if (!muteCtrl_.Init(hWnd_)) {
+ if (!muteCtrl_.Init(hWnd_, &trayIcon_)) {
return false;
}
-
return true;
}
hAppIcon_ = LoadIcon(hglobInstance, MAKEINTRESOURCE(IDI_APP));
- if (!settings_.Init() ||
- !LoadDefaults()) {
+ if (!InitAudio()) {
+ return false;
+ }
+
+ if (!settings_.Init() || !LoadDefaults()) {
return false;
}
return false;
}
- if (!InitAudio()) {
- return false;
- }
-
if (!scrnSaverNoti_.Init()) {
return false;
}
return false;
}
+ if (!RegisterPowerSettingNotification(hWnd_, &GUID_CONSOLE_DISPLAY_STATE, 0)) {
+ PrintWindowsError(_T("RegisterPowerSettingNotification"));
+ return false;
+ }
+
bool isDarkMode = true;
IsDarkMode(isDarkMode);
hTrayIcon_ = LoadIcon(
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 =
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<LPARAM>(&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);
}
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);
}
}
}
- break;
+ return TRUE;
case WM_QUERYENDSESSION:
if (lParam == 0) { // Shutdown
muteCtrl_.NotifyShutdown();
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;
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
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
//
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
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"
(*ppInterfaceToRelease) = nullptr;
}
}
+
+#define ARRAY_SIZE(arr) ((sizeof(arr)) / (sizeof(arr[0])))
#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