From: Alexander Steinhöfer Date: Fri, 29 Jul 2022 13:30:52 +0000 (+0200) Subject: Added BluetoothDetector class X-Git-Tag: 2.1.0.0~15 X-Git-Url: https://repos.lx-s.de/gitweb/?a=commitdiff_plain;h=7cd427129108dad171ca141f58c67c6312f40b01;p=winmute.git Added BluetoothDetector class --- diff --git a/WinMute/BluetoothDetector.cpp b/WinMute/BluetoothDetector.cpp new file mode 100644 index 0000000..b18f7fb --- /dev/null +++ b/WinMute/BluetoothDetector.cpp @@ -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(lParam); + if (header->dbch_devicetype != DBT_DEVTYP_HANDLE) { + return BluetoothStatus::Unknown; + } + + const DEV_BROADCAST_HANDLE* handle = reinterpret_cast(header); + if (!IsEqualGUID(handle->dbch_eventguid, GUID_BLUETOOTH_RADIO_IN_RANGE)) { + return BluetoothStatus::Unknown; + } + + const BTH_RADIO_IN_RANGE *inRangeInfo = reinterpret_cast(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 index 0000000..dc7cd06 --- /dev/null +++ b/WinMute/BluetoothDetector.h @@ -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 notificationHandles_; + + bool LoadRadioNotifications(); + void UnloadRadioNotifications(); + + bool initialized_; +}; diff --git a/WinMute/WinMute.cpp b/WinMute/WinMute.cpp index ccf9139..dfa8597 100644 --- a/WinMute/WinMute.cpp +++ b/WinMute/WinMute.cpp @@ -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 diff --git a/WinMute/WinMute.h b/WinMute/WinMute.h index 1cac6ca..a6501ef 100644 --- a/WinMute/WinMute.h +++ b/WinMute/WinMute.h @@ -65,6 +65,7 @@ private: WMSettings settings_; MuteControl muteCtrl_; QuietHoursTimer quietHours_; + BluetoothDetector btDetector_; bool RegisterWindowClass(); bool InitWindow(); diff --git a/WinMute/WinMute.vcxproj b/WinMute/WinMute.vcxproj index 929dcd3..86b2fc6 100644 --- a/WinMute/WinMute.vcxproj +++ b/WinMute/WinMute.vcxproj @@ -110,7 +110,7 @@ Windows true - strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies) + strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies) PerMonitorHighDPIAware @@ -136,7 +136,7 @@ true true true - strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies) + strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies) PerMonitorHighDPIAware @@ -157,7 +157,7 @@ Windows true - strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies) + strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies) PerMonitorHighDPIAware @@ -183,7 +183,7 @@ true true true - strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Version.lib;%(AdditionalDependencies) + strsafe.lib;comctl32.lib;WtsApi32.lib;Winmm.lib;UxTheme.lib;comsuppwd.lib;Wlanapi.lib;Bthprops.lib;Version.lib;%(AdditionalDependencies) PerMonitorHighDPIAware @@ -191,6 +191,7 @@ + @@ -217,6 +218,7 @@ + Create Create diff --git a/WinMute/WinMute.vcxproj.filters b/WinMute/WinMute.vcxproj.filters index 462786a..d9f986e 100644 --- a/WinMute/WinMute.vcxproj.filters +++ b/WinMute/WinMute.vcxproj.filters @@ -54,6 +54,9 @@ {a804b525-296b-455b-a1bc-d8fdbf5a9c3d} + + {63e91d90-aeee-461f-9783-6e1e42eee65b} + @@ -101,6 +104,9 @@ Source Files\Controllers\WiFi + + Source Files\Controllers\Bluetooth + @@ -182,5 +188,8 @@ Source Files\Controllers\WiFi + + Source Files\Controllers\Bluetooth + \ No newline at end of file diff --git a/WinMute/common.h b/WinMute/common.h index 0390676..adbe021 100644 --- a/WinMute/common.h +++ b/WinMute/common.h @@ -67,6 +67,10 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include +#include +#include #include #include #include @@ -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"