]> repos.lx-s.de Git - winmute.git/commitdiff
Fixed dialog tabs. Renamed log functions. New updater format to allow beta updates
authorlx-s <lx-s@users.noreply.github.com>
Tue, 19 Dec 2023 13:53:22 +0000 (14:53 +0100)
committerlx-s <lx-s@users.noreply.github.com>
Tue, 19 Dec 2023 13:53:22 +0000 (14:53 +0100)
28 files changed:
CURRENT_VERSION
Translations/lang-en.json
WinMute/AboutDlg.cpp
WinMute/BluetoothDetector.cpp
WinMute/MMNotificationClient.cpp
WinMute/MuteControl.cpp
WinMute/QuietHoursTimer.cpp
WinMute/SettingsDlg.cpp
WinMute/Settings_BluetoothDlg.cpp
WinMute/Settings_GeneralDlg.cpp
WinMute/Settings_ManageEndpointsDlg.cpp
WinMute/Settings_MuteDlg.cpp
WinMute/Settings_WifiDlg.cpp
WinMute/UpdateChecker.cpp
WinMute/UpdateChecker.h
WinMute/Utility.cpp
WinMute/VistaAudio.cpp
WinMute/WMLog.cpp
WinMute/WMLog.h
WinMute/WMSettings.cpp
WinMute/WMSettings.h
WinMute/WMi18n.cpp
WinMute/WifiDetector.cpp
WinMute/WinMain.cpp
WinMute/WinMute.cpp
WinMute/WinMute.rc
WinMute/common.h
WinMute/resource.h

index 87199af79c39c55e4cea1f241bbc0a06fd1b7a57..55d58104725ed9d4cdfdd69d07d8b1fddf32c62f 100644 (file)
@@ -1,4 +1,11 @@
 {
-   "version": "2.4.1.0",
-   "versionPage": "https://github.com/lx-s/WinMute/releases/"
+   "version": 1,
+   "stable": {
+      "version": "2.4.1.0",
+      "downloadUrl": "https://github.com/lx-s/WinMute/releases/"
+   },
+   "beta": {
+      "version": "2.9.0.0",
+      "downloadUrl": "https://github.com/lx-s/WinMute/releases/"
+   }
 }
index 1f7638b813a279ce8e316e67e1f9e00adead5223..bf691223bbd40ec786713c45c1072008babba5f4 100644 (file)
@@ -14,6 +14,8 @@
   "general.error.audio-service-shutdown.text": "WinMute is not able to recover from that condition.\nPlease try to restart the program.",
   "popup.update-available.title": "WinMute {} is available!",
   "popup.update-available.text": "Your current version is {}.\nClick on this message to open the download page.",
+  "popup.update-available-beta.title": "WinMute Beta {} is available!",
+  "popup.update-available-beta.text": "Your current version is {}.\nClick on this message to open the beta-download page.",
   "popup.error.update-check-failed.title": "Update check failed.",
   "pupup.error.update-check-failed.text": "Unable to check for a new version.\nPlease check/enable logging for further details.",
   "popup.remote-session-detected.title": "Remote Session detected",
@@ -67,7 +69,8 @@
   "settings.bluetooth.add-edit.edit-title": "Edit Bluetooth device",
   "settings.bluetooth.add-edit.device-name-label": "Bluetooth device name:",
   "settings.general.run-on-startup": "Run WinMute when this user logs on",
-  "settings.general.check-for-updates-on-start": "Check for updates on startup",
+  "settings.general.check-for-updates-on-start": "Check for new updates on startup",
+  "settings.general.check-for-beta-updates-on-start": "Also check for new beta versions",
   "settings.general.enable-logging": "Enable logging",
   "settings.general.btn-open-log-file": "Open log file...",
   "settings.general.select-language-label": "Language",
index bc2bb7702745ac779b63331dab233cb9355cef5b..70ca16603cef34e46120091aa7646dd13a252f7a 100644 (file)
@@ -123,7 +123,7 @@ static void ResizeTabs(HWND hTabCtrl, std::span<HWND> tabs)
 
    HDWP hdwp = BeginDeferWindowPos(static_cast<int>(tabs.size()));
    if (hdwp == nullptr) {
-      PrintWindowsError(L"BeginDeferWindowPos", GetLastError());
+      ShowWindowsError(L"BeginDeferWindowPos", GetLastError());
    } else {
       for (auto hTab : tabs) {
          HDWP newHdwp = DeferWindowPos(
@@ -136,7 +136,7 @@ static void ResizeTabs(HWND hTabCtrl, std::span<HWND> tabs)
             tabCtrlRect.bottom - tabCtrlRect.top,
             0);
          if (newHdwp == nullptr) {
-            PrintWindowsError(L"DeferWindowPos", GetLastError());
+            ShowWindowsError(L"DeferWindowPos", GetLastError());
             break;
          } else {
             hdwp = newHdwp;
index 580e47c954ce03c092f89cee602831d0671c84c2..914058469d3710977415e0329e6c09d312162bea 100644 (file)
@@ -65,7 +65,7 @@ bool BluetoothDetector::LoadRadioNotifications()
    const BLUETOOTH_FIND_RADIO_PARAMS bfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
    HBLUETOOTH_RADIO_FIND hRadiosFind = BluetoothFindFirstRadio(&bfrp, &btHandle);
    if (hRadiosFind == nullptr) {
-      log.WriteWindowsError(L"BluetoothFindFirstRadio", GetLastError());
+      log.LogWinError(L"BluetoothFindFirstRadio", GetLastError());
       return false;
    }
 
@@ -83,14 +83,14 @@ bool BluetoothDetector::LoadRadioNotifications()
       CloseHandle(btHandle);
 
       if (devNotify == nullptr) {
-         log.WriteWindowsError(L"RegisterDeviceNotification", GetLastError());
+         log.LogWinError(L"RegisterDeviceNotification", GetLastError());
       } else {
          notificationHandles_.push_back(devNotify);
       }
    } while (BluetoothFindNextRadio(hRadiosFind, &btHandle));
    const DWORD dwLastError = GetLastError();
    if (dwLastError != ERROR_NO_MORE_ITEMS) {
-      log.WriteWindowsError(L"BluetoothFindNextRadio", GetLastError());
+      log.LogWinError(L"BluetoothFindNextRadio", GetLastError());
       UnloadRadioNotifications();
    } else {
       success = true;
@@ -158,15 +158,15 @@ BluetoothDetector::BluetoothStatus BluetoothDetector::GetBluetoothStatus(
    if (useDeviceList_) {
       auto pos = std::find(begin(deviceNames_), end(deviceNames_), inRangeInfo->deviceInfo.name);
       if (pos == end(deviceNames_)) {
-         log.Write(L"Bluetooth device \"%S\" not in list.", inRangeInfo->deviceInfo.name);
+         log.LogInfo(L"Bluetooth device \"%S\" not in list.", inRangeInfo->deviceInfo.name);
          return BluetoothStatus::Unknown;
       }
    }
    if ((inRangeInfo->deviceInfo.flags & BDIF_CONNECTED) && !(inRangeInfo->previousDeviceFlags & BDIF_CONNECTED)) {
-      log.Write(L"Bluetooth Audio device \"%S\" connected.", inRangeInfo->deviceInfo.name);
+      log.LogInfo(L"Bluetooth Audio device \"%S\" connected.", inRangeInfo->deviceInfo.name);
       return BluetoothStatus::Connected;
    } else if (!(inRangeInfo->deviceInfo.flags & BDIF_CONNECTED) && (inRangeInfo->previousDeviceFlags & BDIF_CONNECTED)) {
-      log.Write(L"Bluetooth Audio device \"%S\" disconnected.", inRangeInfo->deviceInfo.name);
+      log.LogInfo(L"Bluetooth Audio device \"%S\" disconnected.", inRangeInfo->deviceInfo.name);
       return BluetoothStatus::Disconnected;
    }
    return BluetoothStatus::Unknown;
index 529f175e0f27d60017f7dfc21158bf72f9765370..63c008adf6d930c31f91714d4c8a516460610a98 100644 (file)
@@ -90,7 +90,7 @@ HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceAdded(LPCWSTR pwstrDevic
 {
    if (notifyParent_ && pwstrDeviceId != nullptr) {
       const auto deviceName = GetFriendlyDeviceName(pwstrDeviceId);
-      WMLog::GetInstance().GetInstance().Write(L"Device \"%s\" added", deviceName.c_str());
+      WMLog::GetInstance().GetInstance().LogInfo(L"Device \"%s\" added", deviceName.c_str());
       notifyParent_->ShouldReInit();
    }
    return S_OK;
@@ -100,7 +100,7 @@ HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceRemoved(LPCWSTR pwstrDev
 {
    if (notifyParent_ && pwstrDeviceId != nullptr) {
       const auto deviceName = GetFriendlyDeviceName(pwstrDeviceId);
-      WMLog::GetInstance().GetInstance().Write(L"Device \"%s\" removed", deviceName.c_str());
+      WMLog::GetInstance().GetInstance().LogInfo(L"Device \"%s\" removed", deviceName.c_str());
       notifyParent_->ShouldReInit();
    }
    return S_OK;
@@ -127,7 +127,7 @@ HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceStateChanged(
    if (notify && notifyParent_) {
       // TODO: Check if output device
       const auto deviceName = GetFriendlyDeviceName(pwstrDeviceId);
-      WMLog::GetInstance().GetInstance().Write(
+      WMLog::GetInstance().GetInstance().LogInfo(
          L"Device \"%s\" status changed to %s",
          deviceName.c_str(),
          what.c_str());
index 81cf9ae785ed7e8dba33ce6080445d06b9ebf46d..27ad22fce6055f37dc71e42f85424c8d5ab6d6d5 100644 (file)
@@ -109,7 +109,7 @@ bool MuteControl::Init(HWND hParent, const TrayIcon *trayIcon)
    wndClass.hInstance = hglobInstance;
    wndClass.lpszClassName = MUTECONTROL_CLASS_NAME;
    if (!RegisterClassExW(&wndClass)) {
-      WMLog::GetInstance().WriteWindowsError(L"RegisterClassEx");
+      WMLog::GetInstance().LogWinError(L"RegisterClassEx");
       return false;
    }
    hMuteCtrlWnd_ = CreateWindowEx(
@@ -123,7 +123,7 @@ bool MuteControl::Init(HWND hParent, const TrayIcon *trayIcon)
       hglobInstance,
       this);
    if (hMuteCtrlWnd_ == nullptr) {
-      WMLog::GetInstance().WriteWindowsError(L"CreateWindowEx");
+      WMLog::GetInstance().LogWinError(L"CreateWindowEx");
       UnregisterClassW(MUTECONTROL_CLASS_NAME, hglobInstance);
       return false;
    }
@@ -149,7 +149,7 @@ LRESULT CALLBACK MuteControl::WindowProc(
 
 void MuteControl::SetMute(bool mute)
 {
-   WMLog::GetInstance().Write(L"Manual muting: %s", mute ? L"on" : L"off");
+   WMLog::GetInstance().LogInfo(L"Manual muting: %s", mute ? L"on" : L"off");
    winAudio_->SetMute(mute);
 }
 
@@ -164,9 +164,9 @@ void MuteControl::SaveMuteStatus()
    );
 
    if (alreadySaved) {
-      WMLog::GetInstance().Write(L"Muting event already active. Skipping status save");
+      WMLog::GetInstance().LogInfo(L"Muting event already active. Skipping status save");
    } else {
-      WMLog::GetInstance().Write(L"Saving mute status");
+      WMLog::GetInstance().LogInfo(L"Saving mute status");
       winAudio_->SaveMuteStatus();
    }
 }
@@ -188,7 +188,7 @@ void MuteControl::MuteDelayed(int magic)
    if (magic != MUTE_DELAY_MAGIC_VALUE || delayedMuteTimerId_ == 0) {
       return;
    }
-   WMLog::GetInstance().Write(L"Muting workstation after delay");
+   WMLog::GetInstance().LogInfo(L"Muting workstation after delay");
    ShowNotification(
       WMi18n::GetInstance().GetTranslationW("popup.muting-workstation-after-delay.title"),
       WMi18n::GetInstance().GetTranslationW("popup.muting-workstation-after-delay.text"));
@@ -205,7 +205,7 @@ bool MuteControl::StartDelayedMute()
       muteDelaySeconds_ * 1000,
       DelayedMuteTimerProc);
    if (delayedMuteTimerId_ == 0) {
-      WMLog::GetInstance().WriteWindowsError(L"SetTimer", GetLastError());
+      WMLog::GetInstance().LogWinError(L"SetTimer", GetLastError());
    }
    return delayedMuteTimerId_ != 0;
 }
@@ -214,7 +214,7 @@ void MuteControl::RestoreVolume(bool withDelay)
 {
    WMLog& log = WMLog::GetInstance();
    if (!restoreVolume_) {
-      log.Write(L"Volume Restore has been disabled");
+      log.LogInfo(L"Volume Restore has been disabled");
       return;
    }
    const bool restore = !std::any_of(
@@ -225,13 +225,13 @@ void MuteControl::RestoreVolume(bool withDelay)
       }
    );
    if (!restore) {
-      log.Write(L"Skipping restore since other mute event is currently active");
+      log.LogInfo(L"Skipping restore since other mute event is currently active");
    } else if (delayedMuteTimerId_ != 0) {
       KillTimer(hMuteCtrlWnd_, delayedMuteTimerId_);
       delayedMuteTimerId_ = 0;
-      log.Write(L"Skipping restore, since delayed mute was not triggered yet");
+      log.LogInfo(L"Skipping restore, since delayed mute was not triggered yet");
    } else {
-      log.Write(L"Restoring previous mute state");
+      log.LogInfo(L"Restoring previous mute state");
       ShowNotification(
          WMi18n::GetInstance().GetTranslationW("popup.volume-restored.title"),
          WMi18n::GetInstance().GetTranslationW("popup.volume-restored.text"));
@@ -334,13 +334,13 @@ void MuteControl::NotifyRestoreCondition(int type, bool active, bool withDelay)
       muteConfig_[type].active = active;
       if (muteConfig_[type].shouldMute) {
          if (muteDelaySeconds_ == 0) {
-            WMLog::GetInstance().Write(L"Muting workstation");
+            WMLog::GetInstance().LogInfo(L"Muting workstation");
             ShowNotification(
                WMi18n::GetInstance().GetTranslationW("popup.muting-workstation.title"),
                WMi18n::GetInstance().GetTranslationW("popup.muting-workstation.text"));
             winAudio_->SetMute(true);
          } else {
-            WMLog::GetInstance().Write(L"Starting delayed mute timer...");
+            WMLog::GetInstance().LogInfo(L"Starting delayed mute timer...");
             StartDelayedMute();
          }
       }
@@ -356,14 +356,14 @@ void MuteControl::NotifyRestoreCondition(int type, bool active, bool withDelay)
 
 void MuteControl::NotifyWorkstationLock(bool active)
 {
-   WMLog::GetInstance().Write(L"Mute Event: Workstation Lock %s",
+   WMLog::GetInstance().LogInfo(L"Mute Event: Workstation Lock %s",
                               active ? L"start" : L"stop");
    NotifyRestoreCondition(MuteTypeWorkstationLock, active);
 }
 
 void MuteControl::NotifyRemoteSession(bool active)
 {
-   WMLog::GetInstance().Write(L"Mute Event: Remote Session %s",
+   WMLog::GetInstance().LogInfo(L"Mute Event: Remote Session %s",
                               active ? L"start" : L"stop");
    NotifyRestoreCondition(MuteTypeRemoteSession, active);
 }
@@ -371,7 +371,7 @@ void MuteControl::NotifyRemoteSession(bool active)
 void MuteControl::NotifyDisplayStandby(bool active)
 {
    if (displayWasOffOnce_ || active) {
-      WMLog::GetInstance().Write(L"Mute Event: Display Standby %s",
+      WMLog::GetInstance().LogInfo(L"Mute Event: Display Standby %s",
                                  active ? L"start" : L"stop");
       NotifyRestoreCondition(MuteTypeDisplayStandby, active);
       displayWasOffOnce_ = true;
@@ -380,7 +380,7 @@ void MuteControl::NotifyDisplayStandby(bool active)
 
 void MuteControl::NotifyBluetoothConnected(bool connected)
 {
-   WMLog::GetInstance().Write(
+   WMLog::GetInstance().LogInfo(
       L"Mute Event: Bluetooth audio device %s",
       connected ? L"connected" : L"disconnected");
    NotifyRestoreCondition(MuteTypeBluetoothDisconnect, !connected, true);
@@ -388,7 +388,7 @@ void MuteControl::NotifyBluetoothConnected(bool connected)
 
 void MuteControl::NotifyLogout()
 {
-   WMLog::GetInstance().Write(L"Mute Event: Logout start");
+   WMLog::GetInstance().LogInfo(L"Mute Event: Logout start");
    if (muteConfig_[MuteTypeLogout].shouldMute) {
       winAudio_->SetMute(true);
    }
@@ -396,7 +396,7 @@ void MuteControl::NotifyLogout()
 
 void MuteControl::NotifySuspend(bool /*active*/)
 {
-   WMLog::GetInstance().Write(L"Mute Event: Suspend start");
+   WMLog::GetInstance().LogInfo(L"Mute Event: Suspend start");
    if (muteConfig_[MuteTypeSuspend].shouldMute) {
       winAudio_->SetMute(true);
    }
@@ -404,7 +404,7 @@ void MuteControl::NotifySuspend(bool /*active*/)
 
 void MuteControl::NotifyShutdown()
 {
-   WMLog::GetInstance().Write(L"Mute Event: Shutdown start");
+   WMLog::GetInstance().LogInfo(L"Mute Event: Shutdown start");
    if (muteConfig_[MuteTypeShutdown].shouldMute) {
       winAudio_->SetMute(true);
    }
@@ -414,11 +414,11 @@ void MuteControl::NotifyQuietHours(bool active)
 {
    if (active) {
       SaveMuteStatus();
-      WMLog::GetInstance().Write(L"Mute Event: Quiet Hours startet");
+      WMLog::GetInstance().LogInfo(L"Mute Event: Quiet Hours startet");
       winAudio_->SaveMuteStatus();
       winAudio_->SetMute(true);
    } else {
-      WMLog::GetInstance().Write(L"Mute Event: Quiet Hours ended");
+      WMLog::GetInstance().LogInfo(L"Mute Event: Quiet Hours ended");
       RestoreVolume();
    }
 }
index 2de8ab581798dc5a9127d07adce808d5dfe5d18b..fbf6cbcf5cb57e50052e759e58996cb16621cc49 100644 (file)
@@ -149,7 +149,7 @@ bool QuietHoursTimer::LoadFromSettings(const WMSettings& settings)
    end.wHour = static_cast<WORD>((qhEnd_ - end.wMinute - end.wSecond) / 3600);
 
    if (IsQuietHours(&now, &start, &end)) {
-      WMLog::GetInstance().Write(L"Mute: On | Quiet hours have already started");
+      WMLog::GetInstance().LogInfo(L"Mute: On | Quiet hours have already started");
       SendMessage(hParent_, WM_WINMUTE_QUIETHOURS_START, 0, 0);
    } else {
       int timerQhStart = GetDiffMillseconds(&start, &now);
index 4e9eb7796a8f58a35efd62e2061cbe2b8eb41aeb..42188eced2cc2726fd4e87ead27b11554df59183 100644 (file)
@@ -104,7 +104,7 @@ static void ResizeTabs(HWND hTabCtrl, HWND* hTabs, int tabCount)
 
    HDWP hdwp = BeginDeferWindowPos(tabCount);
    if (hdwp == nullptr) {
-      PrintWindowsError(L"BeginDeferWindowPos", GetLastError());
+      ShowWindowsError(L"BeginDeferWindowPos", GetLastError());
    } else {
       for (int i = 0; i < tabCount; ++i) {
          HDWP newHdwp = DeferWindowPos(
@@ -117,7 +117,7 @@ static void ResizeTabs(HWND hTabCtrl, HWND* hTabs, int tabCount)
             tabCtrlRect.bottom - tabCtrlRect.top,
             0);
          if (newHdwp == nullptr) {
-            PrintWindowsError(L"DeferWindowPos", GetLastError());
+            ShowWindowsError(L"DeferWindowPos", GetLastError());
             break;
          } else {
             hdwp = newHdwp;
index e52a1db41a6323cec7c75eb2c399b696f0c8dceb..b26e1c371cde88e1acedc47b900135e8b14e0803 100644 (file)
@@ -52,7 +52,7 @@ static bool GetPairedBtAudioDevices(std::vector<std::wstring>& devices)
    btdi.dwSize = sizeof(btdi);
    HBLUETOOTH_DEVICE_FIND hBtDevFind = BluetoothFindFirstDevice(&bfrp, &btdi);
    if (hBtDevFind == nullptr) {
-      log.WriteWindowsError(L"BluetoothFindFirstDevice", GetLastError());
+      log.LogWinError(L"BluetoothFindFirstDevice", GetLastError());
    } else {
       do {
          if (GET_COD_MAJOR(btdi.ulClassofDevice) == COD_MAJOR_AUDIO) {
index 02fb0639cbd562130dbff971f566e3fc1312b812..d6e55c26bf38a37efe820cff624c7c153ce06ac9 100644 (file)
@@ -51,7 +51,7 @@ static void FillLanguageList(HWND hLanguageList, const SettingsGeneralData& dlgD
    for (const auto &lang : dlgData.langModules) {
       const auto itemId = SendMessage(hLanguageList, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(lang.langName.c_str()));
       if (itemId == CB_ERR || itemId == CB_ERRSPACE) {
-         WMLog::GetInstance().Write(L"Failed to add language %ls to language selector", lang.langName.c_str());
+         WMLog::GetInstance().LogError(L"Failed to add language %ls to language selector", lang.langName.c_str());
       } else {
          ComboBox_SetItemData(hLanguageList, itemId, lang.fileName.c_str());
       }
@@ -65,6 +65,7 @@ static void LoadSettingsGeneralDlgTranslation(HWND hDlg)
    i18n.SetItemText(hDlg, IDC_SELECT_LANGUAGE_LABEL, "settings.general.select-language-label");
    i18n.SetItemText(hDlg, IDC_RUNONSTARTUP, "settings.general.run-on-startup");
    i18n.SetItemText(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP, "settings.general.check-for-updates-on-start");
+   i18n.SetItemText(hDlg, IDC_CHECK_FOR_BETA_UPDATES, "settings.general.check-for-beta-updates-on-start");
    i18n.SetItemText(hDlg, IDC_ENABLELOGGING, "settings.general.enable-logging");
    i18n.SetItemText(hDlg, IDC_OPENLOG, "settings.general.btn-open-log-file");
 }
@@ -75,6 +76,7 @@ INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPA
    case WM_INITDIALOG: {
       HWND hAutostart = GetDlgItem(hDlg, IDC_RUNONSTARTUP);
       HWND hUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP);
+      HWND hBetaUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_BETA_UPDATES);
       HWND hLogging = GetDlgItem(hDlg, IDC_ENABLELOGGING);
       HWND hOpenLog = GetDlgItem(hDlg, IDC_OPENLOG);
 
@@ -99,6 +101,10 @@ INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPA
       enabled = !!dlgData->settings->QueryValue(SettingsKey::CHECK_FOR_UPDATE);
       Button_SetCheck(hUpdateCheck, enabled ? BST_CHECKED : BST_UNCHECKED);
 
+      EnableWindow(hBetaUpdateCheck, enabled);
+      enabled = !!dlgData->settings->QueryValue(SettingsKey::CHECK_FOR_BETA_UPDATE);
+      Button_SetCheck(hBetaUpdateCheck, enabled ? BST_CHECKED : BST_UNCHECKED);
+
       enabled = !!dlgData->settings->QueryValue(SettingsKey::LOGGING_ENABLED);
       Button_SetCheck(hLogging, enabled ? BST_CHECKED : BST_UNCHECKED);
       Button_Enable(hOpenLog, enabled);
@@ -137,6 +143,9 @@ INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPA
             SendMessageW(GetDlgItem(hDlg, IDC_LOGFILEPATH), WM_SETTEXT, 0,
                reinterpret_cast<LPARAM>(L""));
          }
+      } else if (LOWORD(wParam) == IDC_CHECK_FOR_UPDATES_ON_STARTUP) {
+         const int enabled = Button_GetCheck(GetDlgItem(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP));
+         EnableWindow(GetDlgItem(hDlg, IDC_CHECK_FOR_BETA_UPDATES), enabled);
       } else if (LOWORD(wParam) == IDC_OPENLOG) {
          WMLog& log = WMLog::GetInstance();
          const std::wstring filePath = log.GetLogFilePath().c_str();
@@ -151,6 +160,7 @@ INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPA
       HWND hAutostart = GetDlgItem(hDlg, IDC_RUNONSTARTUP);
       HWND hLogging = GetDlgItem(hDlg, IDC_ENABLELOGGING);
       HWND hUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_UPDATES_ON_STARTUP);
+      HWND hBetaUpdateCheck = GetDlgItem(hDlg, IDC_CHECK_FOR_BETA_UPDATES);
 
       const int enableLog = Button_GetCheck(hLogging) == BST_CHECKED;
       dlgData->settings->SetValue(SettingsKey::LOGGING_ENABLED, enableLog);
@@ -180,6 +190,9 @@ INT_PTR CALLBACK Settings_GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPA
       const int enableUpdateCheck = Button_GetCheck(hUpdateCheck) == BST_CHECKED;
       dlgData->settings->SetValue(SettingsKey::CHECK_FOR_UPDATE, enableUpdateCheck);
 
+      const int enableBetaUpdateCheck = Button_GetCheck(hBetaUpdateCheck) == BST_CHECKED;
+      dlgData->settings->SetValue(SettingsKey::CHECK_FOR_BETA_UPDATE, enableBetaUpdateCheck);
+
       if (Button_GetCheck(hAutostart) == BST_CHECKED) {
          dlgData->settings->EnableAutostart(true);
       } else {
index b2535cd7f7c6a76d41de86e58a842a6783b820fb..9ea9062363cb62157312f18adaadec5815ee7be1 100644 (file)
@@ -73,20 +73,20 @@ static bool GetAudioEndpoints(std::vector<std::wstring>& endpoints)
    for (UINT i = 0; i < epCount; ++i) {
       IMMDevicePtr device = nullptr;
       if (FAILED(audioEndpoints->Item(i, &device))) {
-         log.Write(L"Failed to get audio endpoint #%d", i);
+         log.LogError(L"Failed to get audio endpoint #%d", i);
          continue;
       }
 
       IPropertyStorePtr propStore = nullptr;
       if (FAILED(device->OpenPropertyStore(STGM_READ, &propStore))) {
-         log.Write(L"Failed to open property store for audio endpoint #%d", i);
+         log.LogError(L"Failed to open property store for audio endpoint #%d", i);
          continue;
       }
 
       PROPVARIANT value;
       PropVariantInit(&value);
       if (FAILED(propStore->GetValue(PKEY_Device_FriendlyName, &value))) {
-         log.Write(L"Failed to get device name for audio endpoint #%d", i);
+         log.LogError(L"Failed to get device name for audio endpoint #%d", i);
          continue;
       }
 
index 0be463e69129eabdf40d1210a8fd0cb849bc928b..af6c0f9941e90e691bae22273f8e424b2558b020 100644 (file)
@@ -130,7 +130,7 @@ INT_PTR CALLBACK Settings_MuteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM
                hDlg,
                Settings_ManageEndpointsDlgProc,
                reinterpret_cast<LPARAM>(settings)) == 0) {
-            PrintWindowsError(L"DialogBoxParam", GetLastError());
+            ShowWindowsError(L"DialogBoxParam", GetLastError());
          }
       }
       return 0;
index 060b194fa5f65f96d5d34793f885b3e1747676e2..c45a1b89f40457081e15c9bc16db7c9ebc6b5197 100644 (file)
@@ -153,7 +153,6 @@ static void LoadWifiDlgTranslation(HWND hDlg)
 
    i18n.SetItemText(hDlg, IDC_WIFI_INTRO, "settings.wifi.intro");
    i18n.SetItemText(hDlg, IDC_ENABLE_WIFI_MUTE, "settings.wifi.enable");
-   i18n.SetItemText(hDlg, IDC_IS_PERMITLIST, "settings.wifi.mute-when-not-in-list");
    i18n.SetItemText(hDlg, IDC_WIFI_ADD, "settings.btn-add");
    i18n.SetItemText(hDlg, IDC_WIFI_EDIT, "settings.btn-edit");
    i18n.SetItemText(hDlg, IDC_WIFI_REMOVE, "settings.btn-remove");
index 9cc6eef60b4e6d6bbccd480d0cf8ba399d72fd2b..977bf3f72f49eb1abb9bd0fa07b26a82215a09d2 100644 (file)
@@ -66,26 +66,66 @@ UpdateChecker::~UpdateChecker()
 {
 }
 
+bool UpdateChecker::ParseVersionInfo(const nlohmann::json &json, UpdateVersionInfo &versInfo) const
+{
+   WMLog &log = WMLog::GetInstance();
+   if (!json.contains("version") && !json.contains("downloadUrl")) {
+      log.LogError(L"Missing json fields in update file");
+      return false;
+   }
+   versInfo.version = ConvertStringToWideString(json["version"]);;
+   versInfo.downloadUrl = ConvertStringToWideString(json["downloadUrl"]);
+   return true;
+}
+
 bool UpdateChecker::ParseVersionFile(
    const std::string &fileContents,
    UpdateInfo &updateInfo) const
 {
    // Structure
    // {
-   //    "version": "2.4.1.0",
-   //    "versionPage" : "https://github.com/lx-s/WinMute/releases/"
+   //    "version": 1,
+   //       "stable" : {
+   //       "version": "2.4.1.0",
+   //          "download_page" : "https://github.com/lx-s/WinMute/releases/"
+   //    },
+   //       "beta" : {
+   //       "version": "2.4.1.0",
+   //          "download_page" : "https://github.com/lx-s/WinMute/releases/"
+   //    }
    // }
    WMLog &log = WMLog::GetInstance();
    try {
       auto json = nlohmann::json::parse(fileContents);
-      if (!json.contains("version") && !json.contains("versionPage")) {
-         log.Write(L"Missing json fields in update file");
+      if (!json.contains("version")) {
+         log.LogError(L"Missing update-file version");
+         return false;
+      }
+      const auto file_version = json["version"];
+      if (!file_version.is_number() || file_version.get<int>() != 1) {
+         log.LogError(L"Update file has incompatible version number");
+         return false;
+      }
+      if (!json.contains("stable") || !json.contains("beta")) {
+         log.LogError(L"Missing stable and/or beta fields");
          return false;
       }
-      updateInfo.newVersion = ConvertStringToWideString(json["version"]);
-      updateInfo.versionPageUrl = ConvertStringToWideString(json["versionPage"]);
+      const auto stableInfo = json["stable"];
+      const auto betaInfo = json["beta"];
+
+      if (!stableInfo.is_structured() || !betaInfo.is_structured()) {
+         log.LogError(L"Missing stable and/or beta fields");
+         return false;
+      }
+
+      if (!ParseVersionInfo(stableInfo, updateInfo.stable) ||
+          !ParseVersionInfo(betaInfo, updateInfo.beta)) {
+         log.LogError(L"Failed to parse stable and/or beta fields");
+         return false;
+      }
+
    } catch (const nlohmann::json::parse_error &pe) {
-      log.Write(L"Failed to parse update: %S", pe.what());
+      log.LogError(L"Failed to parse update: %S", pe.what());
       return false;
    }
    return true;
@@ -115,13 +155,13 @@ std::optional<bool> UpdateChecker::IsVersionGreater(const std::wstring &newVers,
    std::vector<int> curVersParsed;
    WMLog &log = WMLog::GetInstance();
    if (!ParseVersion(newVers, newVersParsed)) {
-      log.Write(L"Failed to parse new version string \"%s\"", newVers.c_str());
+      log.LogError(L"Failed to parse new version string \"%s\"", newVers.c_str());
       return std::nullopt;
    } else if (!ParseVersion(curVers, curVersParsed)) {
-      log.Write(L"Failed to parse current version string \"%s\"", curVers.c_str());
+      log.LogError(L"Failed to parse current version string \"%s\"", curVers.c_str());
       return std::nullopt;
    } else if (newVersParsed.size() != curVersParsed.size()) {
-      log.Write(L"Version format mismatch \"%s\" / \"%s\"", curVers.c_str(), newVers.c_str());
+      log.LogError(L"Version format mismatch \"%s\" / \"%s\"", curVers.c_str(), newVers.c_str());
       return std::nullopt;
    }
    for (size_t i = 0; i < newVersParsed.size(); ++i) {
@@ -147,12 +187,13 @@ bool UpdateChecker::GetUpdateInfo(UpdateInfo &updateInfo) const
       return false;
    }
 
-   const auto shouldUpdate = IsVersionGreater(updateInfo.newVersion, updateInfo.currentVersion);
-   if (!shouldUpdate) {
+   const auto shouldUpdateStable = IsVersionGreater(updateInfo.stable.version, updateInfo.currentVersion);
+   const auto shouldUpdateBeta = IsVersionGreater(updateInfo.beta.version, updateInfo.currentVersion);
+   if (!shouldUpdateStable || !shouldUpdateBeta) {
       return false;
    }
-   updateInfo.shouldUpdate = *shouldUpdate;
-
+   updateInfo.stable.shouldUpdate = *shouldUpdateStable;
+   updateInfo.beta.shouldUpdate = *shouldUpdateBeta;
    return true;
 }
 
@@ -166,7 +207,7 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
    updateUrl.dwHostNameLength = (DWORD)-1;
    updateUrl.dwUrlPathLength = (DWORD)-1;
    if (!WinHttpCrackUrl(UPDATE_FILE_URL, 0, 0, &updateUrl)) {
-      log.WriteWindowsError(L"WinHttpCrackUrl", GetLastError());
+      log.LogWinError(L"WinHttpCrackUrl", GetLastError());
       return false;
    }
 
@@ -177,7 +218,7 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
       WINHTTP_NO_PROXY_BYPASS,
       WINHTTP_FLAG_SECURE_DEFAULTS);
    if (hSession == nullptr) {
-      log.WriteWindowsError(L"WinHttpOpen", GetLastError());
+      log.LogWinError(L"WinHttpOpen", GetLastError());
       return false;
    }
 
@@ -190,7 +231,7 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
       (updateUrl.nScheme == INTERNET_SCHEME_HTTPS) ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT,
       0);
    if (hConnect == nullptr) {
-      log.WriteWindowsError(L"WinHttpConnect", GetLastError());
+      log.LogWinError(L"WinHttpConnect", GetLastError());
       return false;
    }
 
@@ -207,27 +248,22 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
       WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE);
 
    if (hRequest == nullptr) {
-      log.WriteWindowsError(L"WinHttpConnect", GetLastError());
+      log.LogWinError(L"WinHttpConnect", GetLastError());
       return false;
    }
 
    bool result = WinHttpSendRequest(
-      hRequest,
-      WINHTTP_NO_ADDITIONAL_HEADERS,
-      0,
-      WINHTTP_NO_REQUEST_DATA,
-      0,
-      0,
-      0);
+      hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+      WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
 
    if (!result) {
-      log.WriteWindowsError(L"WinHttpSendRequest", GetLastError());
+      log.LogWinError(L"WinHttpSendRequest", GetLastError());
       return false;
    }
 
    result = WinHttpReceiveResponse(hRequest, nullptr);
    if (!result) {
-      log.WriteWindowsError(L"WinHttpReceiveResponse", GetLastError());
+      log.LogWinError(L"WinHttpReceiveResponse", GetLastError());
       return false;
    }
 
@@ -241,10 +277,10 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
       &statusCodeSize,
       WINHTTP_NO_HEADER_INDEX);
    if (!result) {
-      log.WriteWindowsError(L"WinHttpQueryHeaders(WINHTTP_QUERY_STATUS_CODE)", GetLastError());
+      log.LogWinError(L"WinHttpQueryHeaders(WINHTTP_QUERY_STATUS_CODE)", GetLastError());
       return false;
    } else if (statusCode != HTTP_STATUS_OK) {
-      log.Write(L"Update-Server returned HTTP %d", HTTP_STATUS_OK);
+      log.LogError(L"Update-Server returned HTTP %d", HTTP_STATUS_OK);
       return false;
    }
 
@@ -252,7 +288,7 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
    for (;;) {
       DWORD availBytes = 0;
       if (!WinHttpQueryDataAvailable(hRequest, &availBytes)) {
-         log.WriteWindowsError(L"WinHttpQueryDataAvailable", GetLastError());
+         log.LogWinError(L"WinHttpQueryDataAvailable", GetLastError());
          return false;
       }
       if (availBytes == 0) {
@@ -261,7 +297,7 @@ bool UpdateChecker::GetVersionFile(std::string &fileContents) const
       std::string chunk(availBytes, ' ');
       DWORD byRead = 0;
       if (!WinHttpReadData(hRequest, reinterpret_cast<LPVOID>(&chunk[0]), availBytes, &byRead)) {
-         log.WriteWindowsError(L"WinHttpReadData", GetLastError());
+         log.LogWinError(L"WinHttpReadData", GetLastError());
          return false;
       }
       fileContents.append(chunk.begin(), chunk.begin() + byRead);
@@ -281,7 +317,7 @@ bool UpdateChecker::IsUpdateCheckEnabled(const WMSettings &settings) const
    const DWORD thisExePathSize = ARRAY_SIZE(thisExePath);
    const DWORD thisPathLen = GetModuleFileNameW(nullptr, thisExePath, thisExePathSize);
    if (thisPathLen == 0 || (thisPathLen == thisExePathSize && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
-      WMLog::GetInstance().WriteWindowsError(L"GetModuleFileNameW", ERROR_INSUFFICIENT_BUFFER);
+      WMLog::GetInstance().LogWinError(L"GetModuleFileNameW", ERROR_INSUFFICIENT_BUFFER);
       return false;
    }
    fs::path updateDisableFile{ thisExePath };
index bbfb93facf2f12c2d92db2a8e22b8b2d5279e9e7..33568d33934c57032dfb21da23d4a51c95c15418 100644 (file)
@@ -40,11 +40,16 @@ enum class UpdateCheckInterval : int {
    ON_STARTUP = 1,
 };
 
+struct UpdateVersionInfo {
+   std::wstring version;
+   std::wstring downloadUrl;
+   bool shouldUpdate = false;
+};
+
 struct UpdateInfo {
    std::wstring currentVersion;
-   std::wstring newVersion;
-   std::wstring versionPageUrl;
-   bool shouldUpdate;
+   UpdateVersionInfo stable;
+   UpdateVersionInfo beta;
 };
 
 class UpdateChecker {
@@ -64,4 +69,5 @@ private:
    bool ParseVersionFile(const std::string &fileContents, UpdateInfo& updateInfo) const;
    std::optional<bool> IsVersionGreater(const std::wstring &newVers, const std::wstring &curVers) const;
    bool ParseVersion(const std::wstring &vers, std::vector<int>& parsedVers) const;
+   bool ParseVersionInfo(const nlohmann::json &json, UpdateVersionInfo &versInfo) const;
 };
index 276687a85bbe4e25dc6be1b9568889b045dff727..a99cbe1c9ec25772e7abb41c0aedaf31e6a2d055 100644 (file)
@@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "Common.h"
 
-void PrintWindowsError(const wchar_t *functionName, DWORD lastError)
+void ShowWindowsError(const wchar_t *functionName, DWORD lastError)
 {
    // Retrieve the system error message for the last-error code
    if (lastError == -1) {
index 203d4ff20b16a17548073ee659c8b52d6a664be0..af7337f64aac4a99fc24c82087a6540d211f979b 100644 (file)
@@ -101,13 +101,13 @@ bool VistaAudio::LoadAllEndpoints()
 
       hr = audioEndpoints->Item(i, &device);
       if (FAILED(hr)) {
-         log.Write(L"Failed to get audio endpoint #%d", i);
+         log.LogError(L"Failed to get audio endpoint #%d", i);
          continue;
       }
 
       hr = device->OpenPropertyStore(STGM_READ, &propStore);
       if (FAILED(hr)) {
-         log.Write(L"Failed to open property store for audio endpoint #%d", i);
+         log.LogError(L"Failed to open property store for audio endpoint #%d", i);
          continue;
       }
 
@@ -115,10 +115,10 @@ bool VistaAudio::LoadAllEndpoints()
       PropVariantInit(&value);
       hr = propStore->GetValue(PKEY_Device_FriendlyName, &value);
       if (FAILED(hr)) {
-         log.Write(L"Failed to get device name for audio endpoint #%d", i);
+         log.LogError(L"Failed to get device name for audio endpoint #%d", i);
          continue;
       }
-      log.Write(L"Found audio endpoint \"%s\"", value.pwszVal);
+      log.LogInfo(L"Found audio endpoint \"%s\"", value.pwszVal);
       StringCchCopy(ep->deviceName,
                     sizeof(ep->deviceName)/sizeof(ep->deviceName[0]),
                     value.pwszVal);
@@ -129,14 +129,14 @@ bool VistaAudio::LoadAllEndpoints()
       if (FAILED(device->Activate(
             __uuidof(IAudioSessionManager2), CLSCTX_INPROC_SERVER, nullptr,
             reinterpret_cast<LPVOID*>(&sessionManager2)))) {
-         log.Write(L"Failed to retrieve audio session manager for \"%s\"",
+         log.LogError(L"Failed to retrieve audio session manager for \"%s\"",
                    ep->deviceName);
          continue;
       }
 
       hr = sessionManager2->GetAudioSessionControl(nullptr, 0, &ep->sessionCtrl);
       if (FAILED(hr)) {
-         log.Write(L"Failed to retrieve audio session manager for \"%s\"",
+         log.LogError(L"Failed to retrieve audio session manager for \"%s\"",
             ep->deviceName);
          continue;
       }
@@ -151,8 +151,8 @@ bool VistaAudio::LoadAllEndpoints()
          __uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER,
          nullptr, reinterpret_cast<LPVOID*>(&ep->endpointVolume));
       if (FAILED(hr)) {
-         log.Write(L"Failed to active endpoint volume for device \"%s\"",
-                   ep->deviceName);
+         log.LogError(L"Failed to active endpoint volume for device \"%s\"",
+            ep->deviceName);
          continue;
       }
       endpoints_.push_back(std::move(ep));
@@ -174,7 +174,7 @@ bool VistaAudio::Init(HWND hParent)
          __uuidof(MMDeviceEnumerator),
          nullptr,
          CLSCTX_INPROC_SERVER))) {
-      log.Write(L"Failed to create instance of MMDeviceEnumerator");
+      log.LogError(L"Failed to create instance of MMDeviceEnumerator");
       return false;
    }
 
@@ -223,7 +223,8 @@ bool VistaAudio::AllEndpointsMuted()
       for (auto& e : endpoints_) {
          BOOL isMuted = FALSE;
          if (FAILED(e->endpointVolume->GetMute(&isMuted))) {
-            log.Write(L"Failed to get mute status for \"%s\"",
+            log.LogError(
+               L"Failed to get mute status for \"%s\"",
                e->deviceName);
             allMuted = false;
             break;
@@ -245,8 +246,9 @@ bool VistaAudio::SaveMuteStatus()
       for (auto& e : endpoints_) {
          BOOL isMuted = FALSE;
          if (FAILED(e->endpointVolume->GetMute(&isMuted))) {
-            log.Write(L"Failed to get mute status for \"%s\"",
-                      e->deviceName);
+            log.LogError(
+               L"Failed to get mute status for \"%s\"",
+               e->deviceName);
             success = false;
          } else {
             e->wasMuted = isMuted;
@@ -266,15 +268,15 @@ bool VistaAudio::RestoreMuteStatus()
    }
    for (auto& e : endpoints_) {
       if (!IsEndpointManaged(e->deviceName)) {
-         log.Write(L"Skipping Endpoint %s", e->deviceName);
-            continue;
+         log.LogInfo(L"Skipping Endpoint %s", e->deviceName);
+         continue;
       }
-      log.Write(L"Restoring: Mute %s for \"%s\"",
+      log.LogInfo(L"Restoring: Mute %s for \"%s\"",
                 (e->wasMuted) ? L"true" : L"false",
                 e->deviceName);
       if (e->wasMuted != true) {
          if (FAILED(e->endpointVolume->SetMute(false, nullptr))) {
-            log.Write(_T("Failed to restore mute status to %s for \"%s\""),
+            log.LogError(_T("Failed to restore mute status to %s for \"%s\""),
                       (e->wasMuted) ? L"true" : L"false",
                       e->deviceName);
             success = false;
@@ -292,18 +294,20 @@ void VistaAudio::SetMute(bool mute)
       for (auto& e : endpoints_) {
          BOOL isMuted = !mute;
          if (!IsEndpointManaged(e->deviceName)) {
-            log.Write(L"Skipping Endpoint %s", e->deviceName);
+            log.LogInfo(L"Skipping Endpoint %s", e->deviceName);
             continue;
          }
          if (FAILED(e->endpointVolume->GetMute(&isMuted))) {
-            log.Write(L"Failed to get mute status for \"%s\"",
-                      e->deviceName);
+            log.LogError(
+               L"Failed to get mute status for \"%s\"",
+               e->deviceName);
          }
          if (!!isMuted != mute) {
             if (FAILED(e->endpointVolume->SetMute(mute, nullptr))) {
-               log.Write(L"Failed to set mute status to %s for \"%s\"",
-                         (e->wasMuted) ? L"true" : L"false",
-                         e->deviceName);
+               log.LogError(
+                  L"Failed to set mute status to %s for \"%s\"",
+                  (e->wasMuted) ? L"true" : L"false",
+                  e->deviceName);
             }
          }
       }
index c23090e8a0a69e5a7c8efc67a4a0b04497ea499a..e45f7c122375b4f3a2246d8e063571bc0a930032 100644 (file)
@@ -105,39 +105,77 @@ bool WMLog::IsEnabled() const
    return enabled_;
 }
 
-void WMLog::WriteMessage(const wchar_t* msg)
+void WMLog::WriteMessage(const wchar_t* level, const wchar_t* msg)
 {
-   struct tm tm = { 0 };
-   auto now = std::chrono::system_clock::now();
-   auto in_time_t = std::chrono::system_clock::to_time_t(now);
-
-   std::wstringstream ss;
-   localtime_s(&tm, &in_time_t);
-   ss << L"[" << std::put_time(&tm, L"%Y-%m-%d %X") << L"] "
-      << msg << L"\n";
-   const auto& logStr = ss.str();
+   time_t rawtime;
+   struct tm timeinfo;
+   wchar_t buffer[30];
+
+   time(&rawtime);
+   localtime_s(&timeinfo, &rawtime);
+
+   wcsftime(buffer, ARRAY_SIZE(buffer), L"%Y-%m-%d %H:%M:%S", &timeinfo);
+   const std::wstring logMsg = std::vformat(
+      L"[{} {}]: {}\n",
+      std::make_wformat_args(
+         buffer,
+         level,
+         msg)
+   );
    const std::scoped_lock<std::mutex> lock(logMutex_);
-   logFile_.write(logStr.c_str(), logStr.length());
+   logFile_.write(logMsg.c_str(), logMsg.length());
    logFile_.flush();
 }
 
-void WMLog::Write(_In_z_ _Printf_format_string_ const wchar_t *fmt, ...)
+void WMLog::LogDebug(_In_z_ _Printf_format_string_ const wchar_t *fmt, ...)
+{
+   if (!enabled_) {
+      return;
+   }
+
+   wchar_t buf[1024];
+   va_list ap;
+   va_start(ap, fmt);
+
+   vswprintf_s(buf, fmt, ap);
+   WriteMessage(L"Debug", buf);
+
+   va_end(ap);
+}
+
+void WMLog::LogInfo(_In_z_ _Printf_format_string_ const wchar_t *fmt, ...)
+{
+   if (!enabled_) {
+      return;
+   }
+
+   wchar_t buf[1024];
+   va_list ap;
+   va_start(ap, fmt);
+
+   vswprintf_s(buf, fmt, ap);
+   WriteMessage(L"Info", buf);
+
+   va_end(ap);
+}
+
+void WMLog::LogError(_In_z_ _Printf_format_string_ const wchar_t *fmt, ...)
 {
    if (!enabled_) {
       return;
    }
 
-   wchar_t buf[200];
+   wchar_t buf[1024];
    va_list ap;
    va_start(ap, fmt);
 
    vswprintf_s(buf, fmt, ap);
-   WriteMessage(buf);
+   WriteMessage(L"Error", buf);
 
    va_end(ap);
 }
 
-void WMLog::WriteWindowsError(const wchar_t *functionName, DWORD lastError)
+void WMLog::LogWinError(const wchar_t *functionName, DWORD lastError)
 {
    // Retrieve the system error message for the last-error code
    if (lastError == -1) {
@@ -160,6 +198,6 @@ void WMLog::WriteWindowsError(const wchar_t *functionName, DWORD lastError)
          functionName,
          lastError,
          reinterpret_cast<wchar_t *>(lpMsgBuf)));
-   WriteMessage(static_cast<const wchar_t*>(lpMsgBuf));
+   WriteMessage(L"Error", static_cast<const wchar_t *>(lpMsgBuf));
    LocalFree(lpMsgBuf);
 }
index cd0811c7c4f1e17cc175fa13d5c5f39c175aa386..717b29148313dcb84af86cd2c473de821e467aa5 100644 (file)
@@ -39,8 +39,10 @@ class WMLog {
 public:
    static WMLog& GetInstance();
 
-   void Write(_In_z_ _Printf_format_string_ const wchar_t* fmt, ...);
-   void WriteWindowsError(const wchar_t *functionName, DWORD errorCode = -1);
+   void LogDebug(_In_z_ _Printf_format_string_ const wchar_t *fmt, ...);
+   void LogInfo(_In_z_ _Printf_format_string_ const wchar_t* fmt, ...);
+   void LogError(_In_z_ _Printf_format_string_ const wchar_t *fmt, ...);
+   void LogWinError(const wchar_t *functionName, DWORD errorCode = -1);
 
    void SetEnabled(bool enable);
    bool IsEnabled() const;
@@ -52,7 +54,7 @@ private:
    WMLog(const WMLog&) = delete;
    WMLog& operator=(const WMLog&) = delete;
 
-   void WriteMessage(const wchar_t* msg);
+   void WriteMessage(const wchar_t *level, const wchar_t *msg);
    void DeleteLogFile();
 
    std::mutex logMutex_;
index 09438ccbe380835fa9549c4fc043d398198eb506..53011ef67ea61c5f2fab50bb7d6a2bce3714ec11 100644 (file)
@@ -125,6 +125,9 @@ static const wchar_t* KeyToStr(SettingsKey key)
    case SettingsKey::CHECK_FOR_UPDATE:
       keyStr = L"CheckForUpdate";
       break;
+   case SettingsKey::CHECK_FOR_BETA_UPDATE:
+      keyStr = L"CheckForBetaUpdate";
+      break;
    }
    return keyStr;
 }
@@ -176,6 +179,8 @@ static DWORD GetDefaultSetting(SettingsKey key)
       return 0;
    case SettingsKey::CHECK_FOR_UPDATE:
       return 0;
+   case SettingsKey::CHECK_FOR_BETA_UPDATE:
+      return 0;
    }
    return 0;
 }
@@ -199,8 +204,8 @@ static bool ReadStringFromRegistry(HKEY hKey, const wchar_t *subKey, std::wstrin
    regError = RegQueryValueExW(hKey, subKey, nullptr, nullptr, nullptr, &bufSize);
    if (regError != ERROR_SUCCESS) {
       if (regError != ERROR_FILE_NOT_FOUND) {
-         PrintWindowsError(L"RegQueryValueExW", regError);
-         log.Write(L"[Registry] Failed to read key \"%s\".", subKey);
+         ShowWindowsError(L"RegQueryValueExW", regError);
+         log.LogError(L"[Registry] Failed to read key \"%s\".", subKey);
       }
    } else {
       bufSize += 1; // Trailing '\0'
@@ -208,8 +213,8 @@ static bool ReadStringFromRegistry(HKEY hKey, const wchar_t *subKey, std::wstrin
       regError = RegQueryValueExW(hKey, subKey, nullptr, nullptr,
                                  reinterpret_cast<LPBYTE>(buf), &bufSize);
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegQueryValueExW", regError);
-         log.Write(L"[Registry] Failed to query value for key \"%s\".", subKey);
+         ShowWindowsError(L"RegQueryValueExW", regError);
+         log.LogError(L"[Registry] Failed to query value for key \"%s\".", subKey);
       } else {
          success = true;
          val = buf;
@@ -237,7 +242,7 @@ bool WMSettings::MigrateSettings()
 {
    DWORD version = QueryValue(SettingsKey::SETTINGS_VERSION);
    if (version != CURRENT_SETTINGS_VERSION) {
-      WMLog::GetInstance().Write(L"Unexpected settings version: %d", version);
+      WMLog::GetInstance().LogError(L"Unexpected settings version: %d", version);
    }
    return true;
 }
@@ -256,7 +261,7 @@ bool WMSettings::Init()
          &hSettingsKey_,
          nullptr);
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegCreateKeyEx", regError);
+         ShowWindowsError(L"RegCreateKeyEx", regError);
          return false;
       }
    }
@@ -272,7 +277,7 @@ bool WMSettings::Init()
          &hWifiKey_,
          nullptr);
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegCreateKeyEx", regError);
+         ShowWindowsError(L"RegCreateKeyEx", regError);
          RegCloseKey(hSettingsKey_);
          hSettingsKey_ = nullptr;
          return false;
@@ -290,7 +295,7 @@ bool WMSettings::Init()
          &hBluetoothKey_,
          nullptr);
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegCreateKeyEx", regError);
+         ShowWindowsError(L"RegCreateKeyEx", regError);
          RegCloseKey(hWifiKey_);
          RegCloseKey(hSettingsKey_);
          hSettingsKey_ = nullptr;
@@ -310,7 +315,7 @@ bool WMSettings::Init()
          &hAudioEndpointsKey_,
          nullptr);
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegCreateKeyEx", regError);
+         ShowWindowsError(L"RegCreateKeyEx", regError);
          RegCloseKey(hWifiKey_);
          RegCloseKey(hSettingsKey_);
          RegCloseKey(hBluetoothKey_);
@@ -346,7 +351,7 @@ HKEY WMSettings::OpenAutostartKey(REGSAM samDesired)
       samDesired,
       &hRunKey);
    if (regError != ERROR_SUCCESS) {
-      PrintWindowsError(L"RegOpenKeyEx", regError);
+      ShowWindowsError(L"RegOpenKeyEx", regError);
    }
    return hRunKey;
 }
@@ -357,14 +362,14 @@ bool WMSettings::IsAutostartEnabled()
    WMLog& log = WMLog::GetInstance();
    wchar_t wmPath[MAX_PATH + 1];
    if (GetModuleFileName(nullptr, wmPath, sizeof(wmPath) / sizeof(wmPath[0])) == 0) {
-      log.Write(L"Failed to get path of winmute");
+      log.LogError(L"Failed to get path of winmute");
    } else {
       HKEY hRunKey = OpenAutostartKey(KEY_READ);
       if (hRunKey != nullptr) {
          std::wstring path;
          if (ReadStringFromRegistry(hRunKey, LX_SYSTEMS_AUTOSTART_KEY, path)) {
             if (path != wmPath) {
-               log.Write(L"Autostart entry has wrong path");
+               log.LogInfo(L"Autostart entry has wrong path");
             } else {
                isEnabled = true;
             }
@@ -383,7 +388,7 @@ void WMSettings::EnableAutostart(bool enable)
       if (enable) {
          wchar_t wmPath[MAX_PATH + 1];
          if (GetModuleFileNameW(nullptr, wmPath, sizeof(wmPath) / sizeof(wmPath[0])) == 0) {
-            log.Write(L"Failed to get path of winmute");
+            log.LogError(L"Failed to get path of winmute");
          } else {
             DWORD regError = RegSetKeyValueW(
                hRunKey,
@@ -393,13 +398,13 @@ void WMSettings::EnableAutostart(bool enable)
                wmPath,
                (lstrlen(wmPath) + 1) * sizeof(wchar_t));
             if (regError != ERROR_SUCCESS) {
-               PrintWindowsError(L"RegSetKeyValue", regError);
+               ShowWindowsError(L"RegSetKeyValue", regError);
             }
          }
       } else {
          DWORD regError = RegDeleteKeyValueW(hRunKey, nullptr, LX_SYSTEMS_AUTOSTART_KEY);
          if (regError != ERROR_SUCCESS && regError != ERROR_FILE_NOT_FOUND) {
-            PrintWindowsError(L"RegDeleteKeyValue", regError);
+            ShowWindowsError(L"RegDeleteKeyValue", regError);
          }
       }
       RegCloseKey(hRunKey);
@@ -422,9 +427,9 @@ DWORD WMSettings::QueryValue(SettingsKey key) const
       &size);
    if (regError != ERROR_SUCCESS) {
       if (regError != ERROR_FILE_NOT_FOUND) {
-         PrintWindowsError(L"RegQueryValueExW", regError);
+         ShowWindowsError(L"RegQueryValueExW", regError);
          WMLog &log = WMLog::GetInstance();
-         log.Write(L"[Registry] Failed to query value for key \"%s\"", keyStr);
+         log.LogError(L"[Registry] Failed to query value for key \"%s\"", keyStr);
       }
       return GetDefaultSetting(key);
    }
@@ -456,7 +461,7 @@ bool WMSettings::SetValue(SettingsKey key, DWORD value)
       reinterpret_cast<BYTE*>(&value),
       sizeof(DWORD));
    if (regError != ERROR_SUCCESS) {
-      PrintWindowsError(L"RegSetValueExW", regError);
+      ShowWindowsError(L"RegSetValueExW", regError);
       return false;
    }
 
@@ -478,7 +483,7 @@ bool WMSettings::SetValue(SettingsKey key, const std::wstring &value)
       strValue,
       strLen);
    if (regError != ERROR_SUCCESS) {
-      PrintWindowsError(L"RegSetValueExW", regError);
+      ShowWindowsError(L"RegSetValueExW", regError);
       return false;
    }
 
@@ -503,12 +508,12 @@ bool WMSettings::StoreWifiNetworks(std::vector<std::wstring>& networks)
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return false;
       } else {
          regError = RegDeleteValue(hWifiKey_, valueName);
          if (regError != ERROR_SUCCESS) {
-            PrintWindowsError(L"RegDeleteValue", regError);
+            ShowWindowsError(L"RegDeleteValue", regError);
             return false;
          }
       }
@@ -528,7 +533,7 @@ bool WMSettings::StoreWifiNetworks(std::vector<std::wstring>& networks)
          reinterpret_cast<const BYTE*>(v.c_str()),
          static_cast<DWORD>(v.length() + 1) * sizeof(wchar_t));
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegSetValueEx", regError);
+         ShowWindowsError(L"RegSetValueEx", regError);
          return false;
       }
    }
@@ -558,7 +563,7 @@ std::vector<std::wstring> WMSettings::GetWifiNetworks() const
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return {};
       } else {
          networks.push_back(dataBuf);
@@ -586,12 +591,12 @@ bool WMSettings::StoreBluetoothDevices(std::vector<std::wstring>& devices)
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return false;
       } else {
          regError = RegDeleteValue(hBluetoothKey_, valueName);
          if (regError != ERROR_SUCCESS) {
-            PrintWindowsError(L"RegDeleteValue", regError);
+            ShowWindowsError(L"RegDeleteValue", regError);
             return false;
          }
       }
@@ -614,7 +619,7 @@ bool WMSettings::StoreBluetoothDevices(std::vector<std::wstring>& devices)
          reinterpret_cast<const BYTE*>(v.c_str()),
          static_cast<DWORD>(v.length() + 1) * sizeof(wchar_t));
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegSetValueEx", regError);
+         ShowWindowsError(L"RegSetValueEx", regError);
          return false;
       }
    }
@@ -644,7 +649,7 @@ std::vector<std::string> WMSettings::GetBluetoothDevicesA() const
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return {};
       } else {
          devices.push_back(dataBuf);
@@ -676,7 +681,7 @@ std::vector<std::wstring> WMSettings::GetBluetoothDevicesW() const
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return {};
       } else {
          devices.push_back(dataBuf);
@@ -705,12 +710,12 @@ bool WMSettings::StoreManagedAudioEndpoints(std::vector<std::wstring> &endpoints
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return false;
       } else {
          regError = RegDeleteValue(hAudioEndpointsKey_, valueName);
          if (regError != ERROR_SUCCESS) {
-            PrintWindowsError(L"RegDeleteValue", regError);
+            ShowWindowsError(L"RegDeleteValue", regError);
             return false;
          }
       }
@@ -733,7 +738,7 @@ bool WMSettings::StoreManagedAudioEndpoints(std::vector<std::wstring> &endpoints
          reinterpret_cast<const BYTE *>(v.c_str()),
          static_cast<DWORD>(v.length() + 1) * sizeof(wchar_t));
       if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegSetValueEx", regError);
+         ShowWindowsError(L"RegSetValueEx", regError);
          return false;
       }
    }
@@ -763,7 +768,7 @@ std::vector<std::wstring> WMSettings::GetManagedAudioEndpoints() const
       if (regError == ERROR_NO_MORE_ITEMS) {
          break;
       } else if (regError != ERROR_SUCCESS) {
-         PrintWindowsError(L"RegEnumValue", regError);
+         ShowWindowsError(L"RegEnumValue", regError);
          return {};
       } else {
          devices.push_back(dataBuf);
index c0e929dd18fd6148fd7eb3bfca8961346c9726c1..7d731f2cb122ff56d3acf39e1767dbb2b8acbb3d 100644 (file)
@@ -66,6 +66,7 @@ enum class SettingsKey {
    , LOGGING_ENABLED
    , APP_LANGUAGE
    , CHECK_FOR_UPDATE
+   , CHECK_FOR_BETA_UPDATE
 };
 
 class WMSettings {
index a370adb938763139eabb5e910bec7a2325c754fd..46e305b8184bcc6559af568ff2879682a1d09d23 100644 (file)
@@ -41,7 +41,6 @@ WMi18n::WMi18n() noexcept
 
 WMi18n::~WMi18n() noexcept
 {
-   UnloadLanguage();
 }
 
 WMi18n& WMi18n::GetInstance()
@@ -59,7 +58,7 @@ std::optional<fs::path> WMi18n::GetLanguageFilesPath() const
 {
    wchar_t wmPath[MAX_PATH + 1]{ 0 };
    if (GetModuleFileNameW(nullptr, wmPath, MAX_PATH) <= 0) {
-      WMLog::GetInstance().WriteWindowsError(L"GetModuleFileNameW", GetLastError());
+      WMLog::GetInstance().LogWinError(L"GetModuleFileNameW", GetLastError());
       return std::nullopt;
    }
    fs::path langPath = wmPath;
@@ -93,7 +92,7 @@ std::vector<LanguageModule> WMi18n::GetAvailableLanguages() const
                   langDlls.push_back(langMod);
                }
             } catch (const nlohmann::json::parse_error &pe) {
-               WMLog::GetInstance().Write(L"Failed to parse language file \"%ls\": %S", wfd.cFileName, pe.what());
+               WMLog::GetInstance().LogError(L"Failed to parse language file \"%ls\": %S", wfd.cFileName, pe.what());
             }
          } while (FindNextFileW(hFindFile, &wfd));
       }
@@ -135,7 +134,7 @@ bool WMi18n::LoadLanguage(const std::wstring &fileName, TranslationMap &strings)
    const fs::path loadFilePath{ fileName};
    *langFilePath /= loadFilePath.filename(); // Sanitize
    if (!fs::exists(*langFilePath)) {
-      log.Write(L"Language module \"%ls\" does not exist", langFilePath->c_str());
+      log.LogError(L"Language module \"%ls\" does not exist", langFilePath->c_str());
       return false;
    }
    try {
@@ -144,23 +143,23 @@ bool WMi18n::LoadLanguage(const std::wstring &fileName, TranslationMap &strings)
       TranslationMap translations_temp;
       for (auto it = json_data.begin(); it != json_data.end(); ++it) {
          if (it->is_structured()) {
-            log.Write(L"Language module \"%ls\" has nested elements", langFilePath->c_str());
+            log.LogError(L"Language module \"%ls\" has nested elements", langFilePath->c_str());
             return false;
          }
          const auto value = ConvertStringToWideString(it.value());
          if (value == L"") {
-            log.Write(L"Unable to convert language element \"%S\"", it.key().c_str());
+            log.LogError(L"Unable to convert language element \"%S\"", it.key().c_str());
             return false;
          }
          if (translations_temp.contains(it.key())) {
-            log.Write(L"Double entry for language key \"%S\" found.", it.key().c_str());
+            log.LogError(L"Double entry for language key \"%S\" found.", it.key().c_str());
             return false;
          }
          translations_temp[it.key()] = value;
       }
       strings = std::move(translations_temp);
    } catch (const nlohmann::json::parse_error &pe) {
-      WMLog::GetInstance().Write(
+      log.LogError(
          L"Failed to parse language file \"%ls\": %S",
          langFilePath->filename().c_str(),
          pe.what());
@@ -179,7 +178,7 @@ bool WMi18n::LoadLanguage(const std::wstring &fileName)
 
    TranslationMap new_lang;
    if (!LoadLanguage(fileName, new_lang)) {
-      WMLog::GetInstance().Write(L"Failed to load language \"%ls\"", fileName.c_str());
+      WMLog::GetInstance().LogError(L"Failed to load language \"%ls\"", fileName.c_str());
       return false;
    } else {
       UnloadLanguage();
@@ -191,10 +190,6 @@ bool WMi18n::LoadLanguage(const std::wstring &fileName)
 
 void WMi18n::UnloadLanguage()
 {
-   if (langMutex_.try_lock()) {
-      langMutex_.unlock();
-      throw "Lock was not acquired before unloading the language";
-   }
    loadedLang_.clear();
 }
 
@@ -231,7 +226,7 @@ bool WMi18n::SetItemText(HWND hWnd, int dlgItem, const std::string& textId)
 {
    const auto text = GetTranslationW(textId);
    if (!SetDlgItemTextW(hWnd, dlgItem, text.c_str())) {
-      WMLog::GetInstance().WriteWindowsError(L"SetDlgItemTextW", GetLastError());
+      WMLog::GetInstance().LogWinError(L"SetDlgItemTextW", GetLastError());
       return false;
    }
    return true;
@@ -241,7 +236,7 @@ bool WMi18n::SetItemText(HWND hItem, const std::string &textId)
 {
    const auto text = GetTranslationW(textId);
    if (!SetWindowTextW(hItem, text.c_str())) {
-      WMLog::GetInstance().WriteWindowsError(L"SetDlgItemTextW", GetLastError());
+      WMLog::GetInstance().LogWinError(L"SetDlgItemTextW", GetLastError());
       return false;
    }
    return true;
index 428461b211932909f8188351dbc040ed83226cc1..070a49eccd0f15b5d942a9ff25b0d8373f60a036 100644 (file)
@@ -72,14 +72,14 @@ bool WifiDetector::Init(HWND hNotifyWnd)
       DWORD wlErr = WlanOpenHandle(vers, nullptr, &vers, &wlanHandle_);
       if (wlErr != ERROR_SUCCESS) {
          if (wlErr != ERROR_SERVICE_NOT_ACTIVE) {
-            PrintWindowsError(L"WlanOpenHandle", wlErr);
+            ShowWindowsError(L"WlanOpenHandle", wlErr);
          }
       } else {
          wlErr = WlanRegisterNotification(
             wlanHandle_, WLAN_NOTIFICATION_SOURCE_ACM, TRUE,
             ::WlanNotificationCallback, this, nullptr, nullptr);
          if (wlErr != ERROR_SUCCESS) {
-            PrintWindowsError(L"WlanOpenHandle", wlErr);
+            ShowWindowsError(L"WlanOpenHandle", wlErr);
             WlanCloseHandle(wlanHandle_, nullptr);
          } else {
             initialized_ = true;
@@ -100,7 +100,7 @@ void WifiDetector::CheckNetwork()
    PWLAN_INTERFACE_INFO_LIST ifList;
    DWORD wlanErr = WlanEnumInterfaces(wlanHandle_, nullptr, &ifList);
    if (wlanErr != ERROR_SUCCESS) {
-      PrintWindowsError(L"WlanEnumInterfaces", wlanErr);
+      ShowWindowsError(L"WlanEnumInterfaces", wlanErr);
    } else {
       for (; ifList->dwIndex < ifList->dwNumberOfItems; ++ifList->dwIndex) {
          PWLAN_AVAILABLE_NETWORK_LIST availList = nullptr;
@@ -111,7 +111,7 @@ void WifiDetector::CheckNetwork()
             nullptr,
             &availList);
          if (wlanErr != ERROR_SUCCESS) {
-            PrintWindowsError(L"WlanGetAvailableNetworkList", wlanErr);
+            ShowWindowsError(L"WlanGetAvailableNetworkList", wlanErr);
          } else {
             for (; availList->dwIndex < availList->dwNumberOfItems; ++availList->dwIndex) {
                const PWLAN_AVAILABLE_NETWORK net = &availList->Network[availList->dwIndex];
index e5f9a9f0b7899c9c7a1cb0aefb5aa85b16030842..02edaa6c2513bde05f76fae8671495b199b7b8a2 100644 (file)
@@ -63,10 +63,10 @@ static bool InitWindowsComponents()
    initComCtrl.dwSize = sizeof(INITCOMMONCONTROLSEX);
    initComCtrl.dwICC = ICC_LINK_CLASS;
    if (InitCommonControlsEx(&initComCtrl) == FALSE) {
-      WMLog::GetInstance().WriteWindowsError(L"InitCommonControlsEx", GetLastError());
+      WMLog::GetInstance().LogWinError(L"InitCommonControlsEx", GetLastError());
       return FALSE;
    } else if (CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) != S_OK) {
-      WMLog::GetInstance().WriteWindowsError(L"CoInitializeEx", GetLastError());
+      WMLog::GetInstance().LogWinError(L"CoInitializeEx", GetLastError());
       return FALSE;
    }
    return TRUE;
index 9c352aeeaebf26a662f9f43a00be329296e25387..fa8123bc06d75eeecec940efb39e4c63d5ec39e5 100644 (file)
@@ -133,7 +133,7 @@ bool WinMute::RegisterWindowClass()
    wc.lpszClassName = WINMUTE_CLASS_NAME;
 
    if (!RegisterClassExW(&wc)) {
-      PrintWindowsError(L"RegisterClass");
+      ShowWindowsError(L"RegisterClass");
       return false;
    }
    return true;
@@ -144,7 +144,7 @@ bool WinMute::InitWindow()
    hWnd_ = CreateWindowExW(WS_EX_TOOLWINDOW, WINMUTE_CLASS_NAME, PROGRAM_NAME,
       WS_POPUP, 0, 0, 0, 0, nullptr, 0, hglobInstance, this);
    if (hWnd_ == nullptr) {
-      PrintWindowsError(L"CreateWindowEx");
+      ShowWindowsError(L"CreateWindowEx");
       return false;
    }
    return true;
@@ -179,7 +179,7 @@ bool WinMute::InitTrayMenu()
    if (hTrayMenu_ == nullptr) {
       hTrayMenu_ = LoadMenuW(hglobInstance, MAKEINTRESOURCE(IDR_TRAYMENU));
       if (hTrayMenu_ == nullptr) {
-         PrintWindowsError(L"LoadMenu");
+         ShowWindowsError(L"LoadMenu");
          return false;
       }
    }
@@ -208,7 +208,7 @@ bool WinMute::Init()
 #else
    WMLog::GetInstance().SetEnabled(settings_.QueryValue(SettingsKey::LOGGING_ENABLED));
 #endif
-   log.Write(L"Starting new session...");
+   log.LogInfo(L"Starting new session...");
 
    if (!RegisterWindowClass() || !InitWindow()) {
       return false;
@@ -227,25 +227,25 @@ bool WinMute::Init()
    }
 
    if (!WTSRegisterSessionNotification(hWnd_, NOTIFY_FOR_THIS_SESSION)) {
-      PrintWindowsError(L"WTSRegisterSessionNotification");
+      ShowWindowsError(L"WTSRegisterSessionNotification");
       return false;
    }
 
    if (!RegisterPowerSettingNotification(hWnd_, &GUID_CONSOLE_DISPLAY_STATE, 0)) {
-      PrintWindowsError(L"RegisterPowerSettingNotification");
+      ShowWindowsError(L"RegisterPowerSettingNotification");
       return false;
    }
 
    hTrayIcon_ = LoadIconW(hglobInstance, MAKEINTRESOURCE(IDI_APP));
    if (hTrayIcon_ == nullptr) {
-      PrintWindowsError(_T("LoadIcon"));
+      ShowWindowsError(_T("LoadIcon"));
       return false;
    }
    trayIcon_.Init(hWnd_, 0, hTrayIcon_, L"WinMute", true);
 
    quietHours_.Init(hWnd_, settings_);
 
-   log.Write(L"WinMute initialized");
+   log.LogInfo(L"WinMute initialized");
 
    if (settings_.QueryValue(SettingsKey::MUTE_ON_RDP)
        && IsCurrentSessionRemoteable()) {
@@ -267,21 +267,23 @@ bool WinMute::LoadSettings()
    if (log.IsEnabled()) {
       std::wstring versionNumber;
       GetWinMuteVersion(versionNumber);
-      log.Write(L"Starting WinMute %s", versionNumber.c_str());
-      log.Write(L"Loading settings:");
-      log.Write(L"\tRestore volume: %s", settings_.QueryValue(SettingsKey::RESTORE_AUDIO) ? L"Yes" : L"No");
-      log.Write(L"\tMute delay: %d", settings_.QueryValue(SettingsKey::MUTE_DELAY));
-      log.Write(L"\tMute on lock: %s", settings_.QueryValue(SettingsKey::MUTE_ON_LOCK) ? L"Yes" : L"No");
-      log.Write(L"\tMute on display standby: %s", settings_.QueryValue(SettingsKey::MUTE_ON_DISPLAYSTANDBY) ? L"Yes" : L"No");
-      log.Write(L"\tMute on logout: %s", settings_.QueryValue(SettingsKey::MUTE_ON_LOGOUT) ? L"Yes" : L"No");
-      log.Write(L"\tMute on suspend: %s", settings_.QueryValue(SettingsKey::MUTE_ON_SUSPEND) ? L"Yes" : L"No");
-      log.Write(L"\tMute on shutdown: %s", settings_.QueryValue(SettingsKey::MUTE_ON_SHUTDOWN) ? L"Yes" : L"No");
-      log.Write(L"\tShow notifications: %s", settings_.QueryValue(SettingsKey::NOTIFICATIONS_ENABLED) ? L"Yes" : L"No");
-      log.Write(L"\tMute on bluetooth: %s", settings_.QueryValue(SettingsKey::MUTE_ON_BLUETOOTH) ? L"Yes" : L"No");
-      log.Write(L"\t\tUse devicelist: %s", settings_.QueryValue(SettingsKey::MUTE_ON_BLUETOOTH_DEVICELIST) ? L"Yes" : L"No");
-      log.Write(L"\tMute on WLAN: %s", settings_.QueryValue(SettingsKey::MUTE_ON_WLAN) ? L"Yes" : L"No");
-      log.Write(L"\t\tUse allowlist: %s", settings_.QueryValue(SettingsKey::MUTE_ON_WLAN_ALLOWLIST) ? L"Yes" : L"No");
-      log.Write(L"\tMute specific endpoints only: %s", settings_.QueryValue(SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS) ? L"Yes" : L"No");
+      log.LogInfo(L"Starting WinMute %s", versionNumber.c_str());
+      log.LogInfo(L"Loading settings:");
+      log.LogInfo(L"Check for updates: %s", settings_.QueryValue(SettingsKey::CHECK_FOR_UPDATE) ? L"Yes" : L"No");
+      log.LogInfo(L"\tCheck for beta updates: %s", settings_.QueryValue(SettingsKey::CHECK_FOR_BETA_UPDATE) ? L"Yes" : L"No");
+      log.LogInfo(L"\tRestore volume: %s", settings_.QueryValue(SettingsKey::RESTORE_AUDIO) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute delay: %d", settings_.QueryValue(SettingsKey::MUTE_DELAY));
+      log.LogInfo(L"\tMute on lock: %s", settings_.QueryValue(SettingsKey::MUTE_ON_LOCK) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute on display standby: %s", settings_.QueryValue(SettingsKey::MUTE_ON_DISPLAYSTANDBY) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute on logout: %s", settings_.QueryValue(SettingsKey::MUTE_ON_LOGOUT) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute on suspend: %s", settings_.QueryValue(SettingsKey::MUTE_ON_SUSPEND) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute on shutdown: %s", settings_.QueryValue(SettingsKey::MUTE_ON_SHUTDOWN) ? L"Yes" : L"No");
+      log.LogInfo(L"\tShow notifications: %s", settings_.QueryValue(SettingsKey::NOTIFICATIONS_ENABLED) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute on bluetooth: %s", settings_.QueryValue(SettingsKey::MUTE_ON_BLUETOOTH) ? L"Yes" : L"No");
+      log.LogInfo(L"\t\tUse devicelist: %s", settings_.QueryValue(SettingsKey::MUTE_ON_BLUETOOTH_DEVICELIST) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute on WLAN: %s", settings_.QueryValue(SettingsKey::MUTE_ON_WLAN) ? L"Yes" : L"No");
+      log.LogInfo(L"\t\tUse allowlist: %s", settings_.QueryValue(SettingsKey::MUTE_ON_WLAN_ALLOWLIST) ? L"Yes" : L"No");
+      log.LogInfo(L"\tMute specific endpoints only: %s", settings_.QueryValue(SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS) ? L"Yes" : L"No");
    }
 
    if (!settings_.QueryValue(SettingsKey::MUTE_INDIVIDUAL_ENDPOINTS)) {
@@ -395,6 +397,7 @@ void WinMute::CheckForUpdates()
 
 void WinMute::CheckForUpdatesAsync(std::unique_ptr<UpdateChecker> updateChecker)
 {
+   const bool betaUpdates = settings_.QueryValue(SettingsKey::CHECK_FOR_BETA_UPDATE) != 0;
    if (!updateChecker) {
       return;
    }
@@ -402,10 +405,18 @@ void WinMute::CheckForUpdatesAsync(std::unique_ptr<UpdateChecker> updateChecker)
       trayIcon_.ShowPopup(
          i18n_.GetTranslationW("popup.error.update-check-failed.title"),
          i18n_.GetTranslationW("popup.error.update-check-failed.text"));
-   } else if (updateInfo_.shouldUpdate) {
+   } else if (updateInfo_.beta.shouldUpdate && betaUpdates) {
+      const std::wstring popupTitle = std::vformat(
+         i18n_.GetTranslationW("popup.update-available-beta.title"),
+         std::make_wformat_args(updateInfo_.beta.version));
+      const std::wstring popupText = std::vformat(
+         i18n_.GetTranslationW("popup.update-available-beta.text"),
+         std::make_wformat_args(updateInfo_.currentVersion));
+      trayIcon_.ShowPopup(popupTitle, popupText, WM_WINMUTE_UPDATE_POPUP);
+   } else if (updateInfo_.beta.shouldUpdate) {
       const std::wstring popupTitle = std::vformat(
          i18n_.GetTranslationW("popup.update-available.title"),
-         std::make_wformat_args(updateInfo_.newVersion));
+         std::make_wformat_args(updateInfo_.beta.version));
       const std::wstring popupText = std::vformat(
          i18n_.GetTranslationW("popup.update-available.text"),
          std::make_wformat_args(updateInfo_.currentVersion));
@@ -624,9 +635,16 @@ LRESULT WinMute::OnWifiStatusChange(HWND, WPARAM wParam, LPARAM lParam)
 LRESULT WinMute::OnUpdatePopup(HWND hWnd, WPARAM, LPARAM lParam)
 {
    if (lParam == NIN_BALLOONUSERCLICK) {
-      ShellExecuteW(
-         hWnd, L"open", updateInfo_.versionPageUrl.c_str(),
-         nullptr, nullptr, SW_SHOW);
+      const bool betaUpdates = settings_.QueryValue(SettingsKey::CHECK_FOR_BETA_UPDATE) != 0;
+      if (betaUpdates && updateInfo_.beta.shouldUpdate) {
+         ShellExecuteW(
+            hWnd, L"open", updateInfo_.beta.downloadUrl.c_str(),
+            nullptr, nullptr, SW_SHOW);
+      } else if (updateInfo_.stable.shouldUpdate) {
+         ShellExecuteW(
+            hWnd, L"open", updateInfo_.stable.downloadUrl.c_str(),
+            nullptr, nullptr, SW_SHOW);
+      }
    }
    return 0;
 }
index ee9e61682f6c4c9338f2977eb50a4379908f0f74..0a1a12e51f49f86595c15cb4ba8c562280763c26 100644 (file)
@@ -56,8 +56,8 @@ EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
 CAPTION "About WinMute"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    ICON            IDI_APP,IDC_STATIC,13,7,20,20,SS_CENTERIMAGE
-    LTEXT           "WinMute <VersionNumber>",IDC_ABOUT_TITLE,41,7,193,23
+    ICON            IDI_APP,IDC_STATIC,13,7,21,20,SS_CENTERIMAGE
+    LTEXT           "WinMute <VersionNumber>",IDC_ABOUT_TITLE,45,7,193,23
     CONTROL         "",IDC_ABOUT_TAB,"SysTabControl32",0x0,7,34,299,202
     PUSHBUTTON      "OK",IDOK,242,246,64,16
 END
@@ -68,9 +68,9 @@ EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
 CAPTION "Settings"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
+    CONTROL         "",IDC_SETTINGS_TAB,"SysTabControl32",0x0,7,7,255,238
     DEFPUSHBUTTON   "OK",IDOK,158,246,50,14
     PUSHBUTTON      "Cancel",IDCANCEL,212,246,50,14
-    CONTROL         "",IDC_SETTINGS_TAB,"SysTabControl32",0x0,7,7,255,238
 END
 
 IDD_SETTINGS_GENERAL DIALOGEX 0, 0, 233, 179
@@ -84,9 +84,11 @@ BEGIN
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,34,219,17
     CONTROL         "Check for updates on startup",IDC_CHECK_FOR_UPDATES_ON_STARTUP,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,50,219,17
-    CONTROL         "Enable logging",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,74,219,15
-    PUSHBUTTON      "Open log file...",IDC_OPENLOG,22,90,104,16
-    LTEXT           "[log file path]",IDC_LOGFILEPATH,23,110,203,27
+    CONTROL         "Also check for beta-updates",IDC_CHECK_FOR_BETA_UPDATES,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,27,65,199,17
+    CONTROL         "Enable logging",IDC_ENABLELOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,98,219,15
+    PUSHBUTTON      "Open log file...",IDC_OPENLOG,22,114,104,16
+    LTEXT           "[log file path]",IDC_LOGFILEPATH,23,134,203,27
 END
 
 IDD_SETTINGS_QUIETHOURS DIALOGEX 0, 0, 246, 198
@@ -132,12 +134,17 @@ BEGIN
     GROUPBOX        "General",IDC_GROUP_GENERAL,7,7,228,61
     CONTROL         "Show mute event notifications",IDC_SHOWNOTIFICATIONS,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,15,219,18
+    CONTROL         "Manage audio endpoints individually",IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,28,219,18
+    PUSHBUTTON      "Manage endpoints...",IDC_MANAGE_ENDPOINTS,26,46,97,15
     GROUPBOX        "Mute with volume restore, when...",IDC_GROUP_MUTE_WITH_RESTORE,7,71,228,71
     CONTROL         "... the workstation is locked.",IDC_MUTE_WHEN_WS_LOCKED,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,83,207,10
     CONTROL         "... the screen turns off.",IDC_MUTE_WHEN_SCREEN_OFF,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,97,205,10
     CONTROL         "Restore volume afterwards.",IDC_RESTOREVOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,112,210,10
+    EDITTEXT        IDC_MUTEDELAY,13,124,30,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+    LTEXT           "seconds delay before muting.",IDC_DELAY_MUTING_LABEL,47,127,169,8
     GROUPBOX        "Mute without volume restore, when...",IDC_GROUP_MUTE_WITHOUT_RESTORE,7,145,228,67
     CONTROL         "... the computer shuts down.",IDC_MUTE_WHEN_SHUTDOWN,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,156,207,10
@@ -146,28 +153,23 @@ BEGIN
     CONTROL         "... you log out.",IDC_MUTE_WHEN_LOGOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,184,207,10
     CONTROL         "... when WinMute is started within a RDP session.",IDC_MUTE_WHEN_RDP_SESSION,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,198,208,10
-    CONTROL         "Manage audio endpoints individually",IDC_MANAGE_AUDIO_ENDPOINTS_INDIVIDUALLY,
-                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,28,219,18
-    PUSHBUTTON      "Manage endpoints...",IDC_MANAGE_ENDPOINTS,26,46,97,15
-    LTEXT           "seconds delay before muting.",IDC_DELAY_MUTING_LABEL,47,127,169,8
-    EDITTEXT        IDC_MUTEDELAY,13,124,30,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
 END
 
 IDD_SETTINGS_WIFI DIALOGEX 0, 0, 242, 216
 STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    LISTBOX         IDC_WIFI_LIST,7,88,166,121,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
-    PUSHBUTTON      "Add",IDC_WIFI_ADD,179,87,56,16
-    PUSHBUTTON      "Edit",IDC_WIFI_EDIT,179,106,56,16
-    PUSHBUTTON      "Remove",IDC_WIFI_REMOVE,179,125,56,16
-    PUSHBUTTON      "Remove all",IDC_WIFI_REMOVEALL,179,193,56,16
-    CONTROL         "Enable WLAN based muting",IDC_ENABLE_WIFI_MUTE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,44,228,14
     LTEXT           "Description\nDescription\nDescription\nDescription",IDC_WIFI_INTRO,7,7,228,37
+    CONTROL         "Enable WLAN based muting",IDC_ENABLE_WIFI_MUTE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,44,228,14
     CONTROL         "Mute if connected WLAN is in list",IDC_WLAN_LIST_IS_ALLOWLIST,
                     "Button",BS_AUTORADIOBUTTON,17,60,209,10
     CONTROL         "Mute if connected WLAN is not in list",IDC_WLAN_LIST_IS_BLOCKLIST,
                     "Button",BS_AUTORADIOBUTTON,17,73,207,10
+    LISTBOX         IDC_WIFI_LIST,7,88,166,121,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "Add",IDC_WIFI_ADD,179,87,56,16
+    PUSHBUTTON      "Edit",IDC_WIFI_EDIT,179,106,56,16
+    PUSHBUTTON      "Remove",IDC_WIFI_REMOVE,179,125,56,16
+    PUSHBUTTON      "Remove all",IDC_WIFI_REMOVEALL,179,193,56,16
 END
 
 IDD_SETTINGS_WIFI_ADD DIALOGEX 0, 0, 201, 62
@@ -175,10 +177,10 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM
 CAPTION "Add WiFi"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    DEFPUSHBUTTON   "Save",IDOK,91,41,50,14
-    PUSHBUTTON      "Cancel",IDCANCEL,144,41,50,14
     LTEXT           "SSID/WiFi Name:",IDC_WIFI_NAME_LABEL,7,7,62,14
     EDITTEXT        IDC_WIFI_NAME,7,20,187,16,ES_AUTOHSCROLL
+    DEFPUSHBUTTON   "Save",IDOK,91,41,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,144,41,50,14
 END
 
 IDD_SETTINGS_BLUETOOTH DIALOGEX 0, 0, 244, 222
@@ -186,16 +188,16 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
 EXSTYLE WS_EX_CONTROLPARENT
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
+    LTEXT           "Description\nDescription\nDescription\nDescription\nDescription\nDescription",IDC_BLUETOOTH_DESCRIPTION_LABEL,7,7,230,51
+    CONTROL         "Enable Bluetooth based muting",IDC_ENABLE_BLUETOOTH_MUTE,
+                    "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,62,228,14
+    CONTROL         "Enable only for these devices:",IDC_ENABLE_BLUETOOTH_MUTE_DEVICE_LIST,
+                    "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,20,79,215,12
     LISTBOX         IDC_BLUETOOTH_LIST,7,95,168,120,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
     PUSHBUTTON      "Add",IDC_BLUETOOTH_ADD,181,94,56,16
     PUSHBUTTON      "Edit",IDC_BLUETOOTH_EDIT,181,113,56,16
     PUSHBUTTON      "Remove",IDC_BLUETOOTH_REMOVE,181,132,56,16
     PUSHBUTTON      "Remove all",IDC_BLUETOOTH_REMOVEALL,181,199,56,16
-    CONTROL         "Enable Bluetooth based muting",IDC_ENABLE_BLUETOOTH_MUTE,
-                    "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,62,228,14
-    CONTROL         "Enable only for these devices:",IDC_ENABLE_BLUETOOTH_MUTE_DEVICE_LIST,
-                    "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,20,79,215,12
-    LTEXT           "Description\nDescription\nDescription\nDescription\nDescription\nDescription",IDC_BLUETOOTH_DESCRIPTION_LABEL,7,7,230,51
 END
 
 IDD_SETTINGS_BLUETOOTH_ADD DIALOGEX 0, 0, 201, 62
@@ -203,10 +205,10 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM
 CAPTION "Add Bluetooth device"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    DEFPUSHBUTTON   "Save",IDOK,91,41,50,14
-    PUSHBUTTON      "Cancel",IDCANCEL,144,41,50,14
     LTEXT           "Bluetooth device name:",IDC_LABEL_BT_DEVICE_NAME,7,7,187,14
     COMBOBOX        IDC_BT_DEVICE_NAME,7,22,187,17,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "Save",IDOK,91,41,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,144,41,50,14
 END
 
 IDD_MANAGE_ENDPOINTS DIALOGEX 0, 0, 241, 200
@@ -214,19 +216,19 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM
 CAPTION "Manage Endpoints"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    DEFPUSHBUTTON   "Save",IDOK,133,179,50,14
-    PUSHBUTTON      "Cancel",IDCANCEL,184,179,50,14
-    LISTBOX         IDC_ENDPOINT_LIST,13,60,156,110,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
-    PUSHBUTTON      "Add",IDC_ENDPOINT_ADD,175,60,56,16
-    PUSHBUTTON      "Edit",IDC_ENDPOINT_EDIT,175,78,56,16
-    PUSHBUTTON      "Remove",IDC_ENDPOINT_REMOVE,175,97,56,16
-    PUSHBUTTON      "Remove all",IDC_ENDPOINT_REMOVEALL,178,155,56,16
+    GROUPBOX        "List behaviour",IDC_GROUP_LIST_BEHAVIOUR,7,7,227,41
     CONTROL         "Mute only listed endpoints",IDC_ENDPOINT_LIST_IS_ALLOWLIST,
                     "Button",BS_AUTORADIOBUTTON,13,19,209,10
     CONTROL         "Mute all but the listed endpoints",IDC_ENDPOINT_LIST_IS_BLOCKLIST,
                     "Button",BS_AUTORADIOBUTTON,13,32,207,10
-    GROUPBOX        "List behaviour",IDC_GROUP_LIST_BEHAVIOUR,7,7,227,41
     GROUPBOX        "Endpoints",IDC_GROUP_ENDPOINTS,7,48,227,128
+    LISTBOX         IDC_ENDPOINT_LIST,13,60,156,110,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "Add",IDC_ENDPOINT_ADD,175,60,56,16
+    PUSHBUTTON      "Edit",IDC_ENDPOINT_EDIT,175,78,56,16
+    PUSHBUTTON      "Remove",IDC_ENDPOINT_REMOVE,175,97,56,16
+    PUSHBUTTON      "Remove all",IDC_ENDPOINT_REMOVEALL,178,155,56,16
+    DEFPUSHBUTTON   "Save",IDOK,133,179,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,184,179,50,14
 END
 
 IDD_MANAGE_ENDPOINTS_ADD DIALOGEX 0, 0, 201, 62
@@ -234,10 +236,10 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM
 CAPTION "Add Endpoint"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    DEFPUSHBUTTON   "Save",IDOK,91,41,50,14
-    PUSHBUTTON      "Cancel",IDCANCEL,144,41,50,14
     LTEXT           "Endpoint name:",IDC_ENDPOINT_NAME_LABEL,7,7,187,14
     COMBOBOX        IDC_ENDPOINT_NAME,7,22,187,17,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "Save",IDOK,91,41,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,144,41,50,14
 END
 
 
index 0f1b4fc50e411bea47c1610567ada67378c756d3..824c61e09812d7d3b5662eff1ad63185dca65812 100644 (file)
@@ -134,7 +134,7 @@ constexpr int WM_WINMUTE_UPDATE_POPUP = WM_USER + 301;
 // =============================================================================
 // Utility
 
-void PrintWindowsError(const wchar_t *functionName, DWORD lastError = -1);
+void ShowWindowsError(const wchar_t *functionName, DWORD lastError = -1);
 bool GetWinMuteVersion(std::wstring &versNumber);
 
 std::wstring ConvertStringToWideString(const std::string &ansiString);
index ff2312107ed86b808054ea5f6fb0953b06b85e28..cac11632c0cb4b5ddb03d8c6bb9f44bcaa41e8b5 100644 (file)
 #define IDC_ENABLE_WIFI_MUTE            1011
 #define IDC_ENABLELOGGING               1012
 #define IDC_CHECK3                      1013
-#define IDC_RUNONSTARTUP2               1013
 #define IDC_CHECK_FOR_UPDATES_ON_STARTUP 1013
 #define IDC_OPENLOG                     1014
 #define IDC_LICENSETEXT                 1015
+#define IDC_CHECK_FOR_UPDATES_ON_STARTUP2 1015
+#define IDC_CHECK_FOR_BETA_UPDATES      1015
 #define IDC_ABOUT_TAB                   1016
 #define IDC_ABOUTTEXT                   1019
 #define IDC_TITLE                       1020