--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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_;
+};
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(
settings_.SetValue(SettingsKey::MUTE_ON_LOGOUT, checked);
break;
}
+ case ID_TRAYMENU_BLUETOOTH: {
+ bool checked = false;
+ ToggleMenuCheck(ID_TRAYMENU_MUTEONLOGOUT, &checked);
+
+ break;
+ }
default:
break;
}
}
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
WMSettings settings_;
MuteControl muteCtrl_;
QuietHoursTimer quietHours_;
+ BluetoothDetector btDetector_;
bool RegisterWindowClass();
bool InitWindow();
<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>
<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
#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>
#include "WinAudio.h"
#include "MuteControl.h"
#include "WiFiDetector.h"
+#include "BluetoothDetector.h"
#include "QuietHoursTimer.h"
#include "WinMute.h"
#include "VersionHelper.h"