]> repos.lx-s.de Git - winmute.git/commitdiff
Made endpoint handling more robust
authorlx-s <lx-s@users.noreply.github.com>
Sat, 7 Mar 2026 15:49:00 +0000 (16:49 +0100)
committerlx-s <lx-s@users.noreply.github.com>
Sat, 7 Mar 2026 15:49:00 +0000 (16:49 +0100)
WinMute/MuteControl.cpp
WinMute/MuteControl.h
WinMute/VistaAudio.cpp
WinMute/VistaAudioSessionEvents.cpp
WinMute/WinAudio.h
WinMute/WinMute.cpp
WinMute/WinMute.h
WinMute/common.h

index 19cff60d8aebdd45c533cb4fb292d1067999af3a..573c47280883da4028e758d3705780934cf24f7f 100644 (file)
@@ -38,9 +38,10 @@ extern HINSTANCE hglobInstance;
 static const int BLUETOOTH_RECONNECT_UNMUTE_DELAY = 5000; // Milliseconds
 static const int MUTE_DELAY_MAGIC_VALUE = 0x198604;
 
-static const wchar_t* MUTECONTROL_CLASS_NAME = L"WinMuteMuteControl";
+static const wchar_t *MUTECONTROL_CLASS_NAME = L"WinMuteMuteControl";
 
-enum MuteType {
+enum MuteType
+{
    // With restore
    MuteTypeWorkstationLock = 0,
    MuteTypeRemoteSession,
@@ -56,20 +57,32 @@ enum MuteType {
 
 void DelayedMuteTimerProc(HWND hWnd, UINT, UINT_PTR, DWORD)
 {
-   MuteControl *muteCtrl = reinterpret_cast<MuteControl*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
-   if (muteCtrl != nullptr) {
+   MuteControl *muteCtrl = reinterpret_cast<MuteControl *>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
+   if (muteCtrl != nullptr)
+   {
       muteCtrl->MuteDelayed(MUTE_DELAY_MAGIC_VALUE);
    }
 }
 
+static void CALLBACK BluetoothUnmuteTimerProc(HWND hWnd, UINT, UINT_PTR id, DWORD)
+{
+   KillTimer(hWnd, id);
+   MuteControl *muteCtrl = reinterpret_cast<MuteControl *>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
+   if (muteCtrl != nullptr)
+   {
+      muteCtrl->CompleteVolumeRestore();
+   }
+}
+
 static LRESULT CALLBACK MuteControlWndProc(
-   HWND hWnd,
-   UINT msg,
-   WPARAM wParam,
-   LPARAM lParam)
+    HWND hWnd,
+    UINT msg,
+    WPARAM wParam,
+    LPARAM lParam)
 {
-   auto wm = reinterpret_cast<MuteControl*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
-   switch (msg) {
+   auto wm = reinterpret_cast<MuteControl *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+   switch (msg)
+   {
    case WM_NCCREATE:
    {
       LPCREATESTRUCTW cs = reinterpret_cast<LPCREATESTRUCTW>(lParam);
@@ -81,8 +94,8 @@ static LRESULT CALLBACK MuteControlWndProc(
       break;
    }
    return (wm)
-      ? wm->WindowProc(hWnd, msg, wParam, lParam)
-      : DefWindowProcW(hWnd, msg, wParam, lParam);
+              ? wm->WindowProc(hWnd, msg, wParam, lParam)
+              : DefWindowProcW(hWnd, msg, wParam, lParam);
 }
 
 MuteControl::MuteControl()
@@ -90,7 +103,8 @@ MuteControl::MuteControl()
    MuteConfig initMuteConf;
    initMuteConf.active = false;
    initMuteConf.shouldMute = false;
-   for (int i = 0; i < MuteTypeCount; ++i) {
+   for (int i = 0; i < MuteTypeCount; ++i)
+   {
       muteConfig_.push_back(initMuteConf);
    }
 }
@@ -103,32 +117,35 @@ MuteControl::~MuteControl()
 
 bool MuteControl::Init(HWND hParent, const TrayIcon *trayIcon)
 {
-   WNDCLASSEXW wndClass{ 0 };
+   WNDCLASSEXW wndClass{0};
    wndClass.cbSize = sizeof(wndClass);
    wndClass.lpfnWndProc = MuteControlWndProc;
    wndClass.hInstance = hglobInstance;
    wndClass.lpszClassName = MUTECONTROL_CLASS_NAME;
-   if (!RegisterClassExW(&wndClass)) {
+   if (!RegisterClassExW(&wndClass))
+   {
       WMLog::GetInstance().LogWinError(L"RegisterClassEx");
       return false;
    }
    hMuteCtrlWnd_ = CreateWindowEx(
-      WS_EX_TOOLWINDOW,
-      MUTECONTROL_CLASS_NAME,
-      L"",
-      0,
-      0, 0, 0, 0,
-      nullptr,
-      nullptr,
-      hglobInstance,
-      this);
-   if (hMuteCtrlWnd_ == nullptr) {
+       WS_EX_TOOLWINDOW,
+       MUTECONTROL_CLASS_NAME,
+       L"",
+       0,
+       0, 0, 0, 0,
+       nullptr,
+       nullptr,
+       hglobInstance,
+       this);
+   if (hMuteCtrlWnd_ == nullptr)
+   {
       WMLog::GetInstance().LogWinError(L"CreateWindowEx");
       UnregisterClassW(MUTECONTROL_CLASS_NAME, hglobInstance);
       return false;
    }
    winAudio_ = std::make_unique<VistaAudio>();
-   if (!winAudio_->Init(hParent)) {
+   if (!winAudio_->Init(hParent))
+   {
       DestroyWindow(hMuteCtrlWnd_);
       UnregisterClassW(MUTECONTROL_CLASS_NAME, hglobInstance);
       return false;
@@ -139,10 +156,10 @@ bool MuteControl::Init(HWND hParent, const TrayIcon *trayIcon)
 }
 
 LRESULT CALLBACK MuteControl::WindowProc(
-   HWND hWnd,
-   UINT msg,
-   WPARAM wParam,
-   LPARAM lParam)
+    HWND hWnd,
+    UINT msg,
+    WPARAM wParam,
+    LPARAM lParam)
 {
    return DefWindowProc(hWnd, msg, wParam, lParam);
 }
@@ -156,24 +173,28 @@ void MuteControl::SetMute(bool mute)
 void MuteControl::SaveMuteStatus()
 {
    const bool alreadySaved = std::any_of(
-      muteConfig_.begin(),
-      muteConfig_.end(),
-      [](const MuteConfig &conf) {
-         return conf.shouldMute && conf.active;
-      }
-   );
-
-   if (alreadySaved) {
+       muteConfig_.begin(),
+       muteConfig_.end(),
+       [](const MuteConfig &conf)
+       {
+          return conf.shouldMute && conf.active;
+       });
+
+   if (alreadySaved)
+   {
       WMLog::GetInstance().LogInfo(L"Muting event already active. Skipping status save");
-   } else {
+   }
+   else
+   {
       WMLog::GetInstance().LogInfo(L"Saving mute status");
       winAudio_->SaveMuteStatus();
    }
 }
 
-void MuteControl::ShowNotification(const std::wstring& title, const std::wstring& text)
+void MuteControl::ShowNotification(const std::wstring &title, const std::wstring &text)
 {
-   if (notificationsEnabled_ && trayIcon_ != nullptr) {
+   if (notificationsEnabled_ && trayIcon_ != nullptr)
+   {
       trayIcon_->ShowPopup(title, text);
    }
 }
@@ -185,7 +206,8 @@ void MuteControl::SetNotifications(bool enable)
 
 void MuteControl::MuteDelayed(int magic)
 {
-   if (magic != MUTE_DELAY_MAGIC_VALUE || delayedMuteTimerId_ == 0) {
+   if (magic != MUTE_DELAY_MAGIC_VALUE || delayedMuteTimerId_ == 0)
+   {
       return;
    }
    WMLog::GetInstance().LogInfo(L"Muting workstation after delay");
@@ -197,11 +219,12 @@ void MuteControl::MuteDelayed(int magic)
 bool MuteControl::StartDelayedMute()
 {
    delayedMuteTimerId_ = SetTimer(
-      hMuteCtrlWnd_,
-      delayedMuteTimerId_,
-      muteDelaySeconds_ * 1000,
-      DelayedMuteTimerProc);
-   if (delayedMuteTimerId_ == 0) {
+       hMuteCtrlWnd_,
+       delayedMuteTimerId_,
+       muteDelaySeconds_ * 1000,
+       DelayedMuteTimerProc);
+   if (delayedMuteTimerId_ == 0)
+   {
       WMLog::GetInstance().LogWinError(L"SetTimer", GetLastError());
    }
    return delayedMuteTimerId_ != 0;
@@ -209,38 +232,65 @@ bool MuteControl::StartDelayedMute()
 
 void MuteControl::RestoreVolume(bool withDelay)
 {
-   WMLog& log = WMLog::GetInstance();
-   if (!restoreVolume_) {
+   WMLog &log = WMLog::GetInstance();
+   if (!restoreVolume_)
+   {
       log.LogInfo(L"Volume Restore has been disabled");
       return;
    }
    const bool restore = !std::any_of(
-      muteConfig_.begin(),
-      muteConfig_.end(),
-      [](const MuteConfig &conf) {
-         return conf.shouldMute && conf.active;
-      }
-   );
-   if (!restore) {
+       muteConfig_.begin(),
+       muteConfig_.end(),
+       [](const MuteConfig &conf)
+       {
+          return conf.shouldMute && conf.active;
+       });
+   if (!restore)
+   {
       log.LogInfo(L"Skipping restore since other mute event is currently active");
-   } else if (delayedMuteTimerId_ != 0) {
+   }
+   else if (delayedMuteTimerId_ != 0)
+   {
       KillTimer(hMuteCtrlWnd_, delayedMuteTimerId_);
       delayedMuteTimerId_ = 0;
       log.LogInfo(L"Skipping restore, since delayed mute was not triggered yet");
-   } else {
-      log.LogInfo(L"Restoring previous mute state");
+   }
+   else if (withDelay)
+   {
+      log.LogInfo(L"Restoring previous mute state after Bluetooth delay");
       ShowNotification(
-         WMi18n::GetInstance().GetTranslationW("popup.volume-restored.title"),
-         WMi18n::GetInstance().GetTranslationW("popup.volume-restored.text"));
-      if (withDelay) {
-         Sleep(BLUETOOTH_RECONNECT_UNMUTE_DELAY);
-      }
-      winAudio_->RestoreMuteStatus();
-      if (mediaWasPlaying_ && mediaConfig_.tryResume) {
-         MediaPlaybackController::TryPlayCurrentSession();
-         mediaWasPlaying_ = false;
+          WMi18n::GetInstance().GetTranslationW("popup.volume-restored.title"),
+          WMi18n::GetInstance().GetTranslationW("popup.volume-restored.text"));
+      bluetoothUnmuteTimerId_ = SetTimer(
+          hMuteCtrlWnd_,
+          bluetoothUnmuteTimerId_,
+          BLUETOOTH_RECONNECT_UNMUTE_DELAY,
+          BluetoothUnmuteTimerProc);
+      if (bluetoothUnmuteTimerId_ == 0)
+      {
+         log.LogWinError(L"SetTimer (Bluetooth unmute delay)");
+         CompleteVolumeRestore(); // fall back to immediate restore
       }
    }
+   else
+   {
+      log.LogInfo(L"Restoring previous mute state");
+      ShowNotification(
+          WMi18n::GetInstance().GetTranslationW("popup.volume-restored.title"),
+          WMi18n::GetInstance().GetTranslationW("popup.volume-restored.text"));
+      CompleteVolumeRestore();
+   }
+}
+
+void MuteControl::CompleteVolumeRestore()
+{
+   bluetoothUnmuteTimerId_ = 0;
+   winAudio_->RestoreMuteStatus();
+   if (mediaWasPlaying_ && mediaConfig_.tryResume)
+   {
+      MediaPlaybackController::TryPlayCurrentSession();
+      mediaWasPlaying_ = false;
+   }
 }
 
 void MuteControl::SetRestoreVolume(bool enable)
@@ -342,35 +392,45 @@ void MuteControl::MuteNow()
 {
    WMLog::GetInstance().LogInfo(L"Muting workstation");
    ShowNotification(
-      WMi18n::GetInstance().GetTranslationW("popup.muting-workstation.title"),
-      WMi18n::GetInstance().GetTranslationW("popup.muting-workstation.text"));
+       WMi18n::GetInstance().GetTranslationW("popup.muting-workstation.title"),
+       WMi18n::GetInstance().GetTranslationW("popup.muting-workstation.text"));
    winAudio_->SetMute(true);
-   if (mediaConfig_.tryPause) {
+   if (mediaConfig_.tryPause)
+   {
       bool did_pause = false;
-      if (MediaPlaybackController::TryPauseCurrentSession(did_pause)) {
+      if (MediaPlaybackController::TryPauseCurrentSession(did_pause))
+      {
          mediaWasPlaying_ = did_pause;
       }
    }
 }
 
-
 void MuteControl::NotifyRestoreCondition(int type, bool active, bool withDelay)
 {
-   if (active) {
+   if (active)
+   {
       SaveMuteStatus();
       muteConfig_[type].active = active;
-      if (muteConfig_[type].shouldMute) {
-         if (muteDelaySeconds_ == 0) {
+      if (muteConfig_[type].shouldMute)
+      {
+         if (muteDelaySeconds_ == 0)
+         {
             MuteNow();
-         } else {
+         }
+         else
+         {
             WMLog::GetInstance().LogInfo(L"Starting delayed mute timer...");
             StartDelayedMute();
          }
       }
-   } else {
-      if (muteConfig_[type].active) {
+   }
+   else
+   {
+      if (muteConfig_[type].active)
+      {
          muteConfig_[type].active = false;
-         if (muteConfig_[type].shouldMute) {
+         if (muteConfig_[type].shouldMute)
+         {
             RestoreVolume(withDelay);
          }
       }
@@ -380,22 +440,23 @@ void MuteControl::NotifyRestoreCondition(int type, bool active, bool withDelay)
 void MuteControl::NotifyWorkstationLock(bool active)
 {
    WMLog::GetInstance().LogInfo(L"Mute Event: Workstation Lock %s",
-                              active ? L"start" : L"stop");
+                                active ? L"start" : L"stop");
    NotifyRestoreCondition(MuteTypeWorkstationLock, active);
 }
 
 void MuteControl::NotifyRemoteSession(bool active)
 {
    WMLog::GetInstance().LogInfo(L"Mute Event: Remote Session %s",
-                              active ? L"start" : L"stop");
+                                active ? L"start" : L"stop");
    NotifyRestoreCondition(MuteTypeRemoteSession, active);
 }
 
 void MuteControl::NotifyDisplayStandby(bool active)
 {
-   if (displayWasOffOnce_ || active) {
+   if (displayWasOffOnce_ || active)
+   {
       WMLog::GetInstance().LogInfo(L"Mute Event: Display Standby %s",
-                                 active ? L"start" : L"stop");
+                                   active ? L"start" : L"stop");
       NotifyRestoreCondition(MuteTypeDisplayStandby, active);
       displayWasOffOnce_ = true;
    }
@@ -404,15 +465,16 @@ void MuteControl::NotifyDisplayStandby(bool active)
 void MuteControl::NotifyBluetoothConnected(bool connected)
 {
    WMLog::GetInstance().LogInfo(
-      L"Mute Event: Bluetooth audio device %s",
-      connected ? L"connected" : L"disconnected");
+       L"Mute Event: Bluetooth audio device %s",
+       connected ? L"connected" : L"disconnected");
    NotifyRestoreCondition(MuteTypeBluetoothDisconnect, !connected, true);
 }
 
 void MuteControl::NotifyLogout()
 {
    WMLog::GetInstance().LogInfo(L"Mute Event: Logout start");
-   if (muteConfig_[MuteTypeLogout].shouldMute) {
+   if (muteConfig_[MuteTypeLogout].shouldMute)
+   {
       winAudio_->SetMute(true);
    }
 }
@@ -420,7 +482,8 @@ void MuteControl::NotifyLogout()
 void MuteControl::NotifySuspend(bool /*active*/)
 {
    WMLog::GetInstance().LogInfo(L"Mute Event: Suspend start");
-   if (muteConfig_[MuteTypeSuspend].shouldMute) {
+   if (muteConfig_[MuteTypeSuspend].shouldMute)
+   {
       winAudio_->SetMute(true);
    }
 }
@@ -428,27 +491,31 @@ void MuteControl::NotifySuspend(bool /*active*/)
 void MuteControl::NotifyShutdown()
 {
    WMLog::GetInstance().LogInfo(L"Mute Event: Shutdown start");
-   if (muteConfig_[MuteTypeShutdown].shouldMute) {
+   if (muteConfig_[MuteTypeShutdown].shouldMute)
+   {
       winAudio_->SetMute(true);
    }
 }
 
 void MuteControl::NotifyQuietHours(bool active)
 {
-   if (active) {
+   if (active)
+   {
       SaveMuteStatus();
       WMLog::GetInstance().LogInfo(L"Mute Event: Quiet Hours startet");
       winAudio_->SaveMuteStatus();
       winAudio_->SetMute(true);
-   } else {
+   }
+   else
+   {
       WMLog::GetInstance().LogInfo(L"Mute Event: Quiet Hours ended");
       RestoreVolume();
    }
 }
 
 void MuteControl::SetManagedEndpoints(
-   const std::vector<std::wstring>& endpoints,
-   bool isAllowList)
+    const std::vector<std::wstring> &endpoints,
+    bool isAllowList)
 {
    winAudio_->MuteSpecificEndpoints(true);
    winAudio_->SetManagedEndpoints(endpoints, isAllowList);
index 63eb7c4fe12fde9c17ad8179619ae796887f7f1a..3127eb9da79474d29eaff52ba8f281dea0867503 100644 (file)
@@ -95,6 +95,7 @@ public:
 
    // Should only be called internally
    void MuteDelayed(int magic);
+   void CompleteVolumeRestore();
 private:
    struct MuteConfig {
       bool shouldMute;
@@ -110,6 +111,7 @@ private:
    bool mediaWasPlaying_ = false;
    int muteDelaySeconds_ = 0;
    UINT_PTR delayedMuteTimerId_ = 0;
+   UINT_PTR bluetoothUnmuteTimerId_ = 0;
    std::unique_ptr<WinAudio> winAudio_;
    HWND hMuteCtrlWnd_ = nullptr;
 
index 40e649f561db773deafc15a5a3bb421b74f18cdf..2db0e32cd5257a6da9d5af020f1f344f9cc8e733 100644 (file)
@@ -137,9 +137,10 @@ bool VistaAudio::LoadAllEndpoints()
       endpoints_.push_back(std::move(ep));
    }
 
-exit_error:
-
    return true;
+
+exit_error:
+   return false;
 }
 
 bool VistaAudio::Init(HWND hParent)
@@ -147,7 +148,6 @@ bool VistaAudio::Init(HWND hParent)
    WMLog& log = WMLog::GetInstance();
 
    hParent_ = hParent;
-   reInit_ = false;
 
    if (FAILED(deviceEnumerator_.CoCreateInstance(
          __uuidof(MMDeviceEnumerator),
@@ -183,37 +183,39 @@ void VistaAudio::ShouldReInit()
    reInit_ = true;
 }
 
+void VistaAudio::OnAudioServiceShutdown()
+{
+   PostMessageW(hParent_, WM_WINMUTE_AUDIO_SERVICE_SHUTDOWN, 0, 0);
+}
+
 bool VistaAudio::CheckForReInit()
 {
-   bool ok = true;
-   if (reInit_) {
+   if (reInit_.exchange(false)) {
       Uninit();
-      ok = Init(hParent_);
+      return Init(hParent_);
    }
-   return ok;
+   return true;
 }
 
 bool VistaAudio::AllEndpointsMuted()
 {
-   bool allMuted = true;
    WMLog& log = WMLog::GetInstance();
 
-   if (CheckForReInit()) {
-      for (auto& e : endpoints_) {
-         BOOL isMuted = FALSE;
-         if (FAILED(e->endpointVolume->GetMute(&isMuted))) {
-            log.LogError(
-               L"Failed to get mute status for \"%s\"",
-               e->deviceName.c_str());
-            allMuted = false;
-            break;
-         } else if (isMuted == FALSE) {
-            allMuted = false;
-            break;
-         }
+   if (!CheckForReInit()) {
+      return false;
+   }
+   for (auto& e : endpoints_) {
+      BOOL isMuted = FALSE;
+      if (FAILED(e->endpointVolume->GetMute(&isMuted))) {
+         log.LogError(
+            L"Failed to get mute status for \"%s\"",
+            e->deviceName.c_str());
+         return false;
+      } else if (isMuted == FALSE) {
+         return false;
       }
    }
-   return allMuted;
+   return true;
 }
 
 bool VistaAudio::SaveMuteStatus()
index 4b40b760f14c00074bf47e2e90a140722c7cb7ce..ee3b11254e8a01e6f2b2d87345afd124c04e6b0a 100644 (file)
@@ -131,18 +131,9 @@ HRESULT STDMETHODCALLTYPE VistaAudioSessionEvents::OnSessionDisconnected(
    case DisconnectReasonSessionDisconnected:
       notifyParent_->ShouldReInit();
       break;
-   case DisconnectReasonServerShutdown: {
-      WMi18n &i18n = WMi18n::GetInstance();
-      TaskDialog(nullptr,
-         nullptr,
-         PROGRAM_NAME,
-         i18n.GetTranslationW("general.error.audio-service-shutdown.title").c_str(),
-         i18n.GetTranslationW("general.error.audio-service-shutdown.text").c_str(),
-         TDCBF_OK_BUTTON,
-         TD_WARNING_ICON,
-         nullptr);
+   case DisconnectReasonServerShutdown:
+      notifyParent_->OnAudioServiceShutdown();
       break;
-   }
    case DisconnectReasonSessionLogoff:
       break;
    case DisconnectReasonExclusiveModeOverride:
index 4a544376e45ce22c9473e458c2ae11ed6ef5cc8b..82a75720b21ae38ed264f41abead54d1f7dbade4 100644 (file)
@@ -42,6 +42,7 @@ class WinAudio {
 public:
    virtual bool Init(HWND hParent) = 0;
    virtual void ShouldReInit() = 0;
+   virtual void OnAudioServiceShutdown() = 0;
    virtual bool AllEndpointsMuted() = 0;
    virtual bool SaveMuteStatus() = 0;
    virtual bool RestoreMuteStatus() = 0;
@@ -74,6 +75,7 @@ public:
 
    bool Init(HWND hParent) override;
    void ShouldReInit() override;
+   void OnAudioServiceShutdown() override;
    bool AllEndpointsMuted() override;
    bool SaveMuteStatus() override;
    bool RestoreMuteStatus() override;
@@ -95,7 +97,7 @@ private:
    CComPtr<MMNotificationClient> mmnAudioEvents_;
    CComPtr<IMMDeviceEnumerator> deviceEnumerator_;
 
-   bool reInit_;
+   std::atomic<bool> reInit_;
    bool muteSpecificEndpoints_;
    bool muteSpecificEndpointsAllowList_;
    HWND hParent_;
index ea74ac42cb6aa8c80a3e5342af8c72d04019286e..8ebb4cf2da6df022278638828e156aae8add18f7 100644 (file)
@@ -618,6 +618,16 @@ LRESULT WinMute::OnQuietHours(HWND, UINT msg, WPARAM, LPARAM)
    return 0;
 }
 
+LRESULT WinMute::OnAudioServiceShutdown(HWND hWnd, WPARAM, LPARAM)
+{
+   TaskDialog(
+      hWnd, hglobInstance, PROGRAM_NAME,
+      i18n_.GetTranslationW("general.error.audio-service-shutdown.title").c_str(),
+      i18n_.GetTranslationW("general.error.audio-service-shutdown.text").c_str(),
+      TDCBF_OK_BUTTON, TD_WARNING_ICON, nullptr);
+   return 0;
+}
+
 LRESULT WinMute::OnDeviceChange(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
 {
    if (muteConfig_.muteOnBluetooth) {
@@ -706,6 +716,8 @@ LRESULT CALLBACK WinMute::WindowProc(
    case WM_WINMUTE_QUIETHOURS_START: // fall through
    case WM_WINMUTE_QUIETHOURS_END:
       return OnQuietHours(hWnd, msg, wParam, lParam);
+   case WM_WINMUTE_AUDIO_SERVICE_SHUTDOWN:
+      return OnAudioServiceShutdown(hWnd, wParam, lParam);
    case WM_DEVICECHANGE:
       return OnDeviceChange(hWnd, msg, wParam, lParam);
    case WM_WIFISTATUSCHANGED:
index f24dce2a1659036c8bab69073d3ee825704b0e0c..c1f9eb3cd111c133c223e4e17e0b069533c49cb3 100644 (file)
@@ -99,4 +99,5 @@ private:
    
    LRESULT OnDeviceChange(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT OnQuietHours(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+   LRESULT OnAudioServiceShutdown(HWND hWnd, WPARAM wParam, LPARAM lParam);
 };
index 28caf5d4930125a8e7993ac458c00a479b0954a4..d766ff2fbac65444f03be736af68ff4f735d64e2 100644 (file)
@@ -137,3 +137,4 @@ static const wchar_t *LOG_FILE_NAME = L"WinMute.log";
 constexpr int WM_SAVESETTINGS = WM_USER + 300;
 constexpr int WM_WINMUTE_UPDATE_POPUP = WM_USER + 301;
 constexpr int WM_LOG_UPDATED = WM_USER + 302;
+constexpr int WM_WINMUTE_AUDIO_SERVICE_SHUTDOWN = WM_USER + 303;