From 830c5cd5d09ed3639040b0034f3c031498bc78a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Fri, 30 Sep 2022 21:59:27 +0200 Subject: [PATCH 01/10] FreeBSD: Add support to battery This commit aims to propose a FreeBSD to gain battery support using sysctl on hw.acpi.battery.* --- include/factory.hpp | 2 +- meson.build | 5 +++ src/factory.cpp | 2 +- src/modules/battery.cpp | 79 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/include/factory.hpp b/include/factory.hpp index 55031b83..ca707a3c 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -27,7 +27,7 @@ #include "modules/hyprland/language.hpp" #include "modules/hyprland/window.hpp" #endif -#if defined(__linux__) && !defined(NO_FILESYSTEM) +#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM)) #include "modules/battery.hpp" #endif #if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD) diff --git a/meson.build b/meson.build index aab5a492..e537bcca 100644 --- a/meson.build +++ b/meson.build @@ -179,6 +179,11 @@ elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd 'src/modules/memory/bsd.cpp', 'src/modules/memory/common.cpp', ) + if is_freebsd + src_files += files( + 'src/modules/battery.cpp', + ) + endif endif add_project_arguments('-DHAVE_SWAY', language: 'cpp') diff --git a/src/factory.cpp b/src/factory.cpp index 9b9dde89..d00a7d47 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -7,7 +7,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { auto hash_pos = name.find('#'); auto ref = name.substr(0, hash_pos); auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : ""; -#if defined(__linux__) && !defined(NO_FILESYSTEM) +#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM)) if (ref == "battery") { return new waybar::modules::Battery(id, config_[name]); } diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index e25ad9e5..1fbdcb58 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,9 +1,16 @@ #include "modules/battery.hpp" - +#if defined(__FreeBSD__) +// clang-format off +#include +#include +// clang-format on +#endif #include +#include waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config) : AButton(config, "battery", id, "{capacity}%", 60) { +#if defined(__Linux__) battery_watch_fd_ = inotify_init1(IN_CLOEXEC); if (battery_watch_fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); @@ -19,11 +26,12 @@ waybar::modules::Battery::Battery(const std::string& id, const Json::Value& conf if (global_watch < 0) { throw std::runtime_error("Could not watch for battery plug/unplug"); } - +#endif worker(); } waybar::modules::Battery::~Battery() { +#if (__Linux__) std::lock_guard guard(battery_list_mutex_); if (global_watch >= 0) { @@ -39,9 +47,16 @@ waybar::modules::Battery::~Battery() { batteries_.erase(it); } close(battery_watch_fd_); +#endif } void waybar::modules::Battery::worker() { +#if defined(__FreeBSD__) + thread_timer_ = [this] { + dp.emit(); + thread_timer_.sleep_for(interval_); + }; +#else thread_timer_ = [this] { // Make sure we eventually update the list of batteries even if we miss an // inotify event for some reason @@ -68,9 +83,11 @@ void waybar::modules::Battery::worker() { refreshBatteries(); dp.emit(); }; +#endif } void waybar::modules::Battery::refreshBatteries() { +#if (__Linux__) std::lock_guard guard(battery_list_mutex_); // Mark existing list of batteries as not necessarily found std::map check_map; @@ -135,6 +152,7 @@ void waybar::modules::Battery::refreshBatteries() { batteries_.erase(check.first); } } +#endif } // Unknown > Full > Not charging > Discharging > Charging @@ -158,6 +176,49 @@ const std::tuple waybar::modules::Battery::g try { uint32_t total_power = 0; // μW bool total_power_exists = false; +#if defined(__FreeBSD__) + int capacity; + size_t size_capacity = sizeof capacity; + if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.life failed"); + } + int time; + size_t size_time = sizeof time; + if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.time failed"); + } + int rate; + size_t size_rate = sizeof rate; + if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.rate failed"); + } + + auto status = getAdapterStatus(capacity); + // Handle full-at + if (config_["full-at"].isUInt()) { + auto full_at = config_["full-at"].asUInt(); + if (full_at < 100) { + capacity = 100.f * capacity / full_at; + } + } + if (capacity > 100.f) { + // This can happen when the battery is calibrating and goes above 100% + // Handle it gracefully by clamping at 100% + capacity = 100.f; + } + uint8_t cap = round(capacity); + if (cap == 100 && status=="Plugged") { + // If we've reached 100% just mark as full as some batteries can stay + // stuck reporting they're still charging but not yet done + status = "Full"; + } + + //spdlog::info("{} {} {} {}", capacity,time,status,rate); + return {capacity, time, status, rate}; + +#else + uint32_t total_power = 0; // μW +>>>>>>> 246e377 (FreeBSD: Add support to battery) uint32_t total_energy = 0; // μWh bool total_energy_exists = false; uint32_t total_energy_full = 0; @@ -456,6 +517,7 @@ const std::tuple waybar::modules::Battery::g if (cap == 100 && status == "Charging") status = "Full"; return {cap, time_remaining, status, total_power / 1e6}; +#endif } catch (const std::exception& e) { spdlog::error("Battery: {}", e.what()); return {0, 0, "Unknown", 0}; @@ -463,11 +525,20 @@ const std::tuple waybar::modules::Battery::g } const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { +#if defined(__Linux__) if (!adapter_.empty()) { bool online; std::string status; std::ifstream(adapter_ / "online") >> online; std::getline(std::ifstream(adapter_ / "status"), status); +#else + int state; + size_t size_state = sizeof state; + if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.state failed"); + } + bool online = state == 2; +#endif if (capacity == 100) { return "Full"; } @@ -475,7 +546,9 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c return "Plugged"; } return "Discharging"; +#if defined(__Linux__) } +#endif return "Unknown"; } @@ -497,10 +570,12 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai } auto waybar::modules::Battery::update() -> void { +#if __Linux__ if (batteries_.empty()) { event_box_.hide(); return; } +#endif auto [capacity, time_remaining, status, power] = getInfos(); if (status == "Unknown") { status = getAdapterStatus(capacity); From 45e44e03bd768dcad23309ee4b7d213f6db7332b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:12:42 +0200 Subject: [PATCH 02/10] Apply jbeich suggestion for if defined(__linux__) --- include/modules/battery.hpp | 2 ++ src/modules/battery.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 5f25fd59..42cf1647 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -6,7 +6,9 @@ #include #endif #include +#if #defined(__linux__) #include +#endif #include #include diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 1fbdcb58..13a49208 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -31,7 +31,7 @@ waybar::modules::Battery::Battery(const std::string& id, const Json::Value& conf } waybar::modules::Battery::~Battery() { -#if (__Linux__) +#if defined(__linux__) std::lock_guard guard(battery_list_mutex_); if (global_watch >= 0) { @@ -87,7 +87,7 @@ void waybar::modules::Battery::worker() { } void waybar::modules::Battery::refreshBatteries() { -#if (__Linux__) +#if defined(__linux__) std::lock_guard guard(battery_list_mutex_); // Mark existing list of batteries as not necessarily found std::map check_map; @@ -525,7 +525,7 @@ const std::tuple waybar::modules::Battery::g } const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { -#if defined(__Linux__) +#if defined(__linux__) if (!adapter_.empty()) { bool online; std::string status; @@ -546,7 +546,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c return "Plugged"; } return "Discharging"; -#if defined(__Linux__) +#if defined(__linux__) } #endif return "Unknown"; @@ -570,7 +570,7 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai } auto waybar::modules::Battery::update() -> void { -#if __Linux__ +#if defined(__linux__) if (batteries_.empty()) { event_box_.hide(); return; From 9d5f0e45c051de9b424c89bfb32f43ac7392ab85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:14:37 +0200 Subject: [PATCH 03/10] Add test if there is battery --- include/modules/battery.hpp | 2 +- src/modules/battery.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 42cf1647..614b36ab 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -6,7 +6,7 @@ #include #endif #include -#if #defined(__linux__) +#if defined(__linux__) #include #endif diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 13a49208..a4657409 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -177,6 +177,17 @@ const std::tuple waybar::modules::Battery::g uint32_t total_power = 0; // μW bool total_power_exists = false; #if defined(__FreeBSD__) + /* Allocate state of battery units reported via ACPI. */ + int battery_units = 0; + size_t battery_units_size = sizeof battery_units; + if( sysctlbyname("hw.acpi.battery.units", &battery_units, &battery_units_size, NULL, 0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.units failed"); + } + + if(battery_units < 0) { + throw std::runtime_error("No battery units"); + } + int capacity; size_t size_capacity = sizeof capacity; if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { From 1421163df304db67f220b5ce893099785587fbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:26:24 +0200 Subject: [PATCH 04/10] remove useless include --- src/modules/battery.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index a4657409..5f4734c1 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,7 +1,6 @@ #include "modules/battery.hpp" #if defined(__FreeBSD__) // clang-format off -#include #include // clang-format on #endif From 0ada5ac8b06e1962f9368758b0d114a1ce52a22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:39:29 +0200 Subject: [PATCH 05/10] Battery::getAdapterStatus: better code format --- src/modules/battery.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 5f4734c1..143cc1b0 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -535,7 +535,15 @@ const std::tuple waybar::modules::Battery::g } const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { -#if defined(__linux__) +#if defined(__FreeBSD__) + int state; + size_t size_state = sizeof state; + if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.state failed"); + } + bool online = state == 2; + { +#else if (!adapter_.empty()) { bool online; std::string status; @@ -556,9 +564,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c return "Plugged"; } return "Discharging"; -#if defined(__linux__) } -#endif return "Unknown"; } From a58988ea9dd71eae6ae1b80933e376a9f41fa545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 07:39:35 +0200 Subject: [PATCH 06/10] Battery: replace #else by #elif defined(__linux__) Cannot use #else here when inotify_init1() is hidden behind #if defined(__Linux__). Co-authored-by: Jan Beich --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 143cc1b0..ecf9891d 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -226,7 +226,7 @@ const std::tuple waybar::modules::Battery::g //spdlog::info("{} {} {} {}", capacity,time,status,rate); return {capacity, time, status, rate}; -#else +#elif defined(__linux__) uint32_t total_power = 0; // μW >>>>>>> 246e377 (FreeBSD: Add support to battery) uint32_t total_energy = 0; // μWh From d4d35e2f89818dd949f3399986ef178a7bcef9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 07:41:19 +0200 Subject: [PATCH 07/10] apply clang-format --- src/modules/battery.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index ecf9891d..7b1b3f76 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -179,27 +179,27 @@ const std::tuple waybar::modules::Battery::g /* Allocate state of battery units reported via ACPI. */ int battery_units = 0; size_t battery_units_size = sizeof battery_units; - if( sysctlbyname("hw.acpi.battery.units", &battery_units, &battery_units_size, NULL, 0) != 0) { + if (sysctlbyname("hw.acpi.battery.units", &battery_units, &battery_units_size, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.units failed"); } - if(battery_units < 0) { + if (battery_units < 0) { throw std::runtime_error("No battery units"); } int capacity; size_t size_capacity = sizeof capacity; - if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.life failed"); } int time; size_t size_time = sizeof time; - if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.time failed"); } int rate; size_t size_rate = sizeof rate; - if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.rate failed"); } @@ -217,13 +217,13 @@ const std::tuple waybar::modules::Battery::g capacity = 100.f; } uint8_t cap = round(capacity); - if (cap == 100 && status=="Plugged") { + if (cap == 100 && status == "Plugged") { // If we've reached 100% just mark as full as some batteries can stay // stuck reporting they're still charging but not yet done status = "Full"; } - //spdlog::info("{} {} {} {}", capacity,time,status,rate); + // spdlog::info("{} {} {} {}", capacity,time,status,rate); return {capacity, time, status, rate}; #elif defined(__linux__) @@ -538,7 +538,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c #if defined(__FreeBSD__) int state; size_t size_state = sizeof state; - if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.state failed"); } bool online = state == 2; From 6156a62294de768e9e74a382807f7106cb316c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 08:01:59 +0200 Subject: [PATCH 08/10] fix time_remaining. FreeBSD sysctl returns minutes and not hours --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 7b1b3f76..acdfd438 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -224,7 +224,7 @@ const std::tuple waybar::modules::Battery::g } // spdlog::info("{} {} {} {}", capacity,time,status,rate); - return {capacity, time, status, rate}; + return {capacity, time / 60.0, status, rate}; #elif defined(__linux__) uint32_t total_power = 0; // μW From 72a2ada82c959329a6a8a68509218de736e3e164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 11:38:21 +0200 Subject: [PATCH 09/10] remove clang-format lines --- src/modules/battery.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index acdfd438..fd78c881 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,8 +1,6 @@ #include "modules/battery.hpp" #if defined(__FreeBSD__) -// clang-format off #include -// clang-format on #endif #include From 692b90c995ba9b779d7f31deb3c013a27cea7914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 18 Oct 2022 20:44:55 +0200 Subject: [PATCH 10/10] fix build --- src/modules/battery.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index fd78c881..88774940 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -171,8 +171,6 @@ const std::tuple waybar::modules::Battery::g std::lock_guard guard(battery_list_mutex_); try { - uint32_t total_power = 0; // μW - bool total_power_exists = false; #if defined(__FreeBSD__) /* Allocate state of battery units reported via ACPI. */ int battery_units = 0; @@ -225,8 +223,8 @@ const std::tuple waybar::modules::Battery::g return {capacity, time / 60.0, status, rate}; #elif defined(__linux__) - uint32_t total_power = 0; // μW ->>>>>>> 246e377 (FreeBSD: Add support to battery) + uint32_t total_power = 0; // μW + bool total_power_exists = false; uint32_t total_energy = 0; // μWh bool total_energy_exists = false; uint32_t total_energy_full = 0; @@ -540,6 +538,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c throw std::runtime_error("sysctl hw.acpi.battery.state failed"); } bool online = state == 2; + std::string status{"Unknown"}; // TODO: add status in FreeBSD { #else if (!adapter_.empty()) { @@ -547,13 +546,6 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c std::string status; std::ifstream(adapter_ / "online") >> online; std::getline(std::ifstream(adapter_ / "status"), status); -#else - int state; - size_t size_state = sizeof state; - if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { - throw std::runtime_error("sysctl hw.acpi.battery.state failed"); - } - bool online = state == 2; #endif if (capacity == 100) { return "Full";