]> repos.lx-s.de Git - winmute.git/commitdiff
Added BluetoothDetector class
authorAlexander Steinhöfer <kontakt@lx-s.de>
Fri, 29 Jul 2022 13:30:52 +0000 (15:30 +0200)
committerAlexander Steinhöfer <kontakt@lx-s.de>
Fri, 29 Jul 2022 13:30:52 +0000 (15:30 +0200)
WinMute/BluetoothDetector.cpp [new file with mode: 0644]
WinMute/BluetoothDetector.h [new file with mode: 0644]
WinMute/WinMute.cpp
WinMute/WinMute.h
WinMute/WinMute.vcxproj
WinMute/WinMute.vcxproj.filters
WinMute/common.h

diff --git a/WinMute/BluetoothDetector.cpp b/WinMute/BluetoothDetector.cpp
new file mode 100644 (file)
index 0000000..b18f7fb
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ WinMute
+           Copyright (c) 2022, Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the author nor the names of its contributors may
+      be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#include "common.h"
+
+BluetoothDetector::BluetoothDetector() :
+   hNotifyWnd_(NULL),  hBluetoothNotify_(NULL), initialized_(false)
+{
+
+}
+
+BluetoothDetector::~BluetoothDetector()
+{
+   if (initialized_) {
+      UnloadRadioNotifications();
+   }
+}
+
+void BluetoothDetector::UnloadRadioNotifications()
+{
+   for (auto hDevNotify : notificationHandles_) {
+      UnregisterDeviceNotification(hDevNotify);
+   }
+   notificationHandles_.clear();
+}
+
+bool BluetoothDetector::LoadRadioNotifications()
+{
+   bool success = false;
+   notificationHandles_.clear();
+
+   BLUETOOTH_FIND_RADIO_PARAMS bfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
+   HANDLE btHandle;
+   HBLUETOOTH_RADIO_FIND hRadiosFind = BluetoothFindFirstRadio(&bfrp, &btHandle);
+   if (hRadiosFind == nullptr) {
+      PrintWindowsError(L"BluetoothFindFirstRadio");
+      return false;
+   }
+
+   DEV_BROADCAST_HANDLE dbh = { 0 };
+   dbh.dbch_devicetype = DBT_DEVTYP_HANDLE;
+   dbh.dbch_size = sizeof(dbh);
+   dbh.dbch_eventguid = GUID_BLUETOOTH_RADIO_IN_RANGE;
+
+   do {
+      dbh.dbch_handle = btHandle;
+      HDEVNOTIFY devNotify = RegisterDeviceNotification(
+         hNotifyWnd_,
+         &dbh,
+         DEVICE_NOTIFY_WINDOW_HANDLE);
+      CloseHandle(btHandle);
+
+      if (devNotify == NULL) {
+         PrintWindowsError(L"RegisterDeviceNotification", GetLastError());
+      } else {
+         notificationHandles_.push_back(devNotify);
+      }
+   } while (BluetoothFindNextRadio(hRadiosFind, &btHandle));
+   DWORD dwLastError = GetLastError();
+   if (dwLastError != ERROR_NO_MORE_ITEMS) {
+      PrintWindowsError(L"BluetoothFindNextRadio");
+      UnloadRadioNotifications();
+   } else {
+      success = true;
+   }
+
+   BluetoothFindRadioClose(hRadiosFind);
+   return success;
+}
+
+bool BluetoothDetector::Init(HWND hNotifyWnd)
+{
+   if (!initialized_) {
+      hNotifyWnd_ = hNotifyWnd;
+      if (LoadRadioNotifications()) {
+         initialized_ = true;
+      }
+   }
+   return initialized_;
+}
+
+BluetoothDetector::BluetoothStatus BluetoothDetector::GetBluetoothStatus(
+   const UINT message, const WPARAM wParam, const LPARAM lParam)
+{
+   if (message != WM_DEVICECHANGE || wParam != DBT_CUSTOMEVENT || lParam == 0) {
+      return BluetoothStatus::Unknown;
+   }
+
+   const DEV_BROADCAST_HDR *header = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
+   if (header->dbch_devicetype != DBT_DEVTYP_HANDLE) {
+      return BluetoothStatus::Unknown;
+   }
+
+   const DEV_BROADCAST_HANDLE* handle = reinterpret_cast<const DEV_BROADCAST_HANDLE*>(header);
+   if (!IsEqualGUID(handle->dbch_eventguid, GUID_BLUETOOTH_RADIO_IN_RANGE)) {
+      return BluetoothStatus::Unknown;
+   }
+
+   const BTH_RADIO_IN_RANGE *inRangeInfo = reinterpret_cast<const BTH_RADIO_IN_RANGE*>(handle->dbch_data);
+   if (inRangeInfo == nullptr) {
+      return BluetoothStatus::Unknown;
+   }
+
+   if (inRangeInfo->deviceInfo.flags & BDIF_CONNECTED) {
+      return BluetoothStatus::Connected;
+   }
+
+   return BluetoothStatus::Disconnected;
+}
diff --git a/WinMute/BluetoothDetector.h b/WinMute/BluetoothDetector.h
new file mode 100644 (file)
index 0000000..dc7cd06
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ WinMute
+           Copyright (c) 2022, Alexander Steinhoefer
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of the author nor the names of its contributors may
+      be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include "common.h"
+
+/* wParam = Connected = 1 | Disconnected = 0. lParam = Pointer to Device Name */
+constexpr int WM_BTSTATUSCHANGED = WM_USER + 500;
+
+class BluetoothDetector {
+public:
+   enum class BluetoothStatus { Unknown, Connected, Disconnected };
+   BluetoothDetector();
+   ~BluetoothDetector();
+   BluetoothDetector(const WifiDetector&) = delete;
+   BluetoothDetector& operator=(const WifiDetector&) = delete;
+
+   bool Init(HWND hNotifyWnd);
+   void Unload();
+
+   BluetoothStatus GetBluetoothStatus(
+      const UINT message, const WPARAM wParam, const LPARAM lParam);
+
+private:
+   HWND hNotifyWnd_;
+   HDEVNOTIFY hBluetoothNotify_;
+
+   std::vector<HDEVNOTIFY> notificationHandles_;
+
+   bool LoadRadioNotifications();
+   void UnloadRadioNotifications();
+
+   bool initialized_;
+};
index ccf91394b0892c38c19227b79a563064eb677dd4..dfa859737ae0f70a7f4fc9f83fdec42ca424be53 100644 (file)
@@ -277,6 +277,17 @@ bool WinMute::Init()
       return false;
    }
 
+   if (!btDetector_.Init(hWnd_)) {
+      log.Write(_T("Error loading bluetooth detector"));
+      TaskDialog(nullptr, nullptr,
+         PROGRAM_NAME,
+         _T("Bluetooth not available"),
+         _T("Either the Bluetooth service has not been started, ")
+         _T("or your device is not capable of using bluetooth devices. ")
+         _T("This feature will be disabled for this computer"),
+         TDCBF_OK_BUTTON, TD_INFORMATION_ICON, nullptr);
+   }
+
    bool isDarkMode = true;
    IsDarkMode(isDarkMode);
    hTrayIcon_ = LoadIcon(
@@ -461,6 +472,12 @@ LRESULT CALLBACK WinMute::WindowProc(
          settings_.SetValue(SettingsKey::MUTE_ON_LOGOUT, checked);
          break;
       }
+      case ID_TRAYMENU_BLUETOOTH: {
+         bool checked = false;
+         ToggleMenuCheck(ID_TRAYMENU_MUTEONLOGOUT, &checked);
+         
+         break;
+      }
       default:
          break;
       }
@@ -548,6 +565,15 @@ LRESULT CALLBACK WinMute::WindowProc(
       }
       return 0;
    }
+   case WM_DEVICECHANGE: {
+      const auto btStatus = btDetector_.GetBluetoothStatus(msg, wParam, lParam);
+      if (btStatus == BluetoothDetector::BluetoothStatus::Connected) {
+         MessageBox(hWnd, L"CONNECTED!", NULL, 0);
+      } else if (btStatus == BluetoothDetector::BluetoothStatus::Disconnected) {
+         MessageBox(hWnd, L"DIS-CONNECTED!", NULL, 0);
+      }
+      return TRUE;
+   }
    case WM_WIFISTATUSCHANGED:
       if (muteConfig_.muteOnWlan) {
          if (wParam == 1) { // Connected
index 1cac6ca704b1393bfa6b34691eb85eaeb58d745e..a6501efd7a0bc4d623ec28a44e65a9e1a43bb838 100644 (file)
@@ -65,6 +65,7 @@ private:
    WMSettings settings_;
    MuteControl muteCtrl_;
    QuietHoursTimer quietHours_;
+   BluetoothDetector btDetector_;
 
    bool RegisterWindowClass();
    bool InitWindow();
index 929dcd347e9a0ea4168d116922de50ea5c3bb8e7..86b2fc62103410aebac83bc2593880c7316e9341 100644 (file)
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <Manifest>
       <EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="BaseTypes.h" />
+    <ClInclude Include="BluetoothDetector.h" />
     <ClInclude Include="common.h" />
     <ClInclude Include="WiFiDetector.h" />
     <ClInclude Include="WMLog.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="AboutDlg.cpp" />
+    <ClCompile Include="BluetoothDetector.cpp" />
     <ClCompile Include="common.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
index 462786a3f70f68b9631580e6a82aa8d05d714c5b..d9f986edebd002afc5385978649d03c6e046e735 100644 (file)
@@ -54,6 +54,9 @@
     <Filter Include="Source Files\Controllers\WiFi">
       <UniqueIdentifier>{a804b525-296b-455b-a1bc-d8fdbf5a9c3d}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Source Files\Controllers\Bluetooth">
+      <UniqueIdentifier>{63e91d90-aeee-461f-9783-6e1e42eee65b}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="WinAudio.h">
     <ClInclude Include="WiFiDetector.h">
       <Filter>Source Files\Controllers\WiFi</Filter>
     </ClInclude>
+    <ClInclude Include="BluetoothDetector.h">
+      <Filter>Source Files\Controllers\Bluetooth</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="WinMute.rc">
     <ClCompile Include="WifiDetector.cpp">
       <Filter>Source Files\Controllers\WiFi</Filter>
     </ClCompile>
+    <ClCompile Include="BluetoothDetector.cpp">
+      <Filter>Source Files\Controllers\Bluetooth</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
index 0390676ce74f3a9b42044ed5982922dbc887a261..adbe021766e0a034a963ffb5a2f41a6bbff7fc57 100644 (file)
@@ -67,6 +67,10 @@ POSSIBILITY OF SUCH DAMAGE.
 #include <windowsx.h>
 #include <commctrl.h>
 #include <WtsApi32.h>
+#include <dbt.h>
+#include <Bthdef.h>
+#include <Bthsdpdef.h>
+#include <BluetoothAPIs.h>
 #include <tchar.h>
 #include <strsafe.h>
 #include <time.h>
@@ -89,6 +93,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "WinAudio.h"
 #include "MuteControl.h"
 #include "WiFiDetector.h"
+#include "BluetoothDetector.h"
 #include "QuietHoursTimer.h"
 #include "WinMute.h"
 #include "VersionHelper.h"