diff --git a/.editorconfig b/.editorconfig index 61b7846..63202f0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,7 @@ [*.{cpp,h,sh,md,cfg,sample}] indent_style = tab indent_size = 4 + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/continuous-build-linux.yml b/.github/workflows/continuous-build-linux.yml index 33d545c..38f3f2c 100644 --- a/.github/workflows/continuous-build-linux.yml +++ b/.github/workflows/continuous-build-linux.yml @@ -1,6 +1,7 @@ name: Continuous Build Linux on: + workflow_dispatch: push: branches: - main @@ -12,111 +13,97 @@ on: - '!src/freebsd/**' - 'include/**' - 'Makefile' + - '.github/workflows/continuous-build.yml' jobs: - build: + static-build: + continue-on-error: true + strategy: + matrix: + toolchain: + - aarch64-linux-musl + - aarch64_be-linux-musl + - arm-linux-musleabi + - arm-linux-musleabihf + - armeb-linux-musleabi + - armeb-linux-musleabihf + - armel-linux-musleabi + - armel-linux-musleabihf + - armv5l-linux-musleabi + - armv5l-linux-musleabihf + - armv6-linux-musleabi + - armv6-linux-musleabihf + - armv7l-linux-musleabihf + - armv7m-linux-musleabi + - armv7r-linux-musleabihf + - i486-linux-musl + - i686-linux-musl + - m68k-linux-musl + - mips-linux-musl + - mips-linux-musln32sf + - mips-linux-muslsf + - mips64-linux-musl + - mips64-linux-musln32 + - mips64-linux-musln32sf + - mips64el-linux-musl + - mips64el-linux-musln32 + - mips64el-linux-musln32sf + - mipsel-linux-musl + - mipsel-linux-musln32 + - mipsel-linux-musln32sf + - mipsel-linux-muslsf + - or1k-linux-musl + - powerpc-linux-musl + - powerpc-linux-muslsf + - powerpc64-linux-musl + - powerpc64le-linux-musl + - powerpcle-linux-musl + - powerpcle-linux-muslsf + - riscv32-linux-musl + - riscv64-linux-musl + - s390x-linux-musl + - sh2-linux-musl + - sh2-linux-muslfdpic + - sh2eb-linux-musl + - sh2eb-linux-muslfdpic + - sh4-linux-musl + - sh4eb-linux-musl + - x86_64-linux-musl + - x86_64-linux-muslx32 runs-on: ubuntu-latest - container: ubuntu:21.04 + container: muslcc/x86_64:${{ matrix.toolchain }} steps: - - uses: actions/checkout@v2 - name: Install build tools - run: | - apt update && \ - apt install coreutils sed git build-essential gcc-11 g++-11 -y - apt install -y g++-11-aarch64-linux-gnu g++-11-i686-linux-gnu \ - g++-11-arm-linux-gnueabi g++-11-arm-linux-gnueabihf g++-11-riscv64-linux-gnu \ - g++-11-sparc64-linux-gnu + run: apk add --no-cache coreutils git make tar zstd - mkdir -p multiarch_bin + - name: Checkout source + uses: actions/checkout@v2 - git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] + - name: Fix - Stopping at filesystem boundary + run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] - - name: Compile x86_64 - run: | - make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH - make distclean - - - name: Compile i686 - run: | - make CXX=i686-linux-gnu-g++-11 ARCH=i686 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-i686-$GIT_HASH - make distclean - - - name: Compile aarch64 - run: | - make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-aarch64-$GIT_HASH - make distclean - - - name: Compile armel - run: | - make CXX=arm-linux-gnueabi-g++-11 ARCH=armel STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-armel-$GIT_HASH - make distclean - - - name: Compile armhf - run: | - make CXX=arm-linux-gnueabihf-g++-11 ARCH=armhf STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-armhf-$GIT_HASH - make distclean - - - name: Compile riscv64 - run: | - make CXX=riscv64-linux-gnu-g++-11 ARCH=riscv64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-riscv64-$GIT_HASH - make distclean - - - name: Compile sparc64 - run: | - make CXX=sparc64-linux-gnu-g++-11 ARCH=sparc64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-sparc64-$GIT_HASH - make distclean + - name: Build + run: make STATIC=true STRIP=true QUIET=true - name: Make executable + run: chmod +x bin/* + + - name: Set up directories run: | - chmod +x multiarch_bin/* + mkdir .artifacts + mkdir .package - - uses: actions/upload-artifact@v2 - with: - name: btop-x86_64 - path: 'multiarch_bin/btop-x86_64*' + - name: Create binary atrifacts + run: | + TOOLCHAIN=${{ matrix.toolchain }} + GIT_HASH=$(git rev-parse --short "${{ github.sha }}") + FILENAME=btop-${TOOLCHAIN/linux-musl/}-$GIT_HASH + cp bin/btop .artifacts/$FILENAME - - uses: actions/upload-artifact@v2 + - name: Upload artifacts + uses: actions/upload-artifact@v2 with: - name: btop-i686 - path: 'multiarch_bin/btop-i686*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-aarch64 - path: 'multiarch_bin/btop-aarch64*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-armel - path: 'multiarch_bin/btop-armel*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-armhf - path: 'multiarch_bin/btop-armhf*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-riscv64 - path: 'multiarch_bin/btop-riscv64*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-sparc64 - path: 'multiarch_bin/btop-sparc64*' + name: btop-${{ matrix.toolchain }} + path: '.artifacts/**' diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f1507..197882f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## v1.0.18 + +* Fixed: Makefile g++ -dumpmachine failure to get platform on some distros + +## v1.0.17 + +* Changed: Reverted mutexes back to custom atomic bool based locks + +* Added: Static binaries switched to building with musl + more platforms, by @jan-guenter + +* Fixed: Improved battery detection, by @jan-guenter + +* Added: Displayed battery selectable in options menu + +* Fixed: Battery error if non existent battery named is entered + ## v1.0.16 * Fixed: atomic_wait() and atomic_lock{} use cpu pause instructions instead of thread sleep diff --git a/Img/logo.png b/Img/logo.png index 9704fb5..7e9cb7b 100644 Binary files a/Img/logo.png and b/Img/logo.png differ diff --git a/Img/logo.svg b/Img/logo.svg new file mode 100644 index 0000000..951858f --- /dev/null +++ b/Img/logo.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Makefile b/Makefile index e75861c..1113d4e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ #* Btop++ makefile v1.2 -BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.2\033[0m +BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.3\033[0m override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") @@ -15,9 +15,14 @@ endif PREFIX ?= /usr/local -#? NOTICE! Manually set PLATFORM and ARCH if not compiling for host system +#? Detect PLATFORM and ARCH from uname/gcc if not set PLATFORM ?= $(shell uname -s || echo unknown) -ARCH ?= $(shell uname -m || echo unknown) +ifneq ($(filter unknown darwin, $(PLATFORM)),) + override PLATFORM := $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }') +endif +ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) + +override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') #? Make sure PLATFORM Darwin is OSX and not Darwin ifeq ($(PLATFORM),Darwin) @@ -30,12 +35,16 @@ ifeq ($(PLATFORM),Darwin) endif #? Only enable fcf-protection if on x86_64 -ifeq ($(ARCH),x86_64) +ifneq ($(filter x86_64 i%86, $(ARCH)),) override ADDFLAGS += -fcf-protection endif ifeq ($(STATIC),true) - override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ + override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings +endif + +ifeq ($(STRIP),true) + override ADDFLAGS += -s endif #? Compiler and Linker @@ -58,13 +67,13 @@ ifeq ($(CXX),g++) endif #? Pull in platform specific source files and get thread count -ifeq ($(PLATFORM),Linux) +ifeq ($(PLATFORM_LC),linux) PLATFORM_DIR := linux THREADS := $(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM),FreeBSD) +else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM),OSX) +else ifeq ($(PLATFORM_LC),apple) PLATFORM_DIR := osx THREADS := $(shell sysctl -n hw.ncpu || echo 1) ifeq ($(shell command -v gdate >/dev/null; echo $$?),0) diff --git a/README.md b/README.md index d992af5..42c58b0 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ Also needs a UTF8 locale and a font that covers: ## Installation -**Binary release (statically compiled, for kernel 3.2.0 and newer)** +**Binary release (statically compiled with musl, for kernel 2.6.39 and newer)** 1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder** @@ -238,11 +238,14 @@ Also needs a UTF8 locale and a font that covers: The makefile also needs GNU coreutils and `sed` (should already be installed on any modern distribution). + For a `cmake` based build alternative see the [fork](https://github.com/jan-guenter/btop/tree/main) by @jan-guenter + 1. **Install dependencies (example for Ubuntu 21.04 Hirsute)** + Use gcc-10 g++-10 if gcc-11 isn't available + ``` bash sudo apt install coreutils sed git build-essential gcc-11 g++-11 - # use gcc-10 g++-10 if gcc-11 isn't available ``` 2. **Clone repository** @@ -256,15 +259,20 @@ Also needs a UTF8 locale and a font that covers: Append `STATIC=true` to `make` command for static compilation. - Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users when compiling statically. + Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users if compiling statically with glibc. Append `QUIET=true` for less verbose output. - Notice! Manually set `$ARCH` variable if cross-compiling + Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). + + Append `ARCH=` to manually set the target architecture. + If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system. Use `ADDFLAGS` variable for appending flags to both compiler and linker. - For example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + + If `g++` is linked to an older version of gcc on your system specify the correct version by appending `CXX=g++-10` or `CXX=g++-11`. ``` bash make @@ -272,9 +280,11 @@ Also needs a UTF8 locale and a font that covers: 4. **Install** + Append `PREFIX=/target/dir` to set target, default: `/usr/local` + + Notice! Only use "sudo" when installing to a NON user owned directory. + ``` bash - # use "make install PREFIX=/target/dir" to set target, default: /usr/local - # only use "sudo" when installing to a NON user owned directory sudo make install ``` @@ -282,9 +292,11 @@ Also needs a UTF8 locale and a font that covers: No need for `sudo` to enable signal sending to any process and to prevent /proc read permissions problems on some systems. + Run after make install and use same PREFIX if any was used at install. + + Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `root` + ``` bash - # run after make install and use same PREFIX if any was used at install - # set SU_USER and SU_GROUP to select user and group, default is root:root sudo make setuid ``` diff --git a/src/btop.cpp b/src/btop.cpp index 886447a..3e1f9d1 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -53,7 +53,7 @@ namespace Global { {"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"}, {"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"}, }; - const string Version = "1.0.16"; + const string Version = "1.0.18"; int coreCount; string overlay; diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 09dead3..ca3e66a 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -170,6 +170,8 @@ namespace Config { {"show_battery", "#* Show battery stats in top right if battery is present."}, + {"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."}, + {"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n" "#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."} }; @@ -187,6 +189,7 @@ namespace Config { {"cpu_graph_upper", "total"}, {"cpu_graph_lower", "total"}, {"cpu_sensor", "Auto"}, + {"selected_battery", "Auto"}, {"cpu_core_map", ""}, {"temp_scale", "celsius"}, {"clock_format", "%X"}, @@ -265,6 +268,8 @@ namespace Config { fs::path conf_dir; fs::path conf_file; + vector available_batteries = {"Auto"}; + vector current_boxes; vector preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"}; int current_preset = -1; diff --git a/src/btop_config.hpp b/src/btop_config.hpp index fd08d92..b99e26f 100644 --- a/src/btop_config.hpp +++ b/src/btop_config.hpp @@ -45,6 +45,7 @@ namespace Config { extern vector current_boxes; extern vector preset_list; + extern vector available_batteries; extern int current_preset; //* Check if string only contains space seperated valid names for boxes diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 6c9eb8d..500a86e 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -270,6 +270,13 @@ namespace Menu { "", "Show battery stats in the top right corner", "if a battery is present."}, + {"selected_battery", + "Select battery.", + "", + "Which battery to use if multiple are present.", + "Can be both batteries and UPS.", + "", + "\"Auto\" for auto detection."}, {"log_level", "Set loglevel for error.log", "", @@ -962,7 +969,8 @@ namespace Menu { {"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)}, {"cpu_graph_upper", std::cref(Cpu::available_fields)}, {"cpu_graph_lower", std::cref(Cpu::available_fields)}, - {"cpu_sensor", std::cref(Cpu::available_sensors)} + {"cpu_sensor", std::cref(Cpu::available_sensors)}, + {"selected_battery", std::cref(Config::available_batteries)}, }; auto& tty_mode = Config::getB("tty_mode"); auto& vim_keys = Config::getB("vim_keys"); diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 6d3abaa..2a5a31d 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -27,7 +27,7 @@ tab-size = 4 #include #include -#ifndef STATIC_BUILD +#if !(defined(STATIC_BUILD) && defined(__GLIBC__)) #include #endif @@ -468,61 +468,99 @@ namespace Cpu { return core_map; } + struct battery { + fs::path base_dir, energy_now, energy_full, power_now, status, online; + string device_type; + bool use_energy = true; + }; + auto get_battery() -> tuple { if (not has_battery) return {0, 0, ""}; - static fs::path bat_dir, energy_now_path, energy_full_path, power_now_path, status_path, online_path; - static bool use_energy = true; + static string auto_sel; + static unordered_flat_map batteries; //? Get paths to needed files and check for valid values on first run - if (bat_dir.empty() and has_battery) { + if (batteries.empty() and has_battery) { if (fs::exists("/sys/class/power_supply")) { for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) { - if (const string dir_name = d.path().filename(); d.is_directory() and (dir_name.starts_with("BAT") or s_contains(str_to_lower(dir_name), "battery"))) { - bat_dir = d.path(); - break; + //? Only consider online power supplies of type Battery or UPS + //? see kernel docs for details on the file structure and contents + //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power + battery new_bat; + fs::path bat_dir; + try { + if (not d.is_directory() + or not fs::exists(d.path() / "type") + or not fs::exists(d.path() / "present") + or stoi(readfile(d.path() / "present")) != 1) + continue; + string dev_type = readfile(d.path() / "type"); + if (is_in(dev_type, "Battery", "UPS")) { + bat_dir = d.path(); + new_bat.base_dir = d.path(); + new_bat.device_type = dev_type; + } + } catch (...) { + //? skip power supplies not conforming to the kernel standard + continue; } + + if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now"; + else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now"; + else new_bat.use_energy = false; + + if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full"; + else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full"; + else new_bat.use_energy = false; + + if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { + continue; + } + + if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now"; + else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now"; + + if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online"; + else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online"; + + batteries[bat_dir.filename()] = new_bat; + Config::available_batteries.push_back(bat_dir.filename()); } } - if (bat_dir.empty()) { + if (batteries.empty()) { has_battery = false; return {0, 0, ""}; } - else { - if (fs::exists(bat_dir / "energy_now")) energy_now_path = bat_dir / "energy_now"; - else if (fs::exists(bat_dir / "charge_now")) energy_now_path = bat_dir / "charge_now"; - else use_energy = false; - - if (fs::exists(bat_dir / "energy_full")) energy_full_path = bat_dir / "energy_full"; - else if (fs::exists(bat_dir / "charge_full")) energy_full_path = bat_dir / "charge_full"; - else use_energy = false; - - if (not use_energy and not fs::exists(bat_dir / "capacity")) { - has_battery = false; - return {0, 0, ""}; - } - - if (fs::exists(bat_dir / "power_now")) power_now_path = bat_dir / "power_now"; - else if (fs::exists(bat_dir / "current_now")) power_now_path = bat_dir / "current_now"; - - if (fs::exists(bat_dir / "AC0/online")) online_path = bat_dir / "AC0/online"; - else if (fs::exists(bat_dir / "AC/online")) online_path = bat_dir / "AC/online"; - } } + auto& battery_sel = Config::getS("selected_battery"); + + if (auto_sel.empty()) { + for (auto& [name, bat] : batteries) { + if (bat.device_type == "Battery") { + auto_sel = name; + break; + } + } + if (auto_sel.empty()) auto_sel = batteries.begin()->first; + } + + auto& b = (battery_sel != "Auto" and batteries.contains(battery_sel) ? batteries.at(battery_sel) : batteries.at(auto_sel)); + int percent = -1; long seconds = -1; //? Try to get battery percentage - if (use_energy) { + if (b.use_energy) { try { - percent = round(100.0 * stoll(readfile(energy_now_path, "-1")) / stoll(readfile(energy_full_path, "1"))); + percent = round(100.0 * stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1"))); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } if (percent < 0) { try { - percent = stoll(readfile(bat_dir / "capacity", "-1")); + percent = stoll(readfile(b.base_dir / "capacity", "-1")); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } @@ -533,9 +571,9 @@ namespace Cpu { } //? Get charging/discharging status - string status = str_to_lower(readfile(bat_dir / "status", "unknown")); - if (status == "unknown" and not online_path.empty()) { - const auto online = readfile(online_path, "0"); + string status = str_to_lower(readfile(b.base_dir / "status", "unknown")); + if (status == "unknown" and not b.online.empty()) { + const auto online = readfile(b.online, "0"); if (online == "1" and percent < 100) status = "charging"; else if (online == "1") status = "full"; else status = "discharging"; @@ -543,16 +581,16 @@ namespace Cpu { //? Get seconds to empty if (not is_in(status, "charging", "full")) { - if (use_energy and not power_now_path.empty()) { + if (b.use_energy and not b.power_now.empty()) { try { - seconds = round((double)stoll(readfile(energy_now_path, "0")) / stoll(readfile(power_now_path, "1")) * 3600); + seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } - if (seconds < 0 and fs::exists(bat_dir / "time_to_empty")) { + if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) { try { - seconds = stoll(readfile(bat_dir / "time_to_empty", "0")) * 60; + seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60; } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } @@ -1437,7 +1475,7 @@ namespace Proc { new_proc.user = uid_user.at(uid); } else { - #ifndef STATIC_BUILD + #if !(defined(STATIC_BUILD) && defined(__GLIBC__)) try { struct passwd* udet; udet = getpwuid(stoi(uid));