]> repos.lx-s.de Git - winmute.git/commitdiff
Added settings migration to new quiet hours settings
authorlx-s <lx-s@users.noreply.github.com>
Sun, 1 Feb 2026 12:57:59 +0000 (13:57 +0100)
committerlx-s <lx-s@users.noreply.github.com>
Sun, 1 Feb 2026 12:57:59 +0000 (13:57 +0100)
Translations/lang-de.json
Translations/lang-en.json
WinMute/QuietHoursTimer.cpp
WinMute/Settings_QuietHoursDlg.cpp
WinMute/WMSettings.cpp
WinMute/WMSettings.h

index 9f57ac517ef5043a59961e5f4708f82b1d19675a..5d5054c28714e555fa6e98b96b4732573a840bc9 100644 (file)
@@ -9,6 +9,8 @@
   "init.error.winmute.text": "Ein kritischer Fehler trat beim starten von WinMute auf. Das Programm muss beendet werden.",
   "init.error.winmute.platform-support.title": "Nur Windows Vista and neuer werden unterstützt",
   "init.error.winmute.platform-support.text": "Für Windows XP Unterstützung, kann WinMute in der Version 1.4.2 oder älter installiert werden.",
+  "init.error.winmute.migrating-settings-error": "Fehler beim Migrieren der Einstellungen. Bitte konsultieren sie das Fehlerprotokoll und/oder erstellen sie ein Support-Ticket",
+  "init.error.winmute.quiet-hours-corrupted-settings": "QuietHours Einstellungen wurden beschädigt. Die QuietHour Zeiten wurden zurückgesetzt.",
   "general.error.winapi.text": "{} fehlgeschlagen mit Fehler {}: {}",
   "general.error.audio-service-shutdown.title": "Der Audioservice wurde beendet.",
   "general.error.audio-service-shutdown.text": "WinMute kann diese Situation nicht Beheben. Bitte starten Sie das Programm neu.",
index 5cef550bf0adf0d4c2d5486721cc3e8ed95b52da..33cd2d1f0001d6dc59cc4a7573e0745c869feffc 100644 (file)
@@ -9,6 +9,8 @@
   "init.error.winmute.text": "WinMute encountered a critical error while initializing and must shut down.",
   "init.error.winmute.platform-support.title": "Only Windows Vista and newer is supported",
   "init.error.winmute.platform-support.text": "If Windows XP support is needed, please download WinMute version 1.4.2 or lower.",
+  "init.error.winmute.migrating-settings-error": "Failed to migrate settings. Please review error log and/or create a support ticket",
+  "init.error.winmute.quiet-hours-corrupted-settings": "Quiet Hours settings are corrupted. Quiet Hour times have been reset",
   "general.error.winapi.text": "{} failed with error {}: {}",
   "general.error.audio-service-shutdown.title": "The audio service has been shut down.",
   "general.error.audio-service-shutdown.text": "WinMute is not able to recover from that condition.\nPlease try to restart the program.",
index 3bffa1e683e356beda8439bea6b5bca877552113..2c019727f0636655332af308f2b8ad7d1b1ce680 100644 (file)
@@ -130,8 +130,8 @@ bool QuietHoursTimer::LoadFromSettings(const WMSettings& settings)
       return true;
    }
 
-   qhStart_ = settings.QueryValue(SettingsKey::QUIETHOURS_START);
-   qhEnd_ = settings.QueryValue(SettingsKey::QUIETHOURS_END);
+   qhStart_ = settings.QueryValue(SettingsKey::QUIETHOURS_START_V0_DEPRECATED);
+   qhEnd_ = settings.QueryValue(SettingsKey::QUIETHOURS_END_V0_DEPRECATED);
 
    SYSTEMTIME now;
    SYSTEMTIME start;
index 2785c8d7804065f12a32648d50be108e25306a59..00c116f587c8a43a817ccaddf488fb69df09dc72 100644 (file)
@@ -76,8 +76,8 @@ static bool SaveQuietHours(
    if (!settings->SetValue(SettingsKey::QUIETHOURS_ENABLE, enabled)
        || !settings->SetValue(SettingsKey::QUIETHOURS_FORCEUNMUTE, forceUnmute)
        || !settings->SetValue(SettingsKey::QUIETHOURS_NOTIFICATIONS, showNotifications)
-       || !settings->SetValue(SettingsKey::QUIETHOURS_START, setStart)
-       || !settings->SetValue(SettingsKey::QUIETHOURS_END, setEnd)) {
+       || !settings->SetValue(SettingsKey::QUIETHOURS_START_V0_DEPRECATED, setStart)
+       || !settings->SetValue(SettingsKey::QUIETHOURS_END_V0_DEPRECATED, setEnd)) {
       WMi18n &i18n = WMi18n::GetInstance();
 
       TaskDialog(
@@ -143,8 +143,8 @@ INT_PTR CALLBACK Settings_QuietHoursDlgProc(HWND hDlg, UINT msg, WPARAM wParam,
       EnableWindow(hStart, qhEnabled);
       EnableWindow(hEnd, qhEnabled);
 
-      int setStart = settings->QueryValue(SettingsKey::QUIETHOURS_START);
-      int setEnd = settings->QueryValue(SettingsKey::QUIETHOURS_END);
+      int setStart = settings->QueryValue(SettingsKey::QUIETHOURS_START_V0_DEPRECATED);
+      int setEnd = settings->QueryValue(SettingsKey::QUIETHOURS_END_V0_DEPRECATED);
 
       SYSTEMTIME start;
       GetLocalTime(&start);
index 176c07f6ce23615ce26a7f65fbecff59a58d5061..e7469e481b8bb156cfe30c33fb6baff5e7e5f98b 100644 (file)
@@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "common.h"
 
-static constexpr int CURRENT_SETTINGS_VERSION = 0;
+static constexpr int CURRENT_SETTINGS_VERSION = 1;
 
 static const wchar_t *LX_SYSTEMS_SUBKEY
    = L"SOFTWARE\\lx-systems\\WinMute";
@@ -43,6 +43,8 @@ static const wchar_t* LX_SYSTEMS_BLUETOOTH_SUBKEY
    = L"SOFTWARE\\lx-systems\\WinMute\\BluetoothDevices";
 static const wchar_t *LX_SYSTEMS_AUDIO_ENDPOINTS_SUBKEY
 = L"SOFTWARE\\lx-systems\\WinMute\\ManagedAudioEndpoints";
+static const wchar_t *LX_SYSTEMS_QUIET_HOUR_TIMES_SUBKEY
+= L"SOFTWARE\\lx-systems\\WinMute\\QuietHourTimes";
 
 static const wchar_t* LX_SYSTEMS_AUTOSTART_KEY
    = L"LX-Systems WinMute";
@@ -113,10 +115,10 @@ static const wchar_t* KeyToStr(SettingsKey key)
    case SettingsKey::QUIETHOURS_NOTIFICATIONS:
       keyStr = L"QuietHoursNotifications";
       break;
-   case SettingsKey::QUIETHOURS_START:
+   case SettingsKey::QUIETHOURS_START_V0_DEPRECATED:
       keyStr = L"QuietHoursStart";
       break;
-   case SettingsKey::QUIETHOURS_END:
+   case SettingsKey::QUIETHOURS_END_V0_DEPRECATED:
       keyStr = L"QuietHoursEnd";
       break;
    case SettingsKey::LOGGING_ENABLED:
@@ -177,9 +179,9 @@ static DWORD GetDefaultSetting(SettingsKey key)
       return 0;
    case SettingsKey::QUIETHOURS_NOTIFICATIONS:
       return 0;
-   case SettingsKey::QUIETHOURS_START:
+   case SettingsKey::QUIETHOURS_START_V0_DEPRECATED:
       return 0;
-   case SettingsKey::QUIETHOURS_END:
+   case SettingsKey::QUIETHOURS_END_V0_DEPRECATED:
       return 0;
    case SettingsKey::LOGGING_ENABLED:
       return 0;
@@ -250,9 +252,36 @@ WMSettings::~WMSettings()
 
 bool WMSettings::MigrateSettings()
 {
+   WMi18n &i18n = WMi18n::GetInstance();
    DWORD version = QueryValue(SettingsKey::SETTINGS_VERSION);
-   if (version != CURRENT_SETTINGS_VERSION) {
-      WMLog::GetInstance().LogError(L"Unexpected settings version: %d", version);
+   if (version > CURRENT_SETTINGS_VERSION) {
+      WMLog::GetInstance().LogError(
+         L"Settings version %d is newer than application supports (%d). "
+         L"Some settings may not work correctly.",
+         version,
+         CURRENT_SETTINGS_VERSION);
+   } else if (version == 0) {
+      // Migrate Quiet Hours settings from old keys and update settings version
+      const auto quietHoursStart = QueryValue(SettingsKey::QUIETHOURS_START_V0_DEPRECATED);
+      const auto quietHoursEnd = QueryValue(SettingsKey::QUIETHOURS_END_V0_DEPRECATED);
+
+      if (StoreQuietHoursTimes({ { quietHoursStart, quietHoursEnd } })
+          && SetValue(SettingsKey::SETTINGS_VERSION, CURRENT_SETTINGS_VERSION)) {
+         // Remove old settings keys
+         RegDeleteValueW(hSettingsKey_, KeyToStr(SettingsKey::QUIETHOURS_START_V0_DEPRECATED));
+         RegDeleteValueW(hSettingsKey_, KeyToStr(SettingsKey::QUIETHOURS_END_V0_DEPRECATED));
+      } else {
+         WMLog::GetInstance().LogError(L"Error migrating Quiet Hours settings");
+         TaskDialog(
+            nullptr,
+            nullptr,
+            PROGRAM_NAME,
+            i18n.GetTranslationW("init.error.winmute.title").c_str(),
+            i18n.GetTranslationW("init.error.winmute.migrating-settings-error").c_str(),
+            TDCBF_OK_BUTTON,
+            TD_ERROR_ICON,
+            nullptr);
+      }
    }
    return true;
 }
@@ -336,6 +365,31 @@ bool WMSettings::Init()
       }
    }
 
+   if (hQuietHoursTimesKey_ == nullptr) {
+      DWORD regError = RegCreateKeyExW(
+         HKEY_CURRENT_USER,
+         LX_SYSTEMS_QUIET_HOUR_TIMES_SUBKEY,
+         0,
+         nullptr,
+         0,
+         KEY_READ | KEY_WRITE,
+         nullptr,
+         &hQuietHoursTimesKey_,
+         nullptr);
+      if (regError != ERROR_SUCCESS) {
+         ShowWindowsError(L"RegCreateKeyEx", regError);
+         RegCloseKey(hWifiKey_);
+         RegCloseKey(hSettingsKey_);
+         RegCloseKey(hBluetoothKey_);
+         RegCloseKey(hAudioEndpointsKey_);
+         hSettingsKey_ = nullptr;
+         hWifiKey_ = nullptr;
+         hBluetoothKey_ = nullptr;
+         hAudioEndpointsKey_ = nullptr;
+         return false;
+      }
+   }
+
    MigrateSettings();
 
    return true;
@@ -703,6 +757,136 @@ std::vector<std::wstring> WMSettings::GetBluetoothDevicesW() const
    return devices;
 }
 
+bool WMSettings::StoreQuietHoursTimes(const std::vector<std::pair<DWORD, DWORD>> &times)
+{
+   // Clear all stored keys
+   for (;;) {
+      wchar_t valueName[260] = { 0 };
+      DWORD valueSize = ARRAY_SIZE(valueName);
+      DWORD regError = RegEnumValueW(
+         hQuietHoursTimesKey_,
+         0,
+         valueName,
+         &valueSize,
+         nullptr,
+         nullptr,
+         nullptr,
+         nullptr);
+      if (regError == ERROR_NO_MORE_ITEMS) {
+         break;
+      } else if (regError != ERROR_SUCCESS) {
+         ShowWindowsError(L"RegEnumValue", regError);
+         return false;
+      } else {
+         regError = RegDeleteValue(hQuietHoursTimesKey_, valueName);
+         if (regError != ERROR_SUCCESS) {
+            ShowWindowsError(L"RegDeleteValue", regError);
+            return false;
+         }
+      }
+   }
+
+   for (size_t i = 0; i < times.size(); ++i) {
+      const std::wstring keyStart = L"Start" + std::to_wstring(i);
+      const std::wstring keyEnd = L"End" + std::to_wstring(i);
+      DWORD regError = RegSetValueExW(
+         hQuietHoursTimesKey_,
+         keyStart.c_str(),
+         0,
+         REG_DWORD,
+         reinterpret_cast<const BYTE *>(&times[i].first),
+         static_cast<DWORD>(sizeof(times[i].first)));
+      if (regError != ERROR_SUCCESS) {
+         ShowWindowsError(L"RegSetValueEx", regError);
+         return false;
+      }
+      regError = RegSetValueExW(
+         hQuietHoursTimesKey_,
+         keyEnd.c_str(),
+         0,
+         REG_DWORD,
+         reinterpret_cast<const BYTE *>(&times[i].second),
+         static_cast<DWORD>(sizeof(times[i].second)));
+      if (regError != ERROR_SUCCESS) {
+         ShowWindowsError(L"RegSetValueEx", regError);
+         return false;
+      }
+   }
+   return true;
+}
+
+std::vector<std::pair<DWORD, DWORD>> WMSettings::GetQuietHoursTimes()
+{
+   WMi18n &i18n = WMi18n::GetInstance();
+
+   DWORD numEntries = 0;
+   auto regError = RegQueryInfoKeyW(
+      hQuietHoursTimesKey_,
+      nullptr, nullptr,
+      nullptr, nullptr,
+      nullptr, nullptr,
+      &numEntries, nullptr,
+      nullptr, nullptr,
+      nullptr);
+   if (regError != ERROR_SUCCESS) {
+      ShowWindowsError(L"ShowWindowsError", regError);
+      return {};
+   }
+      
+   if (numEntries % 2 != 0) {
+      WMLog::GetInstance().LogError(
+         L"Corrupted Quiet Hours times in registry: odd number of entries (%d). Resetting QuietHours", numEntries);
+      TaskDialog(
+         nullptr,
+         nullptr,
+         PROGRAM_NAME,
+         i18n.GetTranslationW("init.error.winmute.title").c_str(),
+         i18n.GetTranslationW("init.error.winmute.migrating-settings-error").c_str(),
+         TDCBF_OK_BUTTON,
+         TD_ERROR_ICON,
+         nullptr);
+      StoreQuietHoursTimes({});
+      return {};
+   }
+
+   std::vector<std::pair<DWORD, DWORD>> times;
+   for (DWORD valIdx = 0; valIdx < numEntries; valIdx += 2) {
+      const std::wstring keyStart = L"Start" + std::to_wstring(valIdx);
+      const std::wstring keyEnd = L"End" + std::to_wstring(valIdx);
+
+      std::pair<DWORD, DWORD> timeEntry{};
+      DWORD size{};
+      regError = RegQueryValueExW(
+         hQuietHoursTimesKey_,
+         keyStart.c_str(),
+         0,
+         nullptr,
+         reinterpret_cast<LPBYTE>(&timeEntry.first),
+         &size);
+      if (regError != ERROR_SUCCESS) {
+         WMLog::GetInstance().LogError(
+            L"Failed to read entry \"%s\" while initializing quiet hours",
+            keyStart.c_str());
+         continue;
+      }
+      regError = RegQueryValueExW(
+         hQuietHoursTimesKey_,
+         keyEnd.c_str(),
+         0,
+         nullptr,
+         reinterpret_cast<LPBYTE>(&timeEntry.second),
+         &size);
+      if (regError != ERROR_SUCCESS) {
+         WMLog::GetInstance().LogError(
+            L"Failed to read entry \"%s\" while initializing quiet hours",
+            keyStart.c_str());
+         continue;
+      }
+      times.push_back(std::move(timeEntry));
+   }
+   return times;
+}
+
 
 bool WMSettings::StoreManagedAudioEndpoints(std::vector<std::wstring> &endpoints)
 {
index 1fb919ddd9f2d3929cc47bd53670e67a6dc82a42..be680de98dc76f73bebd3bc238c2d3eb2912f7a5 100644 (file)
@@ -62,8 +62,8 @@ enum class SettingsKey {
    , QUIETHOURS_ENABLE
    , QUIETHOURS_FORCEUNMUTE
    , QUIETHOURS_NOTIFICATIONS
-   , QUIETHOURS_START
-   , QUIETHOURS_END
+   , QUIETHOURS_START_V0_DEPRECATED // Settings v0 to v1. Migrated to Subkey
+   , QUIETHOURS_END_V0_DEPRECATED   // Settings v0 to v1. Migrated to Subkey
    , NOTIFICATIONS_ENABLED
    , LOGGING_ENABLED
    , APP_LANGUAGE
@@ -95,6 +95,9 @@ public:
    bool StoreManagedAudioEndpoints(std::vector<std::wstring> &endpoints);
    std::vector<std::wstring> GetManagedAudioEndpoints() const;
 
+   bool StoreQuietHoursTimes(const std::vector<std::pair<DWORD, DWORD>> &times);
+   std::vector<std::pair<DWORD, DWORD>> GetQuietHoursTimes();
+
    DWORD QueryValue(SettingsKey key) const;
    bool  SetValue(SettingsKey key, DWORD value);
 
@@ -102,10 +105,11 @@ public:
    bool SetValue(SettingsKey key, const std::wstring &value);
 
 private:
-   HKEY hSettingsKey_;
-   HKEY hWifiKey_;
-   HKEY hBluetoothKey_;
-   HKEY hAudioEndpointsKey_;
+   HKEY hSettingsKey_ = nullptr;
+   HKEY hWifiKey_ = nullptr;
+   HKEY hBluetoothKey_ = nullptr;
+   HKEY hAudioEndpointsKey_ = nullptr;
+   HKEY hQuietHoursTimesKey_ = nullptr;
 
    bool MigrateSettings();
    HKEY OpenAutostartKey(REGSAM samDesired);