From e035c388f7aa8c8b04cda94cd0f339ae28f2d61d Mon Sep 17 00:00:00 2001 From: Bunz <66bunz@gmail.com> Date: Tue, 30 Apr 2024 21:38:06 +0200 Subject: [PATCH] Update plugin 0.0.8 --- Bluetooth-Example-Skin/Example.ini | Bin 10016 -> 10082 bytes Bluetooth-Example-Skin/Example.lua | 14 +++-- README.md | 6 +- docs/README.md | 6 +- docs/bangs.md | 4 +- docs/options.md | 6 +- docs/section-variables.md | 2 +- src/BluetoothPlugin.rc | 4 +- src/Plugin.cpp | 88 ++++++++++++++++++++--------- 9 files changed, 86 insertions(+), 44 deletions(-) diff --git a/Bluetooth-Example-Skin/Example.ini b/Bluetooth-Example-Skin/Example.ini index 79cabbfb63db819106df67f9b2f7d7ad7ad5de4b..d75ad50a7588778477bf56c61abfa11e0070bd8a 100644 GIT binary patch delta 92 zcmZ4B_sDO<5k^Lf%|{u7nRp!;Qh>0CA(f$+p?LCrCQ&qzKqm3cVk{mkK=tt)S0yL& bu}W`15k^My%|{u7nKmb|xUm4)%Q>z}PQJ&Zw0Vw_8WWiDNJR|Hm@J|01pp3w B66OE^ diff --git a/Bluetooth-Example-Skin/Example.lua b/Bluetooth-Example-Skin/Example.lua index 302c4e1..11d59a7 100644 --- a/Bluetooth-Example-Skin/Example.lua +++ b/Bluetooth-Example-Skin/Example.lua @@ -88,10 +88,13 @@ function _Populate(PageDevice1, PageDevice2) local Device1Remembered = Device1[4] SKIN:Bang("!SetVariable", "Device1Remembered", Device1Remembered) SKIN:Bang("!WriteKeyValue", "Variables", "Device1Remembered", string.format('%s', Device1Remembered), "Example.ini") - local Device1LastSeen = Device1[5] + local Device1Address = Device1[5] + SKIN:Bang("!SetVariable", "Device1Address", Device1Address) + SKIN:Bang("!WriteKeyValue", "Variables", "Device1Address", string.format('%s', Device1Address), "Example.ini") + local Device1LastSeen = Device1[6] SKIN:Bang("!SetVariable", "Device1LastSeen", Device1LastSeen) SKIN:Bang("!WriteKeyValue", "Variables", "Device1LastSeen", string.format('%s', Device1LastSeen), "Example.ini") - local Device1LastUsed = Device1[6] + local Device1LastUsed = Device1[7] SKIN:Bang("!SetVariable", "Device1LastUsed", Device1LastUsed) SKIN:Bang("!WriteKeyValue", "Variables", "Device1LastUsed", string.format('%s', Device1LastUsed), "Example.ini") @@ -109,10 +112,13 @@ function _Populate(PageDevice1, PageDevice2) local Device2Remembered = Device2[4] SKIN:Bang("!SetVariable", "Device2Remembered", Device2Remembered) SKIN:Bang("!WriteKeyValue", "Variables", "Device2Remembered", string.format('%s', Device2Remembered), "Example.ini") - local Device2LastSeen = Device2[5] + local Device2Address = Device2[5] + SKIN:Bang("!SetVariable", "Device2Address", Device2Address) + SKIN:Bang("!WriteKeyValue", "Variables", "Device2Address", string.format('%s', Device2Address), "Example.ini") + local Device2LastSeen = Device2[6] SKIN:Bang("!SetVariable", "Device2LastSeen", Device2LastSeen) SKIN:Bang("!WriteKeyValue", "Variables", "Device2LastSeen", string.format('%s', Device2LastSeen), "Example.ini") - local Device2LastUsed = Device2[6] + local Device2LastUsed = Device2[7] SKIN:Bang("!SetVariable", "Device2LastUsed", Device2LastUsed) SKIN:Bang("!WriteKeyValue", "Variables", "Device2LastUsed", string.format('%s', Device2LastUsed), "Example.ini") end diff --git a/README.md b/README.md index 88329bc..2e9aefc 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Else, you can download the zip package from the latest [release](https://github. ### Requirements +_TODO_ + ## Documentation @@ -25,7 +27,7 @@ The plugin at every update, is going to scan for Bluetooth devices, and update t The formatted string is going to be in the following format: ```plaintext -device_name|connected[0,1]|Authenticated[0,1]|Remembered[0,1]|datetime_last_seen|datetime_last_used; +device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used; ``` This is an example of how you can use the plugin in a skin: @@ -47,7 +49,7 @@ UpdateDivider=-1 function Refresh() local DevicesString = SKIN:ReplaceVariables('[&BluetoothMeasure:AvailableDevices()]') -- DevicesString = Formatted string of all devices - -- ("device_name|connected[0,1]|Authenticated[0,1]|Remembered[0,1]|datetime_last_seen|datetime_last_used;") + -- ("device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used;") -- Do something with the devices list -- See example skin for an example diff --git a/docs/README.md b/docs/README.md index fb96b35..0e17826 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,7 +25,7 @@ The plugin at every update, is going to scan for Bluetooth devices, and update t The formatted string is going to be in the following format: ```plaintext -device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|datetime_last_seen|datetime_last_used; +device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used; ``` This is an example of how you can use the plugin in a skin: @@ -34,7 +34,7 @@ This is an example of how you can use the plugin in a skin: [Bluetooth] Measure=Plugin Plugin=Bluetooth -UpdateDivider=10 ; Keep a relatively high value, to avoid spamming the plugin with update requests that cannot terminate +UpdateDivider=20 ; Keep a relatively high value, to avoid spamming the plugin with update requests that cannot terminate DevicesUpdatedAction=[!CommandMeasure LuaScript "Refresh()"] [LuaScript] @@ -47,7 +47,7 @@ UpdateDivider=-1 function Refresh() local DevicesString = SKIN:ReplaceVariables('[&BluetoothMeasure:AvailableDevices()]') -- DevicesString = Formatted string of all devices - -- ("device_name|connected[0,1]|Authenticated[0,1]|Remembered[0,1]|datetime_last_seen|datetime_last_used;") + -- ("device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used;") -- Do something with the devices list -- See example skin for an example diff --git a/docs/bangs.md b/docs/bangs.md index ce82da3..76dd888 100644 --- a/docs/bangs.md +++ b/docs/bangs.md @@ -23,7 +23,7 @@ Available if the [#type](options.md#type "mention") is set to `1` or `0`. Disables the Bluetooth adapter. {% hint style="warning" %} -Available if the [#type](options.md#type "mention") is set to `2` or `0`. +Available if the [#type](options.md#type "mention") is set to `1` or `0`. {% endhint %} {% code title="Example Bang" %} @@ -37,7 +37,7 @@ Available if the [#type](options.md#type "mention") is set to `2` or `0`. Enables the Bluetooth adapter. {% hint style="warning" %} -Available if the [#type](options.md#type "mention") is set to `2` or `0`. +Available if the [#type](options.md#type "mention") is set to `1` or `0`. {% endhint %} {% code title="Example Bang" %} diff --git a/docs/options.md b/docs/options.md index bb9456c..0e7b889 100644 --- a/docs/options.md +++ b/docs/options.md @@ -81,8 +81,8 @@ The file will have this structure: {% code title="@Resources/output.txt" lineNumbers="true" fullWidth="false" %} ``` -device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|datetime_last_seen|datetime_last_used; -device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|datetime_last_seen|datetime_last_used; +device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used; +device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used; ... ``` {% endcode %} @@ -117,7 +117,7 @@ The name of the file that contains the [#devicesvariable](options.md#devicesvari {% code title="Example" lineNumbers="true" %} ```ini [Variables] -Variable1=device_name|connected[0,1]|Authenticated[0,1]|Remembered[0,1]|datetime_last_seen|datetime_last_used;... +Variable1=device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used;... [BluetoothMeasure] Measure=Plugin diff --git a/docs/section-variables.md b/docs/section-variables.md index 11fcb9e..f5d5ec5 100644 --- a/docs/section-variables.md +++ b/docs/section-variables.md @@ -8,7 +8,7 @@ description: Possible section variables that can be used Returns the list of devices in a string. -`device_name|connected[0,1]|Authenticated[0,1]|Remembered[0,1]|datetime_last_seen|datetime_last_used;` +`device_name|connected[0,1]|authenticated[0,1]|remembered[0,1]|address|datetime_last_seen|datetime_last_used;` Every device is separated by `;`, and evey item of a device is separated by `|`. diff --git a/src/BluetoothPlugin.rc b/src/BluetoothPlugin.rc index 4ccb373..3883dd8 100644 --- a/src/BluetoothPlugin.rc +++ b/src/BluetoothPlugin.rc @@ -8,7 +8,7 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,7,0 + FILEVERSION 0,0,8,0 PRODUCTVERSION 3,0,2,2161 FILEFLAGSMASK 0x17L #ifdef _DEBUG @@ -26,7 +26,7 @@ BEGIN BEGIN VALUE "CompanyName", "bunz" VALUE "FileDescription", "Bluetooth plugin for Rainmeter" - VALUE "FileVersion", "0.0.7.0" + VALUE "FileVersion", "0.0.8.0" VALUE "InternalName", "Bluetooth Plugin" VALUE "LegalCopyright", "© 2024 - Bunz" VALUE "OriginalFilename", "Bluetooth.dll" diff --git a/src/Plugin.cpp b/src/Plugin.cpp index db08443..301d314 100644 --- a/src/Plugin.cpp +++ b/src/Plugin.cpp @@ -6,11 +6,11 @@ #include #include #include +#include +#include #include #include -#include #include -#include #include using namespace std; @@ -30,6 +30,9 @@ static wstring availableDevices; // Formatted string of all devices ("device_nam static wstring devicesBuffer; // Buffer to save devices during list updates to avoid getting back partial lists static string fileBufferString; // Buffer to save devices during file updates to avoid having an empty file between updates static wstring bluetoothStatus; // String to hold the status of the Bluetooth adapter +static std::mutex bufferMutex; + +std::thread updateThread; #pragma endregion @@ -46,7 +49,7 @@ BOOL WINAPI DllMain( switch (fdwReason) { case DLL_PROCESS_ATTACH: MODULE_INSTANCE = hinstDLL; - //DisableThreadLibraryCalls(hinstDLL); // disable thread library calls, for performance improvement + DisableThreadLibraryCalls(hinstDLL); // disable thread library calls, for performance improvement default: break; } @@ -123,44 +126,54 @@ PLUGIN_EXPORT double Update(void* data) { PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) { Measure* measure = (Measure*)data; if (measure->pluginType == 2) { + if (_wcsicmp(args, L"UpdateDevices") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Updating devices"); + updateDevices(measure); + } + else { + RmLogF(measure->rm, LOG_ERROR, L"[Bluetooth-Plugin] Invalid bang: %s for selected Plugin Type %s", args, measure->pluginType); + } + } + else if (measure->pluginType == 1) { if (_wcsicmp(args, L"DisableBluetooth") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Disabling Bluetooth adapter"); disableBluetooth(measure); } else if (_wcsicmp(args, L"EnableBluetooth") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Enabling Bluetooth adapter"); enableBluetooth(measure); } else if (_wcsicmp(args, L"ToggleBluetooth") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Toggling Bluetooth adapter"); toggleBluetooth(measure); } - else if (_wcsicmp(args, L"UpdateDevices") == 0) { - updateDevices(measure); - } - else { - RmLogF(measure->rm, LOG_ERROR, L"[Bluetooth-Plugin] Invalid bang: %s for selected plugin Type %s", args, measure->pluginType); - } - } - else if (measure->pluginType == 1) { - if (_wcsicmp(args, L"UpdateBluetoothStatus") == 0) { + else if (_wcsicmp(args, L"UpdateBluetoothStatus") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Updating Bluetooth status"); updateBluetoothStatus(measure); } else { - RmLogF(measure->rm, LOG_ERROR, L"[Bluetooth-Plugin] Invalid bang: %s for selected plugin Type %s", args, measure->pluginType); + RmLogF(measure->rm, LOG_ERROR, L"[Bluetooth-Plugin] Invalid bang: %s for selected Plugin Type %s", args, measure->pluginType); } } else if (measure->pluginType == 0) { if (_wcsicmp(args, L"DisableBluetooth") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Disabling Bluetooth adapter"); disableBluetooth(measure); } else if (_wcsicmp(args, L"EnableBluetooth") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Enabling Bluetooth adapter"); enableBluetooth(measure); } else if (_wcsicmp(args, L"ToggleBluetooth") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Toggling Bluetooth adapter"); toggleBluetooth(measure); } else if (_wcsicmp(args, L"UpdateDevices") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Updating devices"); updateDevices(measure); } else if (_wcsicmp(args, L"UpdateBluetoothStatus") == 0) { + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Updating Bluetooth status"); updateBluetoothStatus(measure); } else { @@ -168,7 +181,7 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) { } } else { - RmLogF(measure->rm, LOG_ERROR, L"[Bluetooth-Plugin] Invalid PluginType"); + RmLogF(measure->rm, LOG_ERROR, L"[Bluetooth-Plugin] Invalid Plugin Type"); } } @@ -178,9 +191,15 @@ PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args) { */ PLUGIN_EXPORT void Finalize(void* data) { Measure* measure = (Measure*)data; + + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Unloading"); + + // Clean up resources delete measure; availableDevices.clear(); devicesBuffer.clear(); + fileBufferString.clear(); + bluetoothStatus.clear(); } #pragma endregion @@ -196,7 +215,6 @@ PLUGIN_EXPORT LPCWSTR AvailableDevices(void* data, const int argc, WCHAR* argv[] return availableDevices.c_str(); } - /* * Can be called as a section variable, to get the status of the Bluetooth adapter */ @@ -242,20 +260,27 @@ void updateBluetoothStatus(Measure* measure) { * - if the device is connected * - if the device is authenticated * - if the device is remembered +* - the device address * - when the device was last seen * - when the device was last used */ void updateDevices(Measure* measure) { - std::thread updateThread([measure]() { + updateThread = std::thread([measure]() { + if (!bufferMutex.try_lock()) { + RmLogF(measure->rm, LOG_ERROR, L"Another thread is already updating the devices"); + return; + } devicesBuffer.clear(); fileBufferString.clear(); + set deviceAddresses; // To store unique device addresses + set deviceNames; // To store unique device names HANDLE hRadio; BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(btfrp) }; HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio(&btfrp, &hRadio); - if (hFind != NULL) { + if (hFind != nullptr) { do { BLUETOOTH_RADIO_INFO radioInfo = { sizeof(BLUETOOTH_RADIO_INFO) }; DWORD dwResult = BluetoothGetRadioInfo(hRadio, &radioInfo); @@ -271,21 +296,26 @@ void updateDevices(Measure* measure) { deviceSearchParams.hRadio = hRadio; HBLUETOOTH_DEVICE_FIND hDeviceFind = BluetoothFindFirstDevice(&deviceSearchParams, &deviceInfo); - if (hDeviceFind != NULL) { + if (hDeviceFind != nullptr) { do { - if (deviceInfo.szName && deviceInfo.stLastUsed.wYear != 1601) { // Check to remove ghost devices + if (deviceInfo.szName && deviceInfo.stLastUsed.wYear != 1601 && deviceAddresses.find(deviceInfo.Address.ullLong) == deviceAddresses.end() && deviceNames.find(deviceInfo.szName) == deviceNames.end()) { // Check to remove ghost devices and duplicate addresses + deviceAddresses.insert(deviceInfo.Address.ullLong); // Add the device address to the set + deviceNames.emplace(deviceInfo.szName); // Add the device name to the set + wstring wDeviceName(deviceInfo.szName); - wstring wDeviceConnected = to_wstring((deviceInfo.fConnected ? 1 : 0)); - wstring wDeviceAuthenticated = to_wstring((deviceInfo.fAuthenticated ? 1 : 0)); - wstring wDeviceRemembered = to_wstring((deviceInfo.fRemembered ? 1 : 0)); + wstring wDeviceConnected = to_wstring(deviceInfo.fConnected ? 1 : 0); + wstring wDeviceAuthenticated = to_wstring(deviceInfo.fAuthenticated ? 1 : 0); + wstring wDeviceRemembered = to_wstring(deviceInfo.fRemembered ? 1 : 0); + wstring wDeviceAddress = to_wstring(deviceInfo.Address.ullLong); wstring wDeviceLastSeen = to_wstring(deviceInfo.stLastSeen.wMonth) + L"/" + to_wstring(deviceInfo.stLastSeen.wDay) + L"/" + to_wstring(deviceInfo.stLastSeen.wYear) + L" " + to_wstring(deviceInfo.stLastSeen.wHour) + L":" + to_wstring(deviceInfo.stLastSeen.wMinute) + L":" + to_wstring(deviceInfo.stLastSeen.wSecond); wstring wDeviceLastUsed = to_wstring(deviceInfo.stLastUsed.wMonth) + L"/" + to_wstring(deviceInfo.stLastUsed.wDay) + L"/" + to_wstring(deviceInfo.stLastUsed.wYear) + L" " + to_wstring(deviceInfo.stLastUsed.wHour) + L":" + to_wstring(deviceInfo.stLastUsed.wMinute) + L":" + to_wstring(deviceInfo.stLastUsed.wSecond); wstring wDivider = L"|"; string deviceName(wDeviceName.begin(), wDeviceName.end()); - string DeviceConnected = to_string((deviceInfo.fConnected ? 1 : 0)); - string DeviceAuthenticated = to_string((deviceInfo.fAuthenticated ? 1 : 0)); - string DeviceRemembered = to_string((deviceInfo.fRemembered ? 1 : 0)); + string DeviceConnected = to_string(deviceInfo.fConnected ? 1 : 0); + string DeviceAuthenticated = to_string(deviceInfo.fAuthenticated ? 1 : 0); + string DeviceRemembered = to_string(deviceInfo.fRemembered ? 1 : 0); + string DeviceAddress = to_string(deviceInfo.Address.ullLong); string deviceLastSeen = to_string(deviceInfo.stLastSeen.wMonth) + "/" + to_string(deviceInfo.stLastSeen.wDay) + "/" + to_string(deviceInfo.stLastSeen.wYear) + " " + to_string(deviceInfo.stLastSeen.wHour) + ":" + to_string(deviceInfo.stLastSeen.wMinute) + ":" + to_string(deviceInfo.stLastSeen.wSecond); string deviceLastUsed = to_string(deviceInfo.stLastUsed.wMonth) + "/" + to_string(deviceInfo.stLastUsed.wDay) + "/" + to_string(deviceInfo.stLastUsed.wYear) + " " + to_string(deviceInfo.stLastUsed.wHour) + ":" + to_string(deviceInfo.stLastUsed.wMinute) + ":" + to_string(deviceInfo.stLastUsed.wSecond); string divider = "|"; @@ -297,6 +327,7 @@ void updateDevices(Measure* measure) { wDeviceConnected + wDivider + wDeviceAuthenticated + wDivider + wDeviceRemembered + wDivider + + wDeviceAddress + wDivider + wDeviceLastSeen + wDivider + wDeviceLastUsed + L";" @@ -307,6 +338,7 @@ void updateDevices(Measure* measure) { DeviceConnected + divider + DeviceAuthenticated + divider + DeviceRemembered + divider + + DeviceAddress + divider + deviceLastSeen + divider + deviceLastUsed + ";\n" @@ -320,7 +352,9 @@ void updateDevices(Measure* measure) { } while (BluetoothFindNextRadio(hFind, &hRadio)); BluetoothFindRadioClose(hFind); } - availableDevices = devicesBuffer; // Set the availableDevices string to the content of the buffer to avoid partial lists + availableDevices = devicesBuffer; // Set the availableDevices string to the content of the buffer to avoid partial lists + + bufferMutex.unlock(); // Unlock the mutex // Write to file if the "OutputPath" field is populated if (measure->outputPath != L"") { @@ -377,7 +411,7 @@ void enableBluetooth(Measure* measure) { for (Radio const& radio : radios) { if (radio.Kind() == RadioKind::Bluetooth) { radio.SetStateAsync(RadioState::On).get(); - RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Disabled Bluetooth adapter"); + RmLogF(measure->rm, LOG_DEBUG, L"[Bluetooth-Plugin] Enabled Bluetooth adapter"); bluetoothStatus = L"1"; break; }