mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Compare commits
145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22de71efeb | |||
| ac654ff346 | |||
| df2fdf05e6 | |||
| 788307e98d | |||
| f93341ac61 | |||
| 3e0d97db2e | |||
| 864e707224 | |||
| c42b68404f | |||
| 18374467e6 | |||
| 499e6c85a0 | |||
| 0610faf1be | |||
| 778c6f0513 | |||
| c55ba2685f | |||
| aae66aa966 | |||
| a95b60167c | |||
| f5b987dba9 | |||
| f8eabdd8a6 | |||
| 5ab2c3456d | |||
| 97d9ffd193 | |||
| fa86bb1f0b | |||
| 5b9c5ebb5a | |||
| 56b03a93c5 | |||
| 3b319f0a1e | |||
| c3352d6d28 | |||
| f8426384d8 | |||
| 8791281b48 | |||
| 76ec8aff2e | |||
| 7660b0a091 | |||
| 7a8e484634 | |||
| ed01272b91 | |||
| 1c660caa85 | |||
| c241ead1d5 | |||
| 168d96a182 | |||
| 2075761282 | |||
| d59de1f158 | |||
| d64716ab74 | |||
| 0ffbb8c364 | |||
| c29960abf2 | |||
| 315cb24046 | |||
| 4cabc5684b | |||
| 256c9be19b | |||
| 1b3d713e50 | |||
| 6e816fca6e | |||
| 5a699af610 | |||
| 390119c592 | |||
| 11d7eec4db | |||
| f59be1faf2 | |||
| 7bc4c63eb4 | |||
| 4bf9f524d9 | |||
| 6508ccfc0d | |||
| d0a8d3cdc4 | |||
| 494cc1493e | |||
| 761c649817 | |||
| a2f576f3e5 | |||
| 3b9b03a086 | |||
| ab51a209d7 | |||
| 38ac339011 | |||
| b4777fe73a | |||
| b6e759f3a2 | |||
| 9ddefbc1a2 | |||
| a16851f5de | |||
| 8fe291d161 | |||
| 9ac50fc42f | |||
| c6e5221826 | |||
| 5b2006cd06 | |||
| d3f673dc6f | |||
| b99f444234 | |||
| c504096181 | |||
| c9ef47271a | |||
| fc3891c913 | |||
| cd07354b6f | |||
| fd5aeb2052 | |||
| b1b583721a | |||
| 4c3372a886 | |||
| cf66679323 | |||
| 55b41144db | |||
| ae34208247 | |||
| b462006280 | |||
| 485bcbf054 | |||
| 2e30a57889 | |||
| b439d9c203 | |||
| 08a717f5f7 | |||
| 3a84a1a5fa | |||
| 627d5fc659 | |||
| 25849dc4bb | |||
| 63032cd840 | |||
| 2414246de9 | |||
| c52353b4b8 | |||
| 799628c083 | |||
| 38d5791d57 | |||
| 9d664e2b61 | |||
| 2eb21e3521 | |||
| bfe1265c44 | |||
| dd3109cd89 | |||
| 130d5a5202 | |||
| cda4c62e9e | |||
| df245f32ec | |||
| 04409f4381 | |||
| 155e4a5b80 | |||
| 59a9209621 | |||
| cd5e14a834 | |||
| e707cf8464 | |||
| 8bdd410e97 | |||
| f45654620f | |||
| 72d138f8c4 | |||
| 6a0df7ae49 | |||
| 23def0a1c7 | |||
| 3236ef075d | |||
| d00b301904 | |||
| 6c82686283 | |||
| 399e2235d4 | |||
| bd898e4006 | |||
| 2c49dcceaf | |||
| 3c5b002414 | |||
| ca37206a49 | |||
| 8a939e981c | |||
| bed1b4cf0f | |||
| 04c3a4ccf7 | |||
| f50368a949 | |||
| 4e018dbf26 | |||
| fa02217ff4 | |||
| 22080d36b0 | |||
| 3303f4e1ce | |||
| 11d03ad59e | |||
| 504f1533c2 | |||
| bf1d1cbac5 | |||
| 94119d1674 | |||
| f4a263df01 | |||
| 533231825c | |||
| 40e2787d94 | |||
| 281af9c86f | |||
| fc0db8c291 | |||
| 48d2dbad34 | |||
| be2af8aeaf | |||
| a7621a7301 | |||
| ec87790e4f | |||
| 44632e9bf6 | |||
| 824ada49b6 | |||
| e7938216ba | |||
| 40d6d0b7b5 | |||
| 3f4d4c8eea | |||
| e2fe94d4e4 | |||
| debb5d8ad1 | |||
| f61794ea70 | |||
| d15a977431 |
+33
-19
@@ -28,6 +28,9 @@ jobs:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
|
||||
|
||||
@@ -35,7 +38,7 @@ jobs:
|
||||
env:
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} .
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
@@ -43,6 +46,9 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: run fastfetch --list-features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci
|
||||
|
||||
@@ -64,19 +70,27 @@ jobs:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package
|
||||
run: cmake --build . --target package --verbose
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -119,8 +133,13 @@ jobs:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: brew install vulkan-loader molten-vk imagemagick chafa
|
||||
run: |
|
||||
brew update
|
||||
brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
@@ -131,7 +150,7 @@ jobs:
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package
|
||||
run: cmake --build . --target package --verbose
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -171,13 +190,16 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
uses: cross-platform-actions/action@v0.21.1
|
||||
with:
|
||||
prepare: |
|
||||
pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
|
||||
operating_system: freebsd
|
||||
version: '13.2'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package
|
||||
cmake --build . --target package --verbose
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci
|
||||
time ./fastfetch -c presets/ci --format json
|
||||
@@ -214,19 +236,11 @@ jobs:
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: c, cpp
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
run: cmake --build . --verbose
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
|
||||
@@ -293,7 +307,7 @@ jobs:
|
||||
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
run: cmake --build . --verbose
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -1,3 +1,89 @@
|
||||
# 2.2.3
|
||||
|
||||
Features:
|
||||
* Update the latest mac models (Host, macOS)
|
||||
|
||||
Bugfixes:
|
||||
* Fix local ips detection on Android. Regression from `2.0.0` (LocalIP, Android)
|
||||
* Fix terminal detection on NixOS (Terminal)
|
||||
|
||||
# 2.2.2
|
||||
|
||||
Changes:
|
||||
* `--percent-type` now defaults to 9 (colored percentage numbers)
|
||||
* `fastfetch` now prints LocalIp module by default
|
||||
|
||||
Features:
|
||||
* LocalIP module now prints netmask in CIDR format for IPv4 (LocalIP)
|
||||
* Bios module now detects system firmware type (Bios)
|
||||
* Improve detection of `Battery`
|
||||
* Detect cycle count on supported platforms
|
||||
* Detect temperature on Linux when supported
|
||||
* Status detection on macOS has been adjusted to be consistant with other platforms
|
||||
* Linux binaries are built with imagemagick7 support
|
||||
|
||||
Bugfixes:
|
||||
* Fix unitialized variables (#609)
|
||||
* Fix spelling of `--preserve-aspect-ratio` (#614)
|
||||
|
||||
Logos:
|
||||
|
||||
* Update NixOS_small
|
||||
|
||||
# 2.2.1
|
||||
|
||||
Hotfix release for #606
|
||||
|
||||
Bugfixes:
|
||||
* Fix broken presets due to the breaking changes introduced in 2.2.0
|
||||
|
||||
Features:
|
||||
* Pretty print `fastfetch --help`
|
||||
|
||||
# 2.2.0
|
||||
|
||||
This release introduces a new option `--migrate-config`, which migrates old flag based config file to new JSONC format
|
||||
|
||||
Changes:
|
||||
* `--pipe` and `--stat` are moved from `general` options to `display` options. This affects cjson configuration.
|
||||
* Display keys `percent*` and `size*` in JSON config are restructured. e.g. `{ "sizeNdigits": 1 }` is now `{ "size": { "ndigits": 1 } }`
|
||||
* With the introduction of `--migrate-config`, the old flag based config file is deprecated, and will be removed in 3.0.0 (next major version)
|
||||
* Support of `--gen-config conf` is deprecated accordingly, and will be removed in 2.3.0 (next minor version)
|
||||
* The global flag `--allow-slow-operations` is splitted into some explicit flags in differnet modules
|
||||
* `--packages-winget`: control whether `winget` packages count should be detected. Note it's a very slow operation, please enable it with caution.
|
||||
* `--chassis-use-wmi`: control whether `WMI` query should be used to detect chassis type, which detects more information, but slower. This flag only affects `--chassis-format` and `--format json`.
|
||||
* `--battery-use-setup-api`: control whether `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower.
|
||||
* `--wm-detect-plugin`: control whether WM plugins should be detected. Note it's implemented with global processes enumeration and can report false results.
|
||||
* `--de-slow-version-detection`: control DE version should be detected with slow operations. It's usually not necessary and only provided as a backup.
|
||||
* `--localip-default-route-only` and `--netio-default-route-only` defaults to true to avoid large number of results
|
||||
|
||||
Features:
|
||||
* Quirks for MIPS platforms (CPU, Linux)
|
||||
* Use devicetree path for OBP hosts (Host, Linux)
|
||||
* Detect `tmux: server` as tmux (Terminal, Linux)
|
||||
* Support urxvt version detection (Terminal, Linux)
|
||||
* Support st version detection (Terminal, Linux)
|
||||
* Support st terminal font detection (TerminalFont, Linux)
|
||||
* Support xfce4-terminal 1.1.0+ terminal font detection (TerminalFont, Linux)
|
||||
* Add option `--migrate-config <?target-file-path>`
|
||||
* Support Nvidia GPU temp and cuda core count detection via nvml. Use `--gpu-use-nvml` to enable it (GPU)
|
||||
* Try supporting Wifi authentication type detection in macOS Sonoma. Please file a feature request if you get `to be supported (num)` with result of `/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | grep auth` (Wifi, macOS)
|
||||
|
||||
Bugfixes:
|
||||
* Better GPU memory and type detection (GPU, Windows)
|
||||
* Don't print display type twice (Display)
|
||||
* Detect BSSID instead of Wifi MAC address to align with other platforms (Wifi, macOS)
|
||||
* Remove support of used GPU memory detection, which is not reliable and only supported with `--gpu-force-vulkan`. (GPU)
|
||||
* Fix flag `--brightness-ddcci-sleep` (Brightness, Linux)
|
||||
* Fix hanging if a child process prints to both stdout and stderr (Linux)
|
||||
|
||||
Logos:
|
||||
* Add Black Mesa
|
||||
* Add cycledream
|
||||
* Add Evolinx
|
||||
* Add azos
|
||||
* Add Interix
|
||||
|
||||
# 2.1.2
|
||||
|
||||
Bugfixes:
|
||||
@@ -27,6 +113,8 @@ Logo:
|
||||
* Add Chimera Linux
|
||||
* Add EndeavourSmall
|
||||
* Add Xenia
|
||||
* Add MainsailOS
|
||||
* Fix phyOS
|
||||
|
||||
# 2.1.0
|
||||
|
||||
|
||||
+35
-16
@@ -1,9 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.1.2
|
||||
VERSION 2.2.3
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast system information tool"
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
)
|
||||
|
||||
@@ -70,8 +70,9 @@ cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
|
||||
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
|
||||
@@ -97,7 +98,7 @@ endif()
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=return-type")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion")
|
||||
|
||||
if(WIN32 OR ENABLE_DIRECTX_HEADERS)
|
||||
enable_language(CXX)
|
||||
@@ -116,7 +117,8 @@ if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||
endif()
|
||||
|
||||
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
if(ENABLE_ASAN)
|
||||
message(STATUS "Address sanitizer enabled (DEBUG only)")
|
||||
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
@@ -232,14 +234,11 @@ endif()
|
||||
|
||||
function(fastfetch_load_raw_text FILENAME OUTVAR)
|
||||
file(READ "${FILENAME}" TEMP)
|
||||
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
|
||||
string(JSON TEMP SET "{}" "${TEMP}" "0") # Encode raw strings using JSON_SET
|
||||
string(REGEX REPLACE "^\\{[ \t\r\n]*" "" TEMP "${TEMP}") # Remove JSON braces
|
||||
string(REGEX REPLACE "[ \t\r\n]*:[ \t\r\n]*0[ \t\r\n]*\\}$" "" TEMP "${TEMP}") # Remove trailing ` : 0 }`
|
||||
if(NOT "${TEMP}" MATCHES "^\"[^\n]*\"")
|
||||
message(FATAL_ERROR "Internal error: unexpected output: '${TEMP}'")
|
||||
endif()
|
||||
set(${OUTVAR} "${TEMP}" PARENT_SCOPE)
|
||||
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
|
||||
string(REPLACE "\\" "\\\\" TEMP "${TEMP}") # Escape backslashes
|
||||
string(REPLACE "\n" "\\n" TEMP "${TEMP}") # Replace newlines with \n
|
||||
string(REPLACE "\"" "\\\"" TEMP "${TEMP}") # Replace quotes with \"
|
||||
set(${OUTVAR} "\"${TEMP}\"" PARENT_SCOPE)
|
||||
endfunction(fastfetch_load_raw_text)
|
||||
|
||||
file(GLOB LOGO_FILES "src/logo/ascii/*.txt")
|
||||
@@ -297,7 +296,6 @@ set(LIBFASTFETCH_SRC
|
||||
src/logo/image/im7.c
|
||||
src/logo/image/image.c
|
||||
src/logo/logo.c
|
||||
src/logo/option.c
|
||||
src/modules/battery/battery.c
|
||||
src/modules/bios/bios.c
|
||||
src/modules/bluetooth/bluetooth.c
|
||||
@@ -355,6 +353,11 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/wifi/wifi.c
|
||||
src/modules/wm/wm.c
|
||||
src/modules/wmtheme/wmtheme.c
|
||||
src/options/display.c
|
||||
src/options/modules.c
|
||||
src/options/logo.c
|
||||
src/options/general.c
|
||||
src/options/library.c
|
||||
src/util/edidHelper.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
@@ -388,6 +391,7 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
@@ -416,6 +420,8 @@ if(LINUX)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_linux.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
@@ -465,6 +471,8 @@ elseif(ANDROID)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_nosupport.c
|
||||
src/detection/wifi/wifi_android.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
@@ -494,6 +502,7 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/lm/lm_linux.c
|
||||
@@ -522,6 +531,8 @@ elseif(BSD)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_bsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
@@ -572,6 +583,8 @@ elseif(APPLE)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_apple.c
|
||||
src/detection/wifi/wifi_apple.m
|
||||
src/detection/wm/wm_apple.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
@@ -597,6 +610,7 @@ elseif(WIN32)
|
||||
src/detection/displayserver/displayserver_windows.c
|
||||
src/detection/font/font_windows.c
|
||||
src/detection/gpu/gpu_windows.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_windows.c
|
||||
src/detection/libc/libc_windows.cpp
|
||||
@@ -623,6 +637,8 @@ elseif(WIN32)
|
||||
src/detection/users/users_windows.c
|
||||
src/detection/wallpaper/wallpaper_windows.c
|
||||
src/detection/wifi/wifi_windows.c
|
||||
src/detection/wm/wm_windows.cpp
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
@@ -868,8 +884,11 @@ elseif(APPLE)
|
||||
PRIVATE "-framework OpenCL"
|
||||
PRIVATE "-framework SystemConfiguration"
|
||||
PRIVATE "-weak_framework CoreDisplay"
|
||||
PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
|
||||
|
||||
PRIVATE "-F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework DisplayServices"
|
||||
PRIVATE "-weak_framework MediaRemote"
|
||||
PRIVATE "-weak_framework Apple80211"
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601)
|
||||
|
||||
@@ -23,147 +23,53 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for
|
||||
|
||||
There are [screenshots on different platforms](https://github.com/fastfetch-cli/fastfetch/wiki)
|
||||
|
||||
## Customization
|
||||
## Installation
|
||||
|
||||
With customization and speed being two competing goals, this project actually builds two executables:
|
||||
### Linux
|
||||
|
||||
* The main one is `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent by modifying `$XDG_CONFIG_HOME/fastfetch/config.conf`. Use `fastfetch --gen-config conf` to generate one. To view the available options, run `fastfetch --help`.
|
||||
* The second executable is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
|
||||
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `sudo apt install fastfetch-<version>-Linux.deb`
|
||||
* Arch Linux: `sudo pacman -S fastfetch`
|
||||
* Fedora: `sudo dnf install fastfetch`
|
||||
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
|
||||
|
||||
Currently, the performance difference is measurable, but too small to be recognizable by humans. But with more options planned, the leap will get bigger over time and on slow machines this might actually make a difference.
|
||||
|
||||
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
|
||||
|
||||
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
### Customization with new JSONC format
|
||||
|
||||
A new, structure based, and user-friendly config file format was introduced in v2.0.0. This format is based on [JSONC](https://jsonc.org/). [See more details in Wiki](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration)
|
||||
|
||||
## Dependencies
|
||||
|
||||
Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl`, `libm` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most Linux distributions.
|
||||
|
||||
The following libraries are used if present at runtime:
|
||||
|
||||
### Linux and FreeBSD
|
||||
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
|
||||
* [`libxcb-randr`](https://xcb.freedesktop.org/),
|
||||
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
|
||||
[`libxcb`](https://xcb.freedesktop.org/),
|
||||
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better display detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better display performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
|
||||
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Bluetooth, Player & Media detection.
|
||||
* [`libEGL`](https://www.khronos.org/registry/EGL/),
|
||||
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
|
||||
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
|
||||
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
|
||||
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection.
|
||||
* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection.
|
||||
* [`libddcutil`](https://github.com/rockowitz/ddcutil): Used for brightness detection of external displays
|
||||
* [`DirectX-Headers`](https://github.com/microsoft/DirectX-Headers): Used for GPU detection in WSL
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging)
|
||||
|
||||
### macOS
|
||||
|
||||
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
|
||||
* [`DisplayServices`](https://developer.apple.com/forums/thread/666383#663154022): Need for screen brightness detection. It's a private framework provided by newer macOS system.
|
||||
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Used for fast wallpaper detection ( fallback to AppleScript )
|
||||
|
||||
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
|
||||
`brew install fastfetch`
|
||||
|
||||
### Windows
|
||||
|
||||
* [`wlanapi`](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/): A system dll which isn't supported by Windows Server by default. Used for Wifi info detection.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers)
|
||||
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd)
|
||||
`scoop install fastfetch`
|
||||
|
||||
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later.
|
||||
You may also download it directly from [GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and extract the archive.
|
||||
|
||||
For the image logo, WezTerm with iterm image protocol is known to work, surprisingly.
|
||||
### FreeBSD
|
||||
|
||||
### Android
|
||||
`pkg install fastfetch`
|
||||
|
||||
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
|
||||
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Both the package [termux-api](https://github.com/termux/termux-packages/tree/master/packages/termux-api) and the Android app [Termux API](https://github.com/termux/termux-api) must be installed and the app `Termux API` must be configured to be able to self-running. In order to make Wifi detection actuall work, location privilege must be granted to the app `Termux API`. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail.
|
||||
* [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android.
|
||||
### Android (Termux)
|
||||
|
||||
For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol.
|
||||
`pkg install fastfetch`
|
||||
|
||||
## Support status
|
||||
All categories not listed here should work without needing a specific implementation.
|
||||
## Build from source
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, DiskIO, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme
|
||||
```
|
||||
See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
|
||||
##### Builtin logos
|
||||
## Usage
|
||||
|
||||
<!-- `Content of src/logo/builtin.c`.split('\n').map(x => x.trim()).filter(x => x.startsWith('// ')).map(x => x.slice(3)).filter(x => x != 'LAST').sort((a, b)=>a.toUpperCase().localeCompare(b.toUpperCase())).join(', ') -->
|
||||
```
|
||||
AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, Chimera Linux, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, EndeavourSmall, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LainOS, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xenia, Xferience, YiffOS, Zorin
|
||||
```
|
||||
* Run it with default configuration: `fastfetch`
|
||||
* Run it with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) and find what you interest: `fastfetch -c all.jsonc`
|
||||
* Find all data that fastfetch detects: `fastfetch -s <module> --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --migrate-config`
|
||||
|
||||
Run `fastfetch --print-logos` to print them
|
||||
## Customization
|
||||
|
||||
##### Package managers
|
||||
```
|
||||
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, opkg, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps
|
||||
```
|
||||
Fastfetch uses the JSONC (or JSON with comments) for configuration. [See Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration). There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `-c <filename>`. They may also serve as a good example for format arguments.
|
||||
|
||||
##### WM themes
|
||||
```
|
||||
DWM (Windows), KWin, Marco, Muffin, Mutter, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), XFWM
|
||||
```
|
||||
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
##### DE versions
|
||||
```
|
||||
Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
|
||||
```
|
||||
|
||||
##### Terminal fonts
|
||||
```
|
||||
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Console, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
fastfetch uses [`cmake`](https://cmake.org/) for building. [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is recommended for better library detection. The simplest steps to build the fastfetch and flashfetch binaries are:
|
||||
```bash
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . --target fastfetch --target flashfetch
|
||||
```
|
||||
|
||||
If the build process fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
|
||||
|
||||
### Building on Windows
|
||||
|
||||
Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested.
|
||||
|
||||
1. Install [MSYS2](https://www.msys2.org/#installation)
|
||||
1. Open `MSYS2 / CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
|
||||
1. Install dependencies
|
||||
```bash
|
||||
pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
```
|
||||
|
||||
Follow the building instructions of Linux next.
|
||||
|
||||
## Packaging
|
||||
|
||||
|
||||
+318
-204
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,6 @@
|
||||
"type": "small"
|
||||
},
|
||||
"display": {
|
||||
"percentType": 9,
|
||||
"separator": "\u001b[31m-> "
|
||||
},
|
||||
"modules": [
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
"color": {
|
||||
"keys": "magenta"
|
||||
},
|
||||
"sizeNdigits": 0,
|
||||
"sizeMaxPrefix": "MB",
|
||||
"percentType": 9
|
||||
"size": {
|
||||
"ndigits": 0,
|
||||
"maxPrefix": "MB"
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
"type": "small"
|
||||
},
|
||||
"display": {
|
||||
"percentType": 6,
|
||||
"keyWidth": 11,
|
||||
"bar": {
|
||||
"charElapsed": "=",
|
||||
|
||||
Vendored
+10359
File diff suppressed because it is too large
Load Diff
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/NVIDIA/nvidia-settings/blob/main/src/nvml.h",
|
||||
"license": "Embed in source",
|
||||
"version": "545.23.06",
|
||||
"author": "NVIDIA Corporation"
|
||||
}
|
||||
+27
-21
@@ -6,15 +6,17 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100 && red <= 100);
|
||||
|
||||
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * instance.config.barWidth + 0.5);
|
||||
uint32_t blocksGreen = (uint32_t) (green / 100.0 * instance.config.barWidth + 0.5);
|
||||
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * instance.config.barWidth + 0.5);
|
||||
uint32_t blocksRed = (uint32_t) (red / 100.0 * instance.config.barWidth + 0.5);
|
||||
assert(blocksPercent <= instance.config.barWidth);
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
if(instance.config.barBorder)
|
||||
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksGreen = (uint32_t) (green / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksRed = (uint32_t) (red / 100.0 * options->barWidth + 0.5);
|
||||
assert(blocksPercent <= options->barWidth);
|
||||
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "[ ");
|
||||
@@ -22,7 +24,7 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
|
||||
for (uint32_t i = 0; i < blocksPercent; ++i)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
{
|
||||
if (i == blocksGreen)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
@@ -31,26 +33,26 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
else if (i == blocksRed)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
ffStrbufAppend(buffer, &instance.config.barCharElapsed);
|
||||
ffStrbufAppend(buffer, &options->barCharElapsed);
|
||||
}
|
||||
|
||||
if (blocksPercent < instance.config.barWidth)
|
||||
if (blocksPercent < options->barWidth)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
|
||||
for (uint32_t i = blocksPercent; i < instance.config.barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &instance.config.barCharTotal);
|
||||
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &options->barCharTotal);
|
||||
}
|
||||
|
||||
if(instance.config.barBorder)
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
@@ -67,14 +69,18 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
bool colored = !!(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
|
||||
if (colored && !instance.config.pipe)
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
if(green < yellow)
|
||||
if(percent != percent)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
|
||||
else if(green < yellow)
|
||||
{
|
||||
if (percent <= green)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
@@ -93,9 +99,9 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%.*f%%", instance.config.percentNdigits, percent);
|
||||
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
|
||||
|
||||
if (colored && !instance.config.pipe)
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
+92
-51
@@ -1,6 +1,7 @@
|
||||
#include "commandoption.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/time.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
@@ -8,37 +9,6 @@
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
|
||||
{
|
||||
yyjson_mut_doc* doc = instance.state.resultDoc;
|
||||
if (__builtin_expect(!doc, true)) return NULL;
|
||||
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJson)
|
||||
baseInfo->generateJson(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
return module;
|
||||
}
|
||||
|
||||
bool ffParseModuleCommand(const char* type)
|
||||
{
|
||||
if(!isalpha(type[0])) return false;
|
||||
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (ffStrEqualsIgnCase(type, baseInfo->name))
|
||||
{
|
||||
if (!genJson(baseInfo))
|
||||
baseInfo->printModule(baseInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffParseModuleOptions(const char* key, const char* value)
|
||||
{
|
||||
if (!ffStrStartsWith(key, "--") || !isalpha(key[2])) return false;
|
||||
@@ -53,6 +23,7 @@ bool ffParseModuleOptions(const char* key, const char* value)
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data)
|
||||
{
|
||||
FFOptionsModules* const options = &instance.config.modules;
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
|
||||
@@ -61,22 +32,57 @@ void ffPrepareCommandOption(FFdata* data)
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
|
||||
ffPrepareDiskIO(&instance.config.diskIo);
|
||||
ffPrepareDiskIO(&options->diskIo);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
|
||||
ffPrepareNetIO(&instance.config.netIo);
|
||||
ffPrepareNetIO(&options->netIo);
|
||||
|
||||
if(instance.config.multithreading)
|
||||
if(instance.config.general.multithreading)
|
||||
{
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
|
||||
ffPreparePublicIp(&instance.config.publicIP);
|
||||
ffPreparePublicIp(&options->publicIP);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
|
||||
ffPrepareWeather(&instance.config.weather);
|
||||
ffPrepareWeather(&options->weather);
|
||||
}
|
||||
}
|
||||
|
||||
static void parseStructureCommand(const char* line, FFlist* customValues)
|
||||
static void genJsonConfig(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
|
||||
if (!modules)
|
||||
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
|
||||
|
||||
yyjson_mut_val* module = yyjson_mut_obj(doc);
|
||||
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&type);
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
|
||||
|
||||
if (baseInfo->generateJsonConfig)
|
||||
baseInfo->generateJsonConfig(baseInfo, doc, module);
|
||||
|
||||
if (yyjson_mut_obj_size(module) > 1)
|
||||
yyjson_mut_arr_add_val(modules, module);
|
||||
else
|
||||
yyjson_mut_arr_add_strbuf(doc, modules, &type);
|
||||
}
|
||||
|
||||
static void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJsonResult)
|
||||
baseInfo->generateJsonResult(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
}
|
||||
|
||||
static void parseStructureCommand(
|
||||
const char* line,
|
||||
FFlist* customValues,
|
||||
void (*fn)(FFModuleBaseInfo *baseInfo, yyjson_mut_doc* jsonDoc),
|
||||
yyjson_mut_doc* jsonDoc
|
||||
)
|
||||
{
|
||||
// handle `--set` and `--set-keyless`
|
||||
FF_LIST_FOR_EACH(FFCustomValue, customValue, *customValues)
|
||||
@@ -88,19 +94,35 @@ static void parseStructureCommand(const char* line, FFlist* customValues)
|
||||
if (customValue->printKey)
|
||||
ffStrbufAppend(&options.moduleArgs.key, &customValue->key);
|
||||
ffStrbufAppend(&options.moduleArgs.outputFormat, &customValue->value);
|
||||
ffPrintCustom(&options);
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn((FFModuleBaseInfo*) &options, jsonDoc);
|
||||
else
|
||||
ffPrintCustom(&options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ffParseModuleCommand(line))
|
||||
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
if(isalpha(line[0]))
|
||||
{
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (ffStrEqualsIgnCase(line, baseInfo->name))
|
||||
{
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn(baseInfo, jsonDoc);
|
||||
else
|
||||
baseInfo->printModule(baseInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data)
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
|
||||
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
@@ -109,25 +131,25 @@ void ffPrintCommandOption(FFdata* data)
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
|
||||
uint64_t ms = 0;
|
||||
if(instance.config.stat)
|
||||
if(instance.config.display.stat)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, &data->customValues);
|
||||
parseStructureCommand(data->structure.chars + startIndex, &data->customValues, genJsonResult, jsonDoc);
|
||||
|
||||
if(instance.config.stat)
|
||||
if(instance.config.display.stat)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
|
||||
if (resultDoc)
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
|
||||
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.pipe)
|
||||
if(instance.config.display.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
@@ -135,9 +157,28 @@ void ffPrintCommandOption(FFdata* data)
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!instance.config.noBuffer) fflush(stdout);
|
||||
if (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
|
||||
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, &data->customValues, genJsonConfig, jsonDoc);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ typedef struct FFdata
|
||||
bool loadUserConfig;
|
||||
} FFdata;
|
||||
|
||||
bool ffParseModuleCommand(const char* type);
|
||||
bool ffParseModuleOptions(const char* key, const char* value);
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-5
@@ -7,7 +7,7 @@
|
||||
|
||||
static bool loadLibSymbols(FFDBusLibrary* lib)
|
||||
{
|
||||
FF_LIBRARY_LOAD(dbus, &instance.config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
|
||||
@@ -33,9 +33,6 @@ static const FFDBusLibrary* loadLib(void)
|
||||
static FFDBusLibrary lib;
|
||||
static bool loaded = false;
|
||||
static bool loadSuccess = false;
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
if(!loaded)
|
||||
{
|
||||
@@ -43,7 +40,6 @@ static const FFDBusLibrary* loadLib(void)
|
||||
loadSuccess = loadLibSymbols(&lib);
|
||||
}
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return loadSuccess ? &lib : NULL;
|
||||
}
|
||||
|
||||
|
||||
+17
-253
@@ -15,8 +15,6 @@
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "modules/modules.h"
|
||||
|
||||
FFinstance instance; // Global singleton
|
||||
|
||||
static void initState(FFstate* state)
|
||||
@@ -32,133 +30,11 @@ static void initState(FFstate* state)
|
||||
|
||||
static void defaultConfig(void)
|
||||
{
|
||||
ffInitLogoOptions(&instance.config.logo);
|
||||
|
||||
ffStrbufInit(&instance.config.colorKeys);
|
||||
ffStrbufInit(&instance.config.colorTitle);
|
||||
instance.config.brightColor = true;
|
||||
ffStrbufInitStatic(&instance.config.keyValueSeparator, ": ");
|
||||
instance.config.processingTimeout = 1000;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufInit(&instance.config.playerName);
|
||||
ffStrbufInit(&instance.config.osFile);
|
||||
instance.config.dsForceDrm = false;
|
||||
#elif defined(_WIN32)
|
||||
instance.config.wmiTimeout = 5000;
|
||||
#endif
|
||||
|
||||
instance.config.showErrors = false;
|
||||
instance.config.allowSlowOperations = false;
|
||||
instance.config.pipe = !isatty(STDOUT_FILENO);
|
||||
|
||||
#ifdef NDEBUG
|
||||
instance.config.disableLinewrap = !instance.config.pipe;
|
||||
instance.config.hideCursor = !instance.config.pipe;
|
||||
#else
|
||||
instance.config.disableLinewrap = false;
|
||||
instance.config.hideCursor = false;
|
||||
#endif
|
||||
|
||||
instance.config.escapeBedrock = true;
|
||||
instance.config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
|
||||
instance.config.sizeNdigits = 2;
|
||||
instance.config.sizeMaxPrefix = UINT8_MAX;
|
||||
instance.config.temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS;
|
||||
instance.config.multithreading = true;
|
||||
instance.config.stat = false;
|
||||
instance.config.noBuffer = false;
|
||||
instance.config.keyWidth = 0;
|
||||
|
||||
ffStrbufInitStatic(&instance.config.barCharElapsed, "■");
|
||||
ffStrbufInitStatic(&instance.config.barCharTotal, "-");
|
||||
instance.config.barWidth = 10;
|
||||
instance.config.barBorder = true;
|
||||
instance.config.percentType = 1;
|
||||
instance.config.percentNdigits = 0;
|
||||
|
||||
ffInitBatteryOptions(&instance.config.battery);
|
||||
ffInitBiosOptions(&instance.config.bios);
|
||||
ffInitBluetoothOptions(&instance.config.bluetooth);
|
||||
ffInitBoardOptions(&instance.config.board);
|
||||
ffInitBreakOptions(&instance.config.break_);
|
||||
ffInitBrightnessOptions(&instance.config.brightness);
|
||||
ffInitCPUOptions(&instance.config.cpu);
|
||||
ffInitCPUUsageOptions(&instance.config.cpuUsage);
|
||||
ffInitChassisOptions(&instance.config.chassis);
|
||||
ffInitColorsOptions(&instance.config.colors);
|
||||
ffInitCommandOptions(&instance.config.command);
|
||||
ffInitCursorOptions(&instance.config.cursor);
|
||||
ffInitCustomOptions(&instance.config.custom);
|
||||
ffInitDEOptions(&instance.config.de);
|
||||
ffInitDateTimeOptions(&instance.config.dateTime);
|
||||
ffInitDiskOptions(&instance.config.disk);
|
||||
ffInitDiskIOOptions(&instance.config.diskIo);
|
||||
ffInitDisplayOptions(&instance.config.display);
|
||||
ffInitFontOptions(&instance.config.font);
|
||||
ffInitGPUOptions(&instance.config.gpu);
|
||||
ffInitGamepadOptions(&instance.config.gamepad);
|
||||
ffInitHostOptions(&instance.config.host);
|
||||
ffInitIconsOptions(&instance.config.icons);
|
||||
ffInitKernelOptions(&instance.config.kernel);
|
||||
ffInitLMOptions(&instance.config.lm);
|
||||
ffInitLocalIpOptions(&instance.config.localIP);
|
||||
ffInitLocaleOptions(&instance.config.locale);
|
||||
ffInitMediaOptions(&instance.config.media);
|
||||
ffInitMemoryOptions(&instance.config.memory);
|
||||
ffInitMonitorOptions(&instance.config.monitor);
|
||||
ffInitNetIOOptions(&instance.config.netIo);
|
||||
ffInitOSOptions(&instance.config.os);
|
||||
ffInitOpenCLOptions(&instance.config.openCL);
|
||||
ffInitOpenGLOptions(&instance.config.openGL);
|
||||
ffInitPackagesOptions(&instance.config.packages);
|
||||
ffInitPlayerOptions(&instance.config.player);
|
||||
ffInitPowerAdapterOptions(&instance.config.powerAdapter);
|
||||
ffInitProcessesOptions(&instance.config.processes);
|
||||
ffInitPublicIpOptions(&instance.config.publicIP);
|
||||
ffInitSeparatorOptions(&instance.config.separator);
|
||||
ffInitShellOptions(&instance.config.shell);
|
||||
ffInitSoundOptions(&instance.config.sound);
|
||||
ffInitSwapOptions(&instance.config.swap);
|
||||
ffInitTerminalFontOptions(&instance.config.terminalFont);
|
||||
ffInitTerminalOptions(&instance.config.terminal);
|
||||
ffInitTerminalSizeOptions(&instance.config.terminalSize);
|
||||
ffInitThemeOptions(&instance.config.theme);
|
||||
ffInitTitleOptions(&instance.config.title);
|
||||
ffInitUptimeOptions(&instance.config.uptime);
|
||||
ffInitUsersOptions(&instance.config.users);
|
||||
ffInitVersionOptions(&instance.config.version);
|
||||
ffInitVulkanOptions(&instance.config.vulkan);
|
||||
ffInitWMOptions(&instance.config.wm);
|
||||
ffInitWMThemeOptions(&instance.config.wmTheme);
|
||||
ffInitWallpaperOptions(&instance.config.wallpaper);
|
||||
ffInitWeatherOptions(&instance.config.weather);
|
||||
ffInitWifiOptions(&instance.config.wifi);
|
||||
|
||||
ffStrbufInit(&instance.config.libPCI);
|
||||
ffStrbufInit(&instance.config.libVulkan);
|
||||
ffStrbufInit(&instance.config.libWayland);
|
||||
ffStrbufInit(&instance.config.libXcbRandr);
|
||||
ffStrbufInit(&instance.config.libXcb);
|
||||
ffStrbufInit(&instance.config.libXrandr);
|
||||
ffStrbufInit(&instance.config.libX11);
|
||||
ffStrbufInit(&instance.config.libGIO);
|
||||
ffStrbufInit(&instance.config.libDConf);
|
||||
ffStrbufInit(&instance.config.libDBus);
|
||||
ffStrbufInit(&instance.config.libXFConf);
|
||||
ffStrbufInit(&instance.config.libSQLite3);
|
||||
ffStrbufInit(&instance.config.librpm);
|
||||
ffStrbufInit(&instance.config.libImageMagick);
|
||||
ffStrbufInit(&instance.config.libZ);
|
||||
ffStrbufInit(&instance.config.libChafa);
|
||||
ffStrbufInit(&instance.config.libEGL);
|
||||
ffStrbufInit(&instance.config.libGLX);
|
||||
ffStrbufInit(&instance.config.libOSMesa);
|
||||
ffStrbufInit(&instance.config.libOpenCL);
|
||||
ffStrbufInit(&instance.config.libfreetype);
|
||||
ffStrbufInit(&instance.config.libPulse);
|
||||
ffStrbufInit(&instance.config.libnm);
|
||||
ffStrbufInit(&instance.config.libDdcutil);
|
||||
ffOptionsInitLogo(&instance.config.logo);
|
||||
ffOptionsInitGeneral(&instance.config.general);
|
||||
ffOptionsInitModules(&instance.config.modules);
|
||||
ffOptionsInitDisplay(&instance.config.display);
|
||||
ffOptionsInitLibrary(&instance.config.library);
|
||||
}
|
||||
|
||||
void ffInitInstance(void)
|
||||
@@ -175,29 +51,6 @@ void ffInitInstance(void)
|
||||
defaultConfig();
|
||||
}
|
||||
|
||||
#if defined(FF_HAVE_THREADS) && !(defined(__APPLE__) || defined(_WIN32) || defined(__ANDROID__))
|
||||
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
|
||||
#define FF_START_DETECTION_THREADS
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffConnectDisplayServer)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectQt)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK2)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK3)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK4)
|
||||
|
||||
void startDetectionThreads(void)
|
||||
{
|
||||
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, NULL));
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_THREADS
|
||||
|
||||
static volatile bool ffDisableLinewrap = true;
|
||||
static volatile bool ffHideCursor = true;
|
||||
|
||||
@@ -233,15 +86,15 @@ static void exitSignalHandler(int signal)
|
||||
void ffStart(void)
|
||||
{
|
||||
#ifdef FF_START_DETECTION_THREADS
|
||||
if(instance.config.multithreading)
|
||||
if(instance.config.general.multithreading)
|
||||
startDetectionThreads();
|
||||
#endif
|
||||
|
||||
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe && !instance.state.resultDoc;
|
||||
ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc;
|
||||
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
|
||||
#ifdef _WIN32
|
||||
setvbuf(stdout, NULL, _IOFBF, instance.config.noBuffer ? 0 : 4096);
|
||||
setvbuf(stdout, NULL, _IOFBF, instance.config.display.noBuffer ? 0 : 4096);
|
||||
SetConsoleCtrlHandler(consoleHandler, TRUE);
|
||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
@@ -249,7 +102,7 @@ void ffStart(void)
|
||||
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#else
|
||||
if (instance.config.noBuffer) setvbuf(stdout, NULL, _IONBF, 0);
|
||||
if (instance.config.display.noBuffer) setvbuf(stdout, NULL, _IONBF, 0);
|
||||
struct sigaction action = { .sa_handler = exitSignalHandler };
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
@@ -257,7 +110,7 @@ void ffStart(void)
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
if(!instance.config.pipe && !instance.state.resultDoc)
|
||||
if(!instance.config.display.pipe && !instance.state.resultDoc)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(ffHideCursor)
|
||||
@@ -279,101 +132,11 @@ void ffFinish(void)
|
||||
|
||||
static void destroyConfig(void)
|
||||
{
|
||||
ffDestroyLogoOptions(&instance.config.logo);
|
||||
|
||||
ffStrbufDestroy(&instance.config.colorKeys);
|
||||
ffStrbufDestroy(&instance.config.colorTitle);
|
||||
ffStrbufDestroy(&instance.config.keyValueSeparator);
|
||||
ffStrbufDestroy(&instance.config.barCharElapsed);
|
||||
ffStrbufDestroy(&instance.config.barCharTotal);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufDestroy(&instance.config.playerName);
|
||||
ffStrbufDestroy(&instance.config.osFile);
|
||||
#endif
|
||||
|
||||
ffDestroyBatteryOptions(&instance.config.battery);
|
||||
ffDestroyBiosOptions(&instance.config.bios);
|
||||
ffDestroyBluetoothOptions(&instance.config.bluetooth);
|
||||
ffDestroyBoardOptions(&instance.config.board);
|
||||
ffDestroyBreakOptions(&instance.config.break_);
|
||||
ffDestroyBrightnessOptions(&instance.config.brightness);
|
||||
ffDestroyCPUOptions(&instance.config.cpu);
|
||||
ffDestroyCPUUsageOptions(&instance.config.cpuUsage);
|
||||
ffDestroyChassisOptions(&instance.config.chassis);
|
||||
ffDestroyColorsOptions(&instance.config.colors);
|
||||
ffDestroyCommandOptions(&instance.config.command);
|
||||
ffDestroyCursorOptions(&instance.config.cursor);
|
||||
ffDestroyCustomOptions(&instance.config.custom);
|
||||
ffDestroyDEOptions(&instance.config.de);
|
||||
ffDestroyDateTimeOptions(&instance.config.dateTime);
|
||||
ffDestroyDiskOptions(&instance.config.disk);
|
||||
ffDestroyDiskIOOptions(&instance.config.diskIo);
|
||||
ffDestroyDisplayOptions(&instance.config.display);
|
||||
ffDestroyFontOptions(&instance.config.font);
|
||||
ffDestroyGPUOptions(&instance.config.gpu);
|
||||
ffDestroyGamepadOptions(&instance.config.gamepad);
|
||||
ffDestroyHostOptions(&instance.config.host);
|
||||
ffDestroyIconsOptions(&instance.config.icons);
|
||||
ffDestroyKernelOptions(&instance.config.kernel);
|
||||
ffDestroyLMOptions(&instance.config.lm);
|
||||
ffDestroyLocalIpOptions(&instance.config.localIP);
|
||||
ffDestroyLocaleOptions(&instance.config.locale);
|
||||
ffDestroyMediaOptions(&instance.config.media);
|
||||
ffDestroyMemoryOptions(&instance.config.memory);
|
||||
ffDestroyMonitorOptions(&instance.config.monitor);
|
||||
ffDestroyNetIOOptions(&instance.config.netIo);
|
||||
ffDestroyOSOptions(&instance.config.os);
|
||||
ffDestroyOpenCLOptions(&instance.config.openCL);
|
||||
ffDestroyOpenGLOptions(&instance.config.openGL);
|
||||
ffDestroyPackagesOptions(&instance.config.packages);
|
||||
ffDestroyPlayerOptions(&instance.config.player);
|
||||
ffDestroyPowerAdapterOptions(&instance.config.powerAdapter);
|
||||
ffDestroyProcessesOptions(&instance.config.processes);
|
||||
ffDestroyPublicIpOptions(&instance.config.publicIP);
|
||||
ffDestroySeparatorOptions(&instance.config.separator);
|
||||
ffDestroyShellOptions(&instance.config.shell);
|
||||
ffDestroySoundOptions(&instance.config.sound);
|
||||
ffDestroySwapOptions(&instance.config.swap);
|
||||
ffDestroyTerminalFontOptions(&instance.config.terminalFont);
|
||||
ffDestroyTerminalOptions(&instance.config.terminal);
|
||||
ffDestroyTerminalSizeOptions(&instance.config.terminalSize);
|
||||
ffDestroyThemeOptions(&instance.config.theme);
|
||||
ffDestroyTitleOptions(&instance.config.title);
|
||||
ffDestroyUptimeOptions(&instance.config.uptime);
|
||||
ffDestroyUsersOptions(&instance.config.users);
|
||||
ffDestroyVersionOptions(&instance.config.version);
|
||||
ffDestroyVulkanOptions(&instance.config.vulkan);
|
||||
ffDestroyWMOptions(&instance.config.wm);
|
||||
ffDestroyWMThemeOptions(&instance.config.wmTheme);
|
||||
ffDestroyWallpaperOptions(&instance.config.wallpaper);
|
||||
ffDestroyWeatherOptions(&instance.config.weather);
|
||||
ffDestroyWifiOptions(&instance.config.wifi);
|
||||
|
||||
ffStrbufDestroy(&instance.config.libPCI);
|
||||
ffStrbufDestroy(&instance.config.libVulkan);
|
||||
ffStrbufDestroy(&instance.config.libWayland);
|
||||
ffStrbufDestroy(&instance.config.libXcbRandr);
|
||||
ffStrbufDestroy(&instance.config.libXcb);
|
||||
ffStrbufDestroy(&instance.config.libXrandr);
|
||||
ffStrbufDestroy(&instance.config.libX11);
|
||||
ffStrbufDestroy(&instance.config.libGIO);
|
||||
ffStrbufDestroy(&instance.config.libDConf);
|
||||
ffStrbufDestroy(&instance.config.libDBus);
|
||||
ffStrbufDestroy(&instance.config.libXFConf);
|
||||
ffStrbufDestroy(&instance.config.libSQLite3);
|
||||
ffStrbufDestroy(&instance.config.librpm);
|
||||
ffStrbufDestroy(&instance.config.libImageMagick);
|
||||
ffStrbufDestroy(&instance.config.libZ);
|
||||
ffStrbufDestroy(&instance.config.libChafa);
|
||||
ffStrbufDestroy(&instance.config.libEGL);
|
||||
ffStrbufDestroy(&instance.config.libGLX);
|
||||
ffStrbufDestroy(&instance.config.libOSMesa);
|
||||
ffStrbufDestroy(&instance.config.libOpenCL);
|
||||
ffStrbufDestroy(&instance.config.libfreetype);
|
||||
ffStrbufDestroy(&instance.config.libPulse);
|
||||
ffStrbufDestroy(&instance.config.libnm);
|
||||
ffStrbufDestroy(&instance.config.libDdcutil);
|
||||
ffOptionsDestroyLogo(&instance.config.logo);
|
||||
ffOptionsDestroyGeneral(&instance.config.general);
|
||||
ffOptionsDestroyModules(&instance.config.modules);
|
||||
ffOptionsDestroyDisplay(&instance.config.display);
|
||||
ffOptionsDestroyLibrary(&instance.config.library);
|
||||
}
|
||||
|
||||
static void destroyState(void)
|
||||
@@ -381,6 +144,7 @@ static void destroyState(void)
|
||||
ffPlatformDestroy(&instance.state.platform);
|
||||
yyjson_doc_free(instance.state.configDoc);
|
||||
yyjson_mut_doc_free(instance.state.resultDoc);
|
||||
ffStrbufDestroy(&instance.state.migrateConfigPath);
|
||||
}
|
||||
|
||||
void ffDestroyInstance(void)
|
||||
|
||||
+48
-295
@@ -35,6 +35,18 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs*
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs)
|
||||
{
|
||||
if (!ffStrbufEqual(&defaultModuleArgs->key, &moduleArgs->key))
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "key", &moduleArgs->key);
|
||||
if (!ffStrbufEqual(&defaultModuleArgs->outputFormat, &moduleArgs->outputFormat))
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "format", &moduleArgs->outputFormat);
|
||||
if (!ffStrbufEqual(&defaultModuleArgs->keyColor, &moduleArgs->keyColor))
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "keyColor", &moduleArgs->keyColor);
|
||||
if (moduleArgs->keyWidth != defaultModuleArgs->keyWidth)
|
||||
yyjson_mut_obj_add_uint(doc, module, "keyWidth", moduleArgs->keyWidth);
|
||||
}
|
||||
|
||||
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[])
|
||||
{
|
||||
if (yyjson_is_int(val))
|
||||
@@ -70,21 +82,17 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p
|
||||
return "Invalid enum value type; must be a string or integer";
|
||||
}
|
||||
|
||||
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
|
||||
static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_doc* doc = instance.state.resultDoc;
|
||||
if (__builtin_expect(!doc, true)) return NULL;
|
||||
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJson)
|
||||
baseInfo->generateJson(baseInfo, doc, module);
|
||||
if (baseInfo->generateJsonResult)
|
||||
baseInfo->generateJsonResult(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
return module;
|
||||
}
|
||||
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
if(!isalpha(type[0])) return false;
|
||||
|
||||
@@ -94,7 +102,9 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
|
||||
if (ffStrEqualsIgnCase(type, baseInfo->name))
|
||||
{
|
||||
if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal);
|
||||
if (!genJson(baseInfo))
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
genJsonResult(baseInfo, jsonDoc);
|
||||
else
|
||||
baseInfo->printModule(baseInfo);
|
||||
return true;
|
||||
}
|
||||
@@ -115,39 +125,39 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
case 'd': case 'D': {
|
||||
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseDiskIOJsonObject(&cfg->diskIo, module);
|
||||
ffPrepareDiskIO(&cfg->diskIo);
|
||||
if (module) cfg->modules.diskIo.moduleInfo.parseJsonObject(&cfg->modules.diskIo, module);
|
||||
ffPrepareDiskIO(&cfg->modules.diskIo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'n': case 'N': {
|
||||
if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseNetIOJsonObject(&cfg->netIo, module);
|
||||
ffPrepareNetIO(&cfg->netIo);
|
||||
if (module) cfg->modules.netIo.moduleInfo.parseJsonObject(&cfg->modules.netIo, module);
|
||||
ffPrepareNetIO(&cfg->modules.netIo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'p': case 'P': {
|
||||
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParsePublicIpJsonObject(&cfg->publicIP, module);
|
||||
ffPreparePublicIp(&cfg->publicIP);
|
||||
if (module) cfg->modules.publicIP.moduleInfo.parseJsonObject(&cfg->modules.publicIP, module);
|
||||
ffPreparePublicIp(&cfg->modules.publicIP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'w': case 'W': {
|
||||
if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseWeatherJsonObject(&cfg->weather, module);
|
||||
ffPrepareWeather(&cfg->weather);
|
||||
if (module) cfg->modules.weather.moduleInfo.parseJsonObject(&cfg->modules.weather, module);
|
||||
ffPrepareWeather(&cfg->modules.weather);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(bool prepare)
|
||||
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
@@ -159,14 +169,12 @@ static const char* printJsonConfig(bool prepare)
|
||||
if (!modules) return NULL;
|
||||
if (!yyjson_is_arr(modules)) return "Property 'modules' must be an array of strings or objects";
|
||||
|
||||
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
|
||||
|
||||
yyjson_val* item;
|
||||
size_t idx, max;
|
||||
yyjson_arr_foreach(modules, idx, max, item)
|
||||
{
|
||||
uint64_t ms = 0;
|
||||
if(!prepare && instance.config.stat)
|
||||
if(!prepare && instance.config.display.stat)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
yyjson_val* module = item;
|
||||
@@ -185,22 +193,22 @@ static const char* printJsonConfig(bool prepare)
|
||||
|
||||
if(prepare)
|
||||
prepareModuleJsonObject(type, module);
|
||||
else if(!parseModuleJsonObject(type, module))
|
||||
else if(!parseModuleJsonObject(type, module, jsonDoc))
|
||||
return "Unknown module type";
|
||||
|
||||
if(!prepare && instance.config.stat)
|
||||
if(!prepare && instance.config.display.stat)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
if (resultDoc)
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
|
||||
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.pipe)
|
||||
if(instance.config.display.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
@@ -208,280 +216,25 @@ static const char* printJsonConfig(bool prepare)
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!instance.config.noBuffer && !resultDoc) fflush(stdout);
|
||||
if (!instance.config.display.noBuffer && !jsonDoc) fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseGeneralJsonConfig(void)
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
FFconfig* config = &instance.config;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
yyjson_val* object = yyjson_obj_get(root, "general");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'general' must be an object";
|
||||
|
||||
yyjson_val *key_, *val;
|
||||
size_t idx, max;
|
||||
yyjson_obj_foreach(object, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "allowSlowOperations"))
|
||||
config->allowSlowOperations = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
|
||||
config->multithreading = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "stat"))
|
||||
{
|
||||
if ((config->stat = yyjson_get_bool(val)))
|
||||
config->showErrors = true;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
|
||||
config->escapeBedrock = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "pipe"))
|
||||
config->pipe = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
|
||||
config->processingTimeout = (int32_t) yyjson_get_int(val);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
else if (ffStrEqualsIgnCase(key, "playerName"))
|
||||
ffStrbufSetS(&config->playerName, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osFile"))
|
||||
ffStrbufSetS(&config->osFile, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
|
||||
config->dsForceDrm = yyjson_get_bool(val);
|
||||
#elif defined(_WIN32)
|
||||
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
|
||||
config->wmiTimeout = (int32_t) yyjson_get_int(val);
|
||||
#endif
|
||||
|
||||
else
|
||||
return "Unknown general property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseDisplayJsonConfig(void)
|
||||
{
|
||||
FFconfig* config = &instance.config;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
yyjson_val* object = yyjson_obj_get(root, "display");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'display' must be an object";
|
||||
|
||||
yyjson_val *key_, *val;
|
||||
size_t idx, max;
|
||||
yyjson_obj_foreach(object, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "showErrors"))
|
||||
config->showErrors = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "disableLinewrap"))
|
||||
config->disableLinewrap = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "hideCursor"))
|
||||
config->hideCursor = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "separator"))
|
||||
ffStrbufSetS(&config->keyValueSeparator, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "color"))
|
||||
{
|
||||
if (yyjson_is_str(val))
|
||||
{
|
||||
ffOptionParseColor(yyjson_get_str(val), &config->colorKeys);
|
||||
ffStrbufSet(&config->colorTitle, &config->colorKeys);
|
||||
}
|
||||
else if (yyjson_is_obj(val))
|
||||
{
|
||||
const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys"));
|
||||
if (colorKeys)
|
||||
ffOptionParseColor(colorKeys, &config->colorKeys);
|
||||
const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title"));
|
||||
if (colorTitle)
|
||||
ffOptionParseColor(colorTitle, &config->colorTitle);
|
||||
}
|
||||
else
|
||||
return "display.color must be either a string or an object";
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "brightColor"))
|
||||
config->brightColor = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "binaryPrefix"))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "iec", FF_BINARY_PREFIX_TYPE_IEC },
|
||||
{ "si", FF_BINARY_PREFIX_TYPE_SI },
|
||||
{ "jedec", FF_BINARY_PREFIX_TYPE_JEDEC },
|
||||
{},
|
||||
});
|
||||
if (error) return error;
|
||||
config->binaryPrefixType = (FFBinaryPrefixType) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "sizeNdigits"))
|
||||
config->sizeNdigits = (uint8_t) yyjson_get_uint(val);
|
||||
else if (ffStrEqualsIgnCase(key, "sizeMaxPrefix"))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "B", 0 },
|
||||
{ "kB", 1 },
|
||||
{ "MB", 2 },
|
||||
{ "GB", 3 },
|
||||
{ "TB", 4 },
|
||||
{ "PB", 5 },
|
||||
{ "EB", 6 },
|
||||
{ "ZB", 7 },
|
||||
{ "YB", 8 },
|
||||
{}
|
||||
});
|
||||
if (error) return error;
|
||||
config->sizeMaxPrefix = (uint8_t) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "temperatureUnit"))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS },
|
||||
{ "C", FF_TEMPERATURE_UNIT_CELSIUS },
|
||||
{ "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT },
|
||||
{ "F", FF_TEMPERATURE_UNIT_FAHRENHEIT },
|
||||
{ "KELVIN", FF_TEMPERATURE_UNIT_KELVIN },
|
||||
{ "K", FF_TEMPERATURE_UNIT_KELVIN },
|
||||
{},
|
||||
});
|
||||
if (error) return error;
|
||||
config->temperatureUnit = (FFTemperatureUnit) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "percentType"))
|
||||
config->percentType = (uint8_t) yyjson_get_uint(val);
|
||||
else if (ffStrEqualsIgnCase(key, "percentNdigits"))
|
||||
config->percentNdigits = (uint8_t) yyjson_get_uint(val);
|
||||
else if (ffStrEqualsIgnCase(key, "bar"))
|
||||
{
|
||||
if (yyjson_is_obj(val))
|
||||
{
|
||||
const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed"));
|
||||
if (charElapsed)
|
||||
ffStrbufSetS(&config->barCharElapsed, charElapsed);
|
||||
|
||||
const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal"));
|
||||
if (charTotal)
|
||||
ffStrbufSetS(&config->barCharTotal, charTotal);
|
||||
|
||||
yyjson_val* border = yyjson_obj_get(val, "border");
|
||||
if (border)
|
||||
config->barBorder = yyjson_get_bool(border);
|
||||
|
||||
yyjson_val* width = yyjson_obj_get(val, "width");
|
||||
if (width)
|
||||
config->barWidth = (uint8_t) yyjson_get_uint(width);
|
||||
}
|
||||
else
|
||||
return "display.bar must be an object";
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "noBuffer"))
|
||||
config->noBuffer = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "keyWidth"))
|
||||
config->keyWidth = (uint32_t) yyjson_get_uint(val);
|
||||
else
|
||||
return "Unknown display property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseLibraryJsonConfig(void)
|
||||
{
|
||||
FFconfig* config = &instance.config;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
yyjson_val* object = yyjson_obj_get(root, "library");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'library' must be an object";
|
||||
|
||||
yyjson_val *key_, *val;
|
||||
size_t idx, max;
|
||||
yyjson_obj_foreach(object, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "pci"))
|
||||
ffStrbufSetS(&config->libPCI, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "vulkan"))
|
||||
ffStrbufSetS(&config->libVulkan, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "freetype"))
|
||||
ffStrbufSetS(&config->libfreetype, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "wayland"))
|
||||
ffStrbufSetS(&config->libWayland, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "xcbRandr"))
|
||||
ffStrbufSetS(&config->libXcbRandr, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "xcb"))
|
||||
ffStrbufSetS(&config->libXcb, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "Xrandr"))
|
||||
ffStrbufSetS(&config->libXrandr, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "X11"))
|
||||
ffStrbufSetS(&config->libX11, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "gio"))
|
||||
ffStrbufSetS(&config->libGIO, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "DConf"))
|
||||
ffStrbufSetS(&config->libDConf, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "dbus"))
|
||||
ffStrbufSetS(&config->libDBus, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "XFConf"))
|
||||
ffStrbufSetS(&config->libXFConf, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "sqlite") || ffStrEqualsIgnCase(key, "sqlite3"))
|
||||
ffStrbufSetS(&config->libSQLite3, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "rpm"))
|
||||
ffStrbufSetS(&config->librpm, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "imagemagick"))
|
||||
ffStrbufSetS(&config->libImageMagick, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "z"))
|
||||
ffStrbufSetS(&config->libZ, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "chafa"))
|
||||
ffStrbufSetS(&config->libChafa, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "egl"))
|
||||
ffStrbufSetS(&config->libEGL, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "glx"))
|
||||
ffStrbufSetS(&config->libGLX, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osmesa"))
|
||||
ffStrbufSetS(&config->libOSMesa, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "opencl"))
|
||||
ffStrbufSetS(&config->libOpenCL, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "pulse"))
|
||||
ffStrbufSetS(&config->libPulse, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "nm"))
|
||||
ffStrbufSetS(&config->libnm, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "ddcutil"))
|
||||
ffStrbufSetS(&config->libDdcutil, yyjson_get_str(val));
|
||||
else
|
||||
return "Unknown library property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffPrintJsonConfig(bool prepare)
|
||||
{
|
||||
const char* error = printJsonConfig(prepare);
|
||||
const char* error = printJsonConfig(prepare, jsonDoc);
|
||||
if (error)
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
{
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_obj(jsonDoc);
|
||||
yyjson_mut_obj_add_str(jsonDoc, obj, "error", error);
|
||||
yyjson_mut_doc_set_root(jsonDoc, obj);
|
||||
}
|
||||
else
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs);
|
||||
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
|
||||
void ffPrintJsonConfig(bool prepare);
|
||||
const char* ffParseGeneralJsonConfig(void);
|
||||
const char* ffParseDisplayJsonConfig(void);
|
||||
const char* ffParseLibraryJsonConfig(void);
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc);
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs);
|
||||
|
||||
yyjson_api_inline yyjson_mut_val* yyjson_mut_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) {
|
||||
return yyjson_mut_strncpy(doc, buf->chars, buf->length);
|
||||
}
|
||||
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
|
||||
+57
-57
@@ -5,32 +5,32 @@ static FFModuleBaseInfo* A[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* B[] = {
|
||||
(void*) &instance.config.battery,
|
||||
(void*) &instance.config.bios,
|
||||
(void*) &instance.config.bluetooth,
|
||||
(void*) &instance.config.board,
|
||||
(void*) &instance.config.break_,
|
||||
(void*) &instance.config.brightness,
|
||||
(void*) &instance.config.modules.battery,
|
||||
(void*) &instance.config.modules.bios,
|
||||
(void*) &instance.config.modules.bluetooth,
|
||||
(void*) &instance.config.modules.board,
|
||||
(void*) &instance.config.modules.break_,
|
||||
(void*) &instance.config.modules.brightness,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* C[] = {
|
||||
(void*) &instance.config.chassis,
|
||||
(void*) &instance.config.command,
|
||||
(void*) &instance.config.colors,
|
||||
(void*) &instance.config.cpu,
|
||||
(void*) &instance.config.cpuUsage,
|
||||
(void*) &instance.config.cursor,
|
||||
(void*) &instance.config.custom,
|
||||
(void*) &instance.config.modules.chassis,
|
||||
(void*) &instance.config.modules.command,
|
||||
(void*) &instance.config.modules.colors,
|
||||
(void*) &instance.config.modules.cpu,
|
||||
(void*) &instance.config.modules.cpuUsage,
|
||||
(void*) &instance.config.modules.cursor,
|
||||
(void*) &instance.config.modules.custom,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* D[] = {
|
||||
(void*) &instance.config.dateTime,
|
||||
(void*) &instance.config.de,
|
||||
(void*) &instance.config.display,
|
||||
(void*) &instance.config.disk,
|
||||
(void*) &instance.config.diskIo,
|
||||
(void*) &instance.config.modules.dateTime,
|
||||
(void*) &instance.config.modules.de,
|
||||
(void*) &instance.config.modules.display,
|
||||
(void*) &instance.config.modules.disk,
|
||||
(void*) &instance.config.modules.diskIo,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -39,23 +39,23 @@ static FFModuleBaseInfo* E[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* F[] = {
|
||||
(void*) &instance.config.font,
|
||||
(void*) &instance.config.modules.font,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* G[] = {
|
||||
(void*) &instance.config.gamepad,
|
||||
(void*) &instance.config.gpu,
|
||||
(void*) &instance.config.modules.gamepad,
|
||||
(void*) &instance.config.modules.gpu,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* H[] = {
|
||||
(void*) &instance.config.host,
|
||||
(void*) &instance.config.modules.host,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* I[] = {
|
||||
(void*) &instance.config.icons,
|
||||
(void*) &instance.config.modules.icons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -64,42 +64,42 @@ static FFModuleBaseInfo* J[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* K[] = {
|
||||
(void*) &instance.config.kernel,
|
||||
(void*) &instance.config.modules.kernel,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* L[] = {
|
||||
(void*) &instance.config.lm,
|
||||
(void*) &instance.config.locale,
|
||||
(void*) &instance.config.localIP,
|
||||
(void*) &instance.config.modules.lm,
|
||||
(void*) &instance.config.modules.locale,
|
||||
(void*) &instance.config.modules.localIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* M[] = {
|
||||
(void*) &instance.config.media,
|
||||
(void*) &instance.config.memory,
|
||||
(void*) &instance.config.monitor,
|
||||
(void*) &instance.config.modules.media,
|
||||
(void*) &instance.config.modules.memory,
|
||||
(void*) &instance.config.modules.monitor,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* N[] = {
|
||||
(void*) &instance.config.netIo,
|
||||
(void*) &instance.config.modules.netIo,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* O[] = {
|
||||
(void*) &instance.config.openCL,
|
||||
(void*) &instance.config.openGL,
|
||||
(void*) &instance.config.os,
|
||||
(void*) &instance.config.modules.openCL,
|
||||
(void*) &instance.config.modules.openGL,
|
||||
(void*) &instance.config.modules.os,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* P[] = {
|
||||
(void*) &instance.config.packages,
|
||||
(void*) &instance.config.player,
|
||||
(void*) &instance.config.powerAdapter,
|
||||
(void*) &instance.config.processes,
|
||||
(void*) &instance.config.publicIP,
|
||||
(void*) &instance.config.modules.packages,
|
||||
(void*) &instance.config.modules.player,
|
||||
(void*) &instance.config.modules.powerAdapter,
|
||||
(void*) &instance.config.modules.processes,
|
||||
(void*) &instance.config.modules.publicIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -112,40 +112,40 @@ static FFModuleBaseInfo* R[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* S[] = {
|
||||
(void*) &instance.config.separator,
|
||||
(void*) &instance.config.shell,
|
||||
(void*) &instance.config.sound,
|
||||
(void*) &instance.config.swap,
|
||||
(void*) &instance.config.modules.separator,
|
||||
(void*) &instance.config.modules.shell,
|
||||
(void*) &instance.config.modules.sound,
|
||||
(void*) &instance.config.modules.swap,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* T[] = {
|
||||
(void*) &instance.config.terminal,
|
||||
(void*) &instance.config.terminalFont,
|
||||
(void*) &instance.config.terminalSize,
|
||||
(void*) &instance.config.title,
|
||||
(void*) &instance.config.theme,
|
||||
(void*) &instance.config.modules.terminal,
|
||||
(void*) &instance.config.modules.terminalFont,
|
||||
(void*) &instance.config.modules.terminalSize,
|
||||
(void*) &instance.config.modules.title,
|
||||
(void*) &instance.config.modules.theme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* U[] = {
|
||||
(void*) &instance.config.uptime,
|
||||
(void*) &instance.config.users,
|
||||
(void*) &instance.config.modules.uptime,
|
||||
(void*) &instance.config.modules.users,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* V[] = {
|
||||
(void*) &instance.config.version,
|
||||
(void*) &instance.config.vulkan,
|
||||
(void*) &instance.config.modules.version,
|
||||
(void*) &instance.config.modules.vulkan,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* W[] = {
|
||||
(void*) &instance.config.wallpaper,
|
||||
(void*) &instance.config.weather,
|
||||
(void*) &instance.config.wm,
|
||||
(void*) &instance.config.wifi,
|
||||
(void*) &instance.config.wmTheme,
|
||||
(void*) &instance.config.modules.wallpaper,
|
||||
(void*) &instance.config.modules.weather,
|
||||
(void*) &instance.config.modules.wm,
|
||||
(void*) &instance.config.modules.wifi,
|
||||
(void*) &instance.config.modules.wmTheme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
+7
-4
@@ -17,8 +17,9 @@ typedef struct FFModuleBaseInfo
|
||||
bool (*parseCommandOptions)(void* options, const char* key, const char* value);
|
||||
void (*parseJsonObject)(void* options, struct yyjson_val *module);
|
||||
void (*printModule)(void* options);
|
||||
void (*generateJson)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
|
||||
void (*generateJsonResult)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
|
||||
void (*printHelpFormat)(void);
|
||||
void (*generateJsonConfig)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* obj);
|
||||
} FFModuleBaseInfo;
|
||||
|
||||
static inline void ffOptionInitModuleBaseInfo(
|
||||
@@ -27,16 +28,18 @@ static inline void ffOptionInitModuleBaseInfo(
|
||||
void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value)
|
||||
void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module)
|
||||
void* printModule, // void (*const printModule)(void* options)
|
||||
void* generateJson, // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
void (*printHelpFormat)(void)
|
||||
void* generateJsonResult, // void (*const generateJsonResult)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
void (*printHelpFormat)(void),
|
||||
void* generateJsonConfig // void (*const generateJsonConfig)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
)
|
||||
{
|
||||
baseInfo->name = name;
|
||||
baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions;
|
||||
baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject;
|
||||
baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule;
|
||||
baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson;
|
||||
baseInfo->generateJsonResult = (__typeof__(baseInfo->generateJsonResult)) generateJsonResult;
|
||||
baseInfo->printHelpFormat = printHelpFormat;
|
||||
baseInfo->generateJsonConfig = (__typeof__(baseInfo->generateJsonConfig)) generateJsonConfig;
|
||||
}
|
||||
|
||||
typedef struct FFModuleArgs
|
||||
|
||||
@@ -65,7 +65,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
|
||||
double size = (double) bytes;
|
||||
uint8_t counter = 0;
|
||||
|
||||
while(size >= base && counter < instance.config.sizeMaxPrefix && prefixes[counter + 1])
|
||||
while(size >= base && counter < instance.config.display.sizeMaxPrefix && prefixes[counter + 1])
|
||||
{
|
||||
size /= base;
|
||||
counter++;
|
||||
@@ -74,12 +74,12 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
|
||||
if(counter == 0)
|
||||
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
|
||||
else
|
||||
ffStrbufAppendF(result, "%.*f %s", instance.config.sizeNdigits, size, prefixes[counter]);
|
||||
ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]);
|
||||
}
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFstrbuf* result)
|
||||
{
|
||||
switch (instance.config.binaryPrefixType)
|
||||
switch (instance.config.display.binaryPrefixType)
|
||||
{
|
||||
case FF_BINARY_PREFIX_TYPE_IEC:
|
||||
parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL});
|
||||
@@ -98,7 +98,7 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result)
|
||||
|
||||
void ffParseTemperature(double celsius, FFstrbuf* buffer)
|
||||
{
|
||||
switch (instance.config.temperatureUnit)
|
||||
switch (instance.config.display.temperatureUnit)
|
||||
{
|
||||
case FF_TEMPERATURE_UNIT_CELSIUS:
|
||||
ffStrbufAppendF(buffer, "%.1f°C", celsius);
|
||||
|
||||
+11
-11
@@ -14,16 +14,16 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " "))
|
||||
return;
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
if (instance.config.brightColor)
|
||||
if (instance.config.display.brightColor)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
|
||||
if(moduleArgs && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR) && moduleArgs->keyColor.length > 0)
|
||||
ffPrintColor(&moduleArgs->keyColor);
|
||||
else
|
||||
ffPrintColor(&instance.config.colorKeys);
|
||||
ffPrintColor(&instance.config.display.colorKeys);
|
||||
}
|
||||
|
||||
//NULL check is required for modules with custom keys, e.g. disk with the folder path
|
||||
@@ -43,18 +43,18 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
}
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
ffStrbufWriteTo(&instance.config.keyValueSeparator, stdout);
|
||||
ffStrbufWriteTo(&instance.config.display.keyValueSeparator, stdout);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
|
||||
if (!instance.config.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
|
||||
if (!instance.config.display.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
|
||||
{
|
||||
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.keyWidth;
|
||||
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.display.keyWidth;
|
||||
if (keyWidth > 0)
|
||||
printf("\e[%uG", (unsigned) (keyWidth + instance.state.logoWidth));
|
||||
}
|
||||
@@ -77,17 +77,17 @@ void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFMo
|
||||
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
|
||||
{
|
||||
if(!instance.config.showErrors)
|
||||
if(!instance.config.display.showErrors)
|
||||
return;
|
||||
|
||||
ffPrintLogoAndKey(moduleName, moduleIndex, moduleArgs, printType);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
|
||||
vprintf(message, arguments);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
putchar('\n');
|
||||
|
||||
@@ -34,10 +34,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
//Child
|
||||
if(childPid == 0)
|
||||
{
|
||||
int nullFile = open("/dev/null", O_WRONLY);
|
||||
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
close(useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
setenv("LANG", "C", 1);
|
||||
execvp(argv[0], argv);
|
||||
exit(901);
|
||||
@@ -48,7 +49,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
|
||||
int timeout = instance.config.processingTimeout;
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
if (timeout >= 0)
|
||||
fcntl(childPipeFd, F_SETFL, fcntl(childPipeFd, F_GETFL) | O_NONBLOCK);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ enum { FF_PIPE_BUFSIZ = 4096 };
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
{
|
||||
int timeout = instance.config.processingTimeout;
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
L"\\\\.\\pipe\\LOCAL\\",
|
||||
|
||||
+4
-11
@@ -15,18 +15,14 @@ typedef enum FFInitState
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
|
||||
static dataObject data; \
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
|
||||
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
|
||||
ffThreadMutexLock(&mutex); \
|
||||
if(initState != FF_INITSTATE_UNINITIALIZED) {\
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \
|
||||
} \
|
||||
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||
void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \
|
||||
if(libraryHandle == NULL) { \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
} \
|
||||
|
||||
@@ -35,20 +31,17 @@ typedef enum FFInitState
|
||||
if(data.ff ## symbolName == NULL) { \
|
||||
dlclose(libraryHandle); \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_RETURN \
|
||||
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &data;
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_ERROR \
|
||||
{ \
|
||||
dlclose(libraryHandle); \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
@@ -99,7 +92,7 @@ typedef struct GSettingsData
|
||||
|
||||
static const GSettingsData* getGSettingsData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance.config.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance.config.library.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_lookup)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_has_key)
|
||||
@@ -172,7 +165,7 @@ typedef struct DConfData
|
||||
|
||||
static const DConfData* getDConfData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance.config.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance.config.library.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_read_full)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
|
||||
@@ -243,7 +236,7 @@ typedef struct XFConfData
|
||||
|
||||
static const XFConfData* getXFConfData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance.config.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance.config.library.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_has_property)
|
||||
@@ -305,7 +298,7 @@ typedef struct SQLiteData
|
||||
|
||||
static const SQLiteData* getSQLiteData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance.config.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance.config.library.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file sets the default config for all users of the system.
|
||||
|
||||
# For more information about how configuration files work,
|
||||
# see ~/.config/fastfetch/config.conf, generated during first run.
|
||||
# see ~/.config/fastfetch/config.conf.
|
||||
# All options that can be put there (or passed as argument) can be put here too.
|
||||
|
||||
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
"top": 2
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"percentType": 9 // colored percent number
|
||||
},
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
@@ -34,6 +31,7 @@
|
||||
"gpu",
|
||||
"memory",
|
||||
"disk",
|
||||
"localip",
|
||||
"battery",
|
||||
"poweradapter",
|
||||
"locale",
|
||||
|
||||
+71
-60
@@ -1,9 +1,11 @@
|
||||
Usage: fastfetch <options>
|
||||
Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way
|
||||
|
||||
Usage: fastfetch <?options>
|
||||
|
||||
Informative options:
|
||||
-h,--help: Show this message
|
||||
-h,--help <command>: Show help for a specific command
|
||||
-v,--version: Show the version of fastfetch
|
||||
-h, --help: Show this message
|
||||
-h, --help <command>: Show help for a specific command
|
||||
-v, --version: Show the version of fastfetch
|
||||
--list-config-paths: List search paths of config files
|
||||
--list-data-paths: List search paths of presets and logos
|
||||
--list-logos: List available logos
|
||||
@@ -14,33 +16,33 @@ Informative options:
|
||||
--print-config-system: Print the default system config
|
||||
--print-config-user: Print the default user config
|
||||
--print-structure: Print the default structure
|
||||
--gen-config <?type>: Generate a sample config file in the default path. Param `type` can be `jsonc` or `conf`
|
||||
--gen-config-force <?type>: Generate a sample config file in the default path. Overwrite the existing one
|
||||
|
||||
Config options:
|
||||
-c, --load-config <file>: Load a config file or preset (+)
|
||||
--gen-config <type>: Generate a sample config file in the default path. Param `type` can be `jsonc` or deprecated `conf`
|
||||
--gen-config-force <type>: Generate a sample config file in the default path. Overwrite the existing one
|
||||
--migrate-config <?path>: Migrate old flag based config file to new JSONC format. Optional param `path` is the file path that new file should be write to
|
||||
|
||||
General options:
|
||||
--load-config <file>: Load a config file or preset (+)
|
||||
--config <file>: Alias of --load-config (+)
|
||||
--multithreading <?value>: Use multiple threads to detect values
|
||||
--stat <?value>: Show time usage (in ms) for individual modules
|
||||
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
|
||||
--thread <?value>: Use separate threads to send HTTP requests
|
||||
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
|
||||
--pipe <?value>: Disable logo and all escape sequences
|
||||
--wmi-timeout <num>: Set the timeout (ms) for WMI queries. Windows only. Default is 5000
|
||||
--processing-timeout <num>: Set the timeout (ms) when waiting for child processes. Default is 1000
|
||||
--ds-force-drm <?value>: Set if only DRM should be used to detect displays. Default is false
|
||||
--ds-force-drm <?value>: Set if only DRM should be used to detect displays. Default is false. Linux only
|
||||
|
||||
Logo options:
|
||||
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
|
||||
-l, --logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
|
||||
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
|
||||
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
|
||||
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
|
||||
--logo-preserve-aspect-radio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
|
||||
--logo-preserve-aspect-ratio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
|
||||
--logo-color-[1-9] <color>: Overwrite a color in the logo
|
||||
--logo-padding <padding>: Set the padding on the left and the right of the logo
|
||||
--logo-padding-left <padding>: Set the padding on the left of the logo
|
||||
--logo-padding-right <padding>: Set the padding on the right of the logo
|
||||
--logo-padding-top <padding>: Set the padding on the top of the logo
|
||||
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
|
||||
--logo-separate <?value>: If true, print modules at bottom of the logo
|
||||
--logo-recache <?value>: If true, regenerate image logo cache
|
||||
--file <file>: Short for --logo-type file --logo <file>
|
||||
--file-raw <file>: Short for --logo-type file-raw --logo <file>
|
||||
@@ -57,7 +59,9 @@ Logo options:
|
||||
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
|
||||
|
||||
Display options:
|
||||
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
|
||||
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use `fastfetch --list-modules` to see the ones available.
|
||||
--stat <?value>: Show time usage (in ms) for individual modules
|
||||
--pipe <?value>: Disable logo and all escape sequences
|
||||
--color-keys <color>: Set the color of the keys
|
||||
--color-title <color>: Set the color of the title
|
||||
--color <color>: Set the color of both the keys and title
|
||||
@@ -70,7 +74,7 @@ Display options:
|
||||
--disable-linewrap <?value>: Whether to disable line wrap during the run
|
||||
--hide-cursor <?value>: Whether to hide the cursor during the run
|
||||
--binary-prefix <value>: Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 9
|
||||
--percent-ndigits <value>: Set the number of digits to keep after the decimal point when formatting percentage numbers. Default is 0
|
||||
--bar-char-elapsed <str>: Set the character to use in elapsed part. Default is '■'
|
||||
--bar-char-total <str>: Set the character to use in total part. Default is '-'
|
||||
@@ -83,8 +87,8 @@ Display options:
|
||||
|
||||
General module options:
|
||||
--<module>-format <format>: Set the format string to use for each specific module.
|
||||
To see how a format string works, use fastfetch --help format.
|
||||
To see help about a specific format string, use fastfetch --help <module>-format.
|
||||
To see how a format string works, use `fastfetch --help format`.
|
||||
To see help about a specific format string, use `fastfetch --help <module>-format`.
|
||||
|
||||
--<module>-key <key>: Set the key to use for each specific module.
|
||||
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
|
||||
@@ -93,37 +97,39 @@ General module options:
|
||||
--<module>-key-width <num>: Override the global `--key-width` option for each specific module.
|
||||
|
||||
Library options: Set the path of a library to load
|
||||
--lib-PCI <path>
|
||||
--lib-vulkan <path>
|
||||
--lib-wayland <path>
|
||||
--lib-xcb-randr <path>
|
||||
--lib-xcb <path>
|
||||
--lib-Xrandr <path>
|
||||
--lib-X11 <path>
|
||||
--lib-gio <path>
|
||||
--lib-DConf <path>
|
||||
--lib-DBus <path>
|
||||
--lib-XFConf <path>
|
||||
--lib-sqlite3 <path>
|
||||
--lib-rpm <path>
|
||||
--lib-imagemagick <path>
|
||||
--lib-z <path>
|
||||
--lib-chafa <path>
|
||||
--lib-egl <path>
|
||||
--lib-glx <path>
|
||||
--lib-osmesa <path>
|
||||
--lib-opencl <path>
|
||||
--lib-pulse <path>
|
||||
--lib-freetype <path>
|
||||
--lib-ddcutil <path>
|
||||
--lib-PCI <path>: GPU output
|
||||
--lib-vulkan <path>: Vulkan module & fallback for GPU output
|
||||
--lib-wayland <path>: Better display performance and output in wayland sessions
|
||||
--lib-xcb-randr <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-xcb <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-Xrandr <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-X11 <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-gio <path>: Needed for values that are only stored GSettings
|
||||
--lib-DConf <path>: Needed for values that are only stored in DConf + Fallback for GSettings
|
||||
--lib-DBus <path>: Bluetooth, Player & Media detection
|
||||
--lib-XFConf <path>: Needed for XFWM theme and XFCE Terminal font
|
||||
--lib-sqlite3 <path>: Needed for pkg & rpm package count
|
||||
--lib-rpm <path>: Slower fallback for rpm package count
|
||||
--lib-imagemagick <path>: Images in terminal using sixel or kitty graphics protocol
|
||||
--lib-z <path>: Libz. Faster image output when using kitty graphics protocol
|
||||
--lib-chafa <path>: Image output as ascii art
|
||||
--lib-egl <path>: Needed by the OpenGL module for gl context creation
|
||||
--lib-glx <path>: Needed by the OpenGL module for gl context creation
|
||||
--lib-osmesa <path>: Needed by the OpenGL module for gl context creation
|
||||
--lib-opencl <path>: OpenCL module
|
||||
--lib-pulse <path>: Pulseaudio. Used for Sound detection
|
||||
--lib-nm: NetworkManager. Used for Wifi detection
|
||||
--lib-freetype <path>: Used for Termux font detection
|
||||
--lib-ddcutil <path>: Used for brightness detection of external displays
|
||||
|
||||
Module specific options:
|
||||
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||
--title-color-user <color>: Set color of the user name (left part). Default is empty (use color of `--color-title`).
|
||||
--title-color-at <color>: Set color of the @ symbol (middle part). Default is empty (use color of `--color-title`)
|
||||
--title-color-host <color>: Set color of the host name (right part). Default is empty (use color of `--color-title`)
|
||||
--chassis-use-wmi <?value>: Set if WMI query should be used on Windows, which detects more information but slower. Default is false
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS information
|
||||
--os-file <path>: Set the path to the file containing OS information. Linux only
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-show-regular <?value>: Set if regular volume should be printed. Default is true
|
||||
--disk-show-external <?value>: Set if external volume should be printed. Default is true
|
||||
@@ -133,17 +139,21 @@ Module specific options:
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
|
||||
--disk-use-available <?value>: Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false
|
||||
--diskio-name-prefix <str>: Show disks with given name prefix only. Default is empty
|
||||
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
|
||||
--display-compact-type: <?string>: Set if all displays should be printed in one line. Default is none
|
||||
--display-detect-name: <?value>: Set if display name should be detected and printed (if supported). Default is false
|
||||
--display-precise-refresh-rate: <?value>:Set if decimal refresh rates should not be rounded into integers when printing. Default is true
|
||||
--brightness-ddcci-sleep: <num> Set the sleep times (in ms) when sending DDC/CI requests. See <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail. Default is 10
|
||||
--sound-type: <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--bluetooth-show-disconnected <?value>: Set if disconnected bluetooth devices should be printed. Default is false
|
||||
--packages-winget <?value>: Set if winget package count should be detected. Default is false
|
||||
--display-compact-type <?string>: Set if all displays should be printed in one line. Default is none
|
||||
--display-detect-name <?value>: Set if display name should be detected and printed (if supported). Default is false
|
||||
--display-precise-refresh-rate <?value>: Set if decimal refresh rates should not be rounded into integers when printing. Default is true
|
||||
--brightness-ddcci-sleep <num>: Set the sleep times (in ms) when sending DDC/CI requests. See <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail. Default is 10
|
||||
--sound-type <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only
|
||||
--battery-use-setup-api <?value>: Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--cpu-freq-ndigits <num>: Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2
|
||||
--cpuusage-separate <?value>: Display CPU usage per CPU logical core, instead of an average result. Default is false
|
||||
--de-slow-version-detection <?value>: Set if DE version should be detected with slow operations. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-use-nvml <?value>: Use nvml (NVIDIA Management Library) to detect more detailed GPU information (memory usage, CUDA core count, etc). Default is false
|
||||
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
|
||||
--gpu-hide-type <?value>: Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
@@ -152,17 +162,18 @@ Module specific options:
|
||||
--localip-show-mac <?value>: Show mac addresses in local ip module. Default is false
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--localip-name-prefix <str>: Show interfaces with given interface name prefix only. Default is empty
|
||||
--localip-default-route-only <?value>: Show the interface that is used for default routing only. Default is false
|
||||
--localip-default-route-only <?value>: Show the interface that is used for default routing only. Default is true on non-android platforms
|
||||
--localip-compact <?value>: Show all IPs in one line. Default is false
|
||||
--netio-name-prefix <str>: Show interfaces with given name prefix only. Default is empty
|
||||
--netio-default-route-only <?value>: Show the interfac that is used for default routing only. Default is false
|
||||
--publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--publicip-url: The URL of public IP detection server to be used.
|
||||
--weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
|
||||
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||
--player-name: The name of the player to use
|
||||
--opengl-library <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--netio-default-route-only <?value>: Show the interfac that is used for default routing only. Default is true on non-android platforms
|
||||
--publicip-timeout <num>: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--publicip-url <str>: The URL of public IP detection server to be used.
|
||||
--weather-location <str>: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
|
||||
--weather-timeout <num>: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format <str>: The output weather format to be used. It must be URI encoded.
|
||||
--wm-detect-plugin <?value>: Set if window manager plugin should be detected on supported platforms. Default is false
|
||||
--player-name <str>: The name of the player to use for module Media and Player. Linux only
|
||||
--opengl-library <str>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, /bin/sh for *nix
|
||||
--command-key <str>: Set the module key to display
|
||||
--command-text <str>: Set the command text to be executed
|
||||
@@ -172,4 +183,4 @@ Module specific options:
|
||||
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||
If a value starts with a ?, it is optional. "true" will be used if not set.
|
||||
A (+) at the end indicates that more help can be printed with --help <option>
|
||||
All options can be made permanent in $XDG_CONFIG_HOME/fastfetch/config.conf
|
||||
All options can be made permanent with command `fastfetch <options> --migrate-config`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
usage: fastfetch --color <color>
|
||||
Usage: fastfetch --color <color>
|
||||
|
||||
<color> must be a color encoding for linux terminals. It is inserted between "ESC[" and "m".
|
||||
<color> must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m".
|
||||
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||
Examples:
|
||||
--color 35: sets the color to pink
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
usage: fastfetch --load-config <file>
|
||||
Usage: fastfetch -c <file>
|
||||
|
||||
Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.
|
||||
If the file is relative it looks in the following order:
|
||||
|
||||
@@ -1 +1 @@
|
||||
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
|
||||
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:LocalIp:Battery:PowerAdapter:Locale:Break:Colors
|
||||
|
||||
@@ -15,6 +15,7 @@ typedef struct FFBatteryResult
|
||||
double capacity;
|
||||
FFstrbuf status;
|
||||
double temperature;
|
||||
uint32_t cycleCount;
|
||||
} FFBatteryResult;
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results);
|
||||
|
||||
@@ -35,6 +35,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
|
||||
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
|
||||
@@ -5,16 +5,6 @@
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static double detectBatteryTemp(void)
|
||||
{
|
||||
double result = 0;
|
||||
|
||||
if(ffDetectCoreTemps(FF_TEMP_BATTERY, &result))
|
||||
return FF_BATTERY_TEMP_UNSET;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
io_iterator_t iterator;
|
||||
@@ -24,7 +14,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
@@ -35,7 +25,13 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
const char* error;
|
||||
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
battery->capacity = 0.0/0.0;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
|
||||
@@ -50,33 +46,38 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
|
||||
battery->capacity = currentCapacity * 100.0 / maxCapacity;
|
||||
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffCfDictGetString(properties, CFSTR("DeviceName"), &battery->modelName);
|
||||
|
||||
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
|
||||
{
|
||||
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
|
||||
ffStrbufAppendS(&battery->modelName, "Builtin");
|
||||
ffStrbufAppendS(&battery->technology, "Lithium");
|
||||
if (!battery->modelName.length)
|
||||
ffStrbufAppendS(&battery->modelName, "Built-in");
|
||||
}
|
||||
|
||||
ffCfDictGetInt(properties, CFSTR("CycleCount"), (int32_t*) &battery->cycleCount);
|
||||
|
||||
if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "AC connected, ");
|
||||
else
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if (!ffCfDictGetBool(properties, CFSTR("AtCriticalLevel"), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
ffStrbufAppendS(&battery->manufacturer, "Unknown");
|
||||
ffStrbufAppendS(&battery->modelName, "Unknown");
|
||||
ffStrbufAppendS(&battery->technology, "Unknown");
|
||||
int64_t temp;
|
||||
if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp))
|
||||
battery->temperature = (double) temp / 10 - 273.15;
|
||||
else
|
||||
ffDetectCoreTemps(FF_TEMP_BATTERY, &battery->temperature);
|
||||
}
|
||||
|
||||
ffStrbufInit(&battery->status);
|
||||
if (!ffCfDictGetBool(properties, CFSTR("FullyCharged"), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Fully charged");
|
||||
else if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Charging");
|
||||
else
|
||||
ffStrbufAppendS(&battery->status, "");
|
||||
|
||||
battery->temperature = options->temp ? detectBatteryTemp() : FF_BATTERY_TEMP_UNSET;
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io/io.h"
|
||||
#include "battery.h"
|
||||
#include "common/io/io.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static void parseBattery(FFstrbuf* dir, FFlist* results)
|
||||
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
|
||||
@@ -65,7 +65,26 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
|
||||
ffReadFileBuffer(dir->chars, &result->status);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufAppendS(dir, "/cycle_count");
|
||||
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if(dir->length)
|
||||
result->cycleCount = (uint32_t) ffStrbufToUInt(&testBatteryBuffer, 0);
|
||||
|
||||
result->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
if (options->temp)
|
||||
{
|
||||
const FFlist* tempsResult = ffDetectTemps();
|
||||
|
||||
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
|
||||
{
|
||||
if (ffStrbufEqualS(&value->name, id))
|
||||
{
|
||||
result->temperature = value->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
@@ -84,7 +103,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
|
||||
uint32_t baseDirLength = baseDir.length;
|
||||
|
||||
DIR* dirp = opendir(baseDir.chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
|
||||
if(dirp == NULL)
|
||||
return "opendir(batteryDir) == NULL";
|
||||
|
||||
@@ -95,12 +114,10 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&baseDir, entry->d_name);
|
||||
parseBattery(&baseDir, results);
|
||||
parseBattery(&baseDir, entry->d_name, options, results);
|
||||
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
|
||||
if(results->length == 0)
|
||||
return "batteryDir doesn't contain any battery folder";
|
||||
|
||||
|
||||
@@ -30,137 +30,146 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
SetupDiDestroyDeviceInfoList(*hdev);
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
if(instance.config.allowSlowOperations)
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(hdev == INVALID_HANDLE_VALUE)
|
||||
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
|
||||
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(hdev == INVALID_HANDLE_VALUE)
|
||||
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
|
||||
DWORD cbRequired = 0;
|
||||
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
|
||||
if(!pdidd)
|
||||
break; //Out of memory
|
||||
|
||||
pdidd->cbSize = sizeof(*pdidd);
|
||||
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||
continue;
|
||||
|
||||
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
|
||||
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(hBattery == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
|
||||
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
|
||||
|
||||
DWORD dwWait = 0;
|
||||
DWORD dwOut;
|
||||
|
||||
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
|
||||
continue;
|
||||
|
||||
BATTERY_INFORMATION bi = {0};
|
||||
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
|
||||
continue;
|
||||
|
||||
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
|
||||
continue;
|
||||
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
|
||||
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lead Acid");
|
||||
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lithium Ion");
|
||||
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
|
||||
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
|
||||
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Zinc");
|
||||
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
|
||||
else
|
||||
ffStrbufInitS(&battery->technology, "Unknown");
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
|
||||
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
|
||||
{
|
||||
DWORD cbRequired = 0;
|
||||
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
|
||||
if(!pdidd)
|
||||
break; //Out of memory
|
||||
|
||||
pdidd->cbSize = sizeof(*pdidd);
|
||||
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||
continue;
|
||||
|
||||
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
|
||||
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(hBattery == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
|
||||
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
|
||||
|
||||
DWORD dwWait = 0;
|
||||
DWORD dwOut;
|
||||
|
||||
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
|
||||
continue;
|
||||
|
||||
BATTERY_INFORMATION bi = {0};
|
||||
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
|
||||
continue;
|
||||
|
||||
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
|
||||
continue;
|
||||
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
|
||||
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lead Acid");
|
||||
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lithium Ion");
|
||||
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
|
||||
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
|
||||
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Zinc");
|
||||
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
|
||||
else
|
||||
ffStrbufInitS(&battery->technology, "Unknown");
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->modelName);
|
||||
bqi.InformationLevel = BatteryDeviceName;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffStrbufSetWS(&battery->modelName, name);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
bqi.InformationLevel = BatteryManufactureName;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffStrbufSetWS(&battery->manufacturer, name);
|
||||
}
|
||||
|
||||
battery->temperature = 0.0/0.0;
|
||||
if(options->temp)
|
||||
{
|
||||
bqi.InformationLevel = BatteryTemperature;
|
||||
ULONG temp;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
|
||||
battery->temperature = temp;
|
||||
}
|
||||
|
||||
{
|
||||
BATTERY_STATUS bs;
|
||||
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
|
||||
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
|
||||
else
|
||||
battery->capacity = 0;
|
||||
|
||||
ffStrbufInit(&battery->status);
|
||||
if(bs.PowerState & BATTERY_POWER_ON_LINE)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||
if(bs.PowerState & BATTERY_DISCHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if(bs.PowerState & BATTERY_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging");
|
||||
if(bs.PowerState & BATTERY_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SYSTEM_BATTERY_STATE info;
|
||||
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
|
||||
{
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
battery->temperature = 0.0/0.0;
|
||||
bqi.InformationLevel = BatteryDeviceName;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffStrbufSetWS(&battery->modelName, name);
|
||||
}
|
||||
|
||||
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
|
||||
if(info.AcOnLine)
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
if(info.Charging)
|
||||
ffStrbufAppendS(&battery->status, ", Charging");
|
||||
}
|
||||
else if(info.Discharging)
|
||||
ffStrbufAppendS(&battery->status, "Discharging");
|
||||
{
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
bqi.InformationLevel = BatteryManufactureName;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffStrbufSetWS(&battery->manufacturer, name);
|
||||
}
|
||||
|
||||
battery->cycleCount = bi.CycleCount;
|
||||
|
||||
battery->temperature = 0.0/0.0;
|
||||
if(options->temp)
|
||||
{
|
||||
bqi.InformationLevel = BatteryTemperature;
|
||||
ULONG temp;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
|
||||
battery->temperature = temp;
|
||||
}
|
||||
|
||||
{
|
||||
BATTERY_STATUS bs;
|
||||
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
|
||||
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
|
||||
else
|
||||
battery->capacity = 0;
|
||||
|
||||
ffStrbufInit(&battery->status);
|
||||
if(bs.PowerState & BATTERY_POWER_ON_LINE)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||
if(bs.PowerState & BATTERY_DISCHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if(bs.PowerState & BATTERY_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if(bs.PowerState & BATTERY_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
SYSTEM_BATTERY_STATE info;
|
||||
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
|
||||
{
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
battery->temperature = 0.0/0.0;
|
||||
battery->cycleCount = 0;
|
||||
|
||||
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
|
||||
if(info.AcOnLine)
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
if(info.Charging)
|
||||
ffStrbufAppendS(&battery->status, ", Charging");
|
||||
}
|
||||
else if(info.Discharging)
|
||||
ffStrbufAppendS(&battery->status, "Discharging");
|
||||
return NULL;
|
||||
}
|
||||
return "NtPowerInformation(SystemBatteryState) failed";
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
return true
|
||||
? detectWithSetupApi(options, results)
|
||||
: detectWithNtApi(options, results);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef struct FFBiosResult
|
||||
FFstrbuf release;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf version;
|
||||
FFstrbuf type;
|
||||
} FFBiosResult;
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios);
|
||||
|
||||
@@ -9,5 +9,7 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
if (ffStrbufIgnCaseEqualS(&bios->version, "unknown"))
|
||||
ffStrbufClear(&bios->version);
|
||||
|
||||
ffStrbufSetStatic(&bios->type, "Bootloader");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
ffCfDictGetString(properties, CFSTR("vendor"), &bios->vendor);
|
||||
ffCfDictGetString(properties, CFSTR("version"), &bios->version);
|
||||
ffCfDictGetString(properties, CFSTR("release-date"), &bios->date);
|
||||
ffStrbufAppendS(&bios->release, "Efi");
|
||||
ffStrbufSetStatic(&bios->type, "UEFI");
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
@@ -54,12 +54,12 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
uint32_t index = ffStrbufFirstIndexC(&bios->version, '-');
|
||||
if (index != bios->version.length)
|
||||
{
|
||||
ffStrbufAppendNS(&bios->release, index, bios->version.chars);
|
||||
ffStrbufAppendNS(&bios->type, index, bios->version.chars);
|
||||
ffStrbufRemoveSubstr(&bios->version, 0, index + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendS(&bios->release, "iBoot");
|
||||
ffStrbufSetStatic(&bios->type, "iBoot");
|
||||
}
|
||||
CFRelease(properties);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "bios.h"
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* result)
|
||||
@@ -13,5 +14,6 @@ const char* ffDetectBios(FFBiosResult* result)
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
ffSettingsGetFreeBSDKenv("smbios.bios.version", &result->version);
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
ffSysctlGetString("machdep.bootmethod", &result->type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -23,5 +23,9 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor);
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version);
|
||||
if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE))
|
||||
ffStrbufSetStatic(&bios->type, "UEFI");
|
||||
else
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,30 @@
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
|
||||
{
|
||||
GUID BootIdentifier;
|
||||
FIRMWARE_TYPE FirmwareType;
|
||||
union
|
||||
{
|
||||
ULONGLONG BootFlags;
|
||||
struct
|
||||
{
|
||||
ULONGLONG DbgMenuOsSelection : 1; // REDSTONE4
|
||||
ULONGLONG DbgHiberBoot : 1;
|
||||
ULONGLONG DbgSoftBoot : 1;
|
||||
ULONGLONG DbgMeasuredLaunch : 1;
|
||||
ULONGLONG DbgMeasuredLaunchCapable : 1; // 19H1
|
||||
ULONGLONG DbgSystemHiveReplace : 1;
|
||||
ULONGLONG DbgMeasuredLaunchSmmProtections : 1;
|
||||
ULONGLONG DbgMeasuredLaunchSmmLevel : 7; // 20H1
|
||||
};
|
||||
};
|
||||
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
@@ -24,5 +48,18 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
)
|
||||
ffStrbufAppendF(&bios->release, "%u.%u", (unsigned)major, (unsigned)minor);
|
||||
|
||||
// Same as GetFirmwareType, but support (?) Windows 7
|
||||
// https://ntdoc.m417z.com/system_information_class
|
||||
SYSTEM_BOOT_ENVIRONMENT_INFORMATION sbei;
|
||||
if (NT_SUCCESS(NtQuerySystemInformation(90 /*SystemBootEnvironmentInformation*/, &sbei, sizeof(sbei), NULL)))
|
||||
{
|
||||
switch (sbei.FirmwareType)
|
||||
{
|
||||
case FirmwareTypeBios: ffStrbufSetStatic(&bios->type, "BIOS"); break;
|
||||
case FirmwareTypeUefi: ffStrbufSetStatic(&bios->type, "UEFI"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ double ddca_set_default_sleep_multiplier(double multiplier); // ddcutil 1.4
|
||||
|
||||
static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
|
||||
FF_LIBRARY_LOAD(libddcutil, &instance.config.library.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type)
|
||||
|
||||
@@ -12,7 +12,7 @@ typedef struct FFChassisResult
|
||||
FFstrbuf version;
|
||||
} FFChassisResult;
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result);
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options);
|
||||
const char* ffChassisTypeToString(uint32_t type);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "common/settings.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
{
|
||||
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
|
||||
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
|
||||
|
||||
@@ -17,7 +17,7 @@ static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstr
|
||||
ffStrbufClear(buffer);
|
||||
}
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
{
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "chassis.h"
|
||||
|
||||
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
|
||||
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
{
|
||||
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
|
||||
if(len == 0)
|
||||
return "ChassisTypes contain no data failed";
|
||||
return "ChassisTypes contain no data";
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
@@ -65,9 +65,9 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
|
||||
{
|
||||
if (instance.config.allowSlowOperations)
|
||||
if (options->useWmi)
|
||||
return detectWithWmi(result);
|
||||
return detectWithRegistry(result);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
ffParsePropLine(line, "isa :", cpuIsa) ||
|
||||
ffParsePropLine(line, "uarch :", cpuUarch) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) //For POWER
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,12 +83,10 @@ static double getFrequency(const char* info, const char* scaling)
|
||||
|
||||
static double detectCPUTemp(void)
|
||||
{
|
||||
const FFTempsResult* temps = ffDetectTemps();
|
||||
const FFlist* tempsResult = ffDetectTemps();
|
||||
|
||||
for(uint32_t i = 0; i < temps->values.length; i++)
|
||||
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
|
||||
{
|
||||
FFTempValue* value = ffListGet(&temps->values, i);
|
||||
|
||||
if(
|
||||
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
|
||||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
|
||||
@@ -115,6 +114,10 @@ static void parseIsa(FFstrbuf* cpuIsa)
|
||||
}
|
||||
// The final ISA output of the above example is "rv64gch".
|
||||
}
|
||||
if(ffStrbufStartsWithS(cpuIsa, "mips"))
|
||||
{
|
||||
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
@@ -27,6 +27,7 @@ const char* ffGetCpuUsageResult(FFlist* result)
|
||||
if(cpuTimes1.length == 0) return "No CPU cores found";
|
||||
|
||||
FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo));
|
||||
uint32_t retryCount = 0;
|
||||
|
||||
retry:
|
||||
error = ffGetCpuUsageInfo(&cpuTimes2);
|
||||
@@ -39,9 +40,12 @@ retry:
|
||||
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
|
||||
if (cpuTime2->totalAll <= cpuTime1->totalAll)
|
||||
{
|
||||
ffListClear(&cpuTimes2);
|
||||
ffTimeSleep(200);
|
||||
goto retry;
|
||||
if (++retryCount <= 3)
|
||||
{
|
||||
ffListClear(&cpuTimes2);
|
||||
ffTimeSleep(200);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options);
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "de.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
}
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
"plasmashell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // plasmashell 5.27.5
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getGnome(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gnome-shell/org.gnome.Extensions", "version :", result);
|
||||
|
||||
if (result->length == 0)
|
||||
{
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
"gnome-shell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // GNOME Shell 44.1
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getCinnamon(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", result);
|
||||
}
|
||||
|
||||
static void getMate(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY major = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY minor = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY micro = ffStrbufCreate();
|
||||
|
||||
ffParsePropFileDataValues("mate-about/mate-version.xml", 3, (FFpropquery[]) {
|
||||
{"<platform>", &major},
|
||||
{"<minor>", &minor},
|
||||
{"<micro>", µ}
|
||||
});
|
||||
|
||||
ffParseSemver(result, &major, &minor, µ);
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
ffProcessAppendStdOut(result, (char* const[]){
|
||||
"mate-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrAfterFirstC(result, ' ');
|
||||
ffStrbufTrim(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getXFCE4(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", result);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if(result->length == 0)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/");
|
||||
if (dirp)
|
||||
{
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5]))
|
||||
continue;
|
||||
ffStrbufAppendS(result, &entry->d_name[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
//This is somewhat slow
|
||||
ffProcessAppendStdOut(result, (char* const[]){
|
||||
"xfce4-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(result, '(');
|
||||
ffStrbufSubstrAfterFirstC(result, ' ');
|
||||
ffStrbufTrim(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getLXQt(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gconfig/lxqt.pc", "Version:", result);
|
||||
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", result);
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
//This is really, really, really slow. Thank you, LXQt developers
|
||||
ffProcessAppendStdOut(result, (char* const[]){
|
||||
"lxqt-session",
|
||||
"-v",
|
||||
NULL
|
||||
});
|
||||
|
||||
result->length = 0; //don't set '\0' byte
|
||||
ffParsePropLines(result->chars , "liblxqt", result);
|
||||
}
|
||||
}
|
||||
|
||||
static void getBudgie(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("budgie/budgie-version.xml", "<str>", result);
|
||||
}
|
||||
|
||||
const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
if (ffStrbufEqualS(deName, FF_DE_PRETTY_PLASMA))
|
||||
getKDE(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_GNOME) || ffStrbufEqualS(deName, FF_DE_PRETTY_GNOME))
|
||||
getGnome(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_CINNAMON))
|
||||
getCinnamon(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_XFCE4))
|
||||
getXFCE4(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_MATE))
|
||||
getMate(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_LXQT))
|
||||
getLXQt(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_BUDGIE))
|
||||
getBudgie(result, options);
|
||||
else
|
||||
return "Unsupported DE";
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "de.h"
|
||||
|
||||
const char* ffDetectDEVersion(FF_MAYBE_UNUSED const FFstrbuf* deName, FF_MAYBE_UNUSED FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -68,7 +68,6 @@ typedef struct FFDisplayServerResult
|
||||
FFstrbuf wmProtocolName;
|
||||
FFstrbuf deProcessName;
|
||||
FFstrbuf dePrettyName;
|
||||
FFstrbuf deVersion;
|
||||
FFlist displays; //List of FFDisplayResult
|
||||
} FFDisplayServerResult;
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
|
||||
{
|
||||
// Only for MiUI
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
;
|
||||
|
||||
if (ffSettingsGetAndroidProperty("persist.sys.miui_resolution", &buffer) &&
|
||||
ffStrbufContainC(&buffer, ','))
|
||||
{
|
||||
@@ -107,7 +107,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 0);
|
||||
|
||||
if (!detectWithGetprop(ds))
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "displayserver.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <CoreGraphics/CGDirectDisplay.h>
|
||||
@@ -70,35 +67,6 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
}
|
||||
}
|
||||
|
||||
static void detectWMPlugin(FFstrbuf* name)
|
||||
{
|
||||
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
|
||||
u_int requestLength = sizeof(request) / sizeof(*request);
|
||||
|
||||
size_t length = 0;
|
||||
FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length);
|
||||
if(processes == NULL)
|
||||
return;
|
||||
|
||||
for(size_t i = 0; i < length / sizeof(struct kinfo_proc); i++)
|
||||
{
|
||||
const char* comm = processes[i].kp_proc.p_comm;
|
||||
|
||||
if(
|
||||
strcasecmp(comm, "spectacle") != 0 &&
|
||||
strcasecmp(comm, "amethyst") != 0 &&
|
||||
strcasecmp(comm, "kwm") != 0 &&
|
||||
strcasecmp(comm, "chunkwm") != 0 &&
|
||||
strcasecmp(comm, "yabai") != 0 &&
|
||||
strcasecmp(comm, "rectangle") != 0
|
||||
) continue;
|
||||
|
||||
ffStrbufAppendS(name, comm);
|
||||
name->chars[0] = (char) toupper(name->chars[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
{
|
||||
{
|
||||
@@ -116,18 +84,8 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
}
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
|
||||
if(instance.config.allowSlowOperations)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY name;
|
||||
ffStrbufInit(&name);
|
||||
detectWMPlugin(&name);
|
||||
if(name.length)
|
||||
ffStrbufAppendF(&ds->wmPrettyName, " (with %s)", name.chars);
|
||||
}
|
||||
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInitStatic(&ds->dePrettyName, "Aqua");
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
|
||||
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
|
||||
detectDisplays(ds);
|
||||
|
||||
@@ -143,20 +143,21 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
{
|
||||
BOOL enabled;
|
||||
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled == TRUE)
|
||||
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
|
||||
{
|
||||
ffStrbufInitStatic(&ds->wmProcessName, "dwm.exe");
|
||||
ffStrbufInitStatic(&ds->wmPrettyName, "Desktop Window Manager");
|
||||
}
|
||||
else
|
||||
{
|
||||
// `explorer.exe` only provides a subset of WM functions, as well as the taskbar and desktop icons.
|
||||
// While a window itself is drawn by kernel (GDI). Killing `explorer.exe` won't affect how windows are displayed generally.
|
||||
ffStrbufInitStatic(&ds->wmProcessName, "explorer.exe");
|
||||
ffStrbufInitStatic(&ds->wmPrettyName, "Windows Explorer");
|
||||
ffStrbufInitStatic(&ds->wmPrettyName, "Internal");
|
||||
}
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInit(&ds->displays, sizeof(FFDisplayResult));
|
||||
|
||||
detectDisplays(ds);
|
||||
|
||||
@@ -85,10 +85,9 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
|
||||
|
||||
if (!instance.config.dsForceDrm)
|
||||
if (!instance.config.general.dsForceDrm)
|
||||
{
|
||||
//We try wayland as our prefered display server, as it supports the most features.
|
||||
//This method can't detect the name of our WM / DE
|
||||
|
||||
@@ -202,9 +202,6 @@ static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* regist
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
return;
|
||||
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
@@ -262,8 +259,6 @@ static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* regist
|
||||
ffStrbufDestroy(&display.vendorAndModelId);
|
||||
ffStrbufDestroy(&display.name);
|
||||
ffStrbufDestroy(&display.edidName);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
}
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
@@ -276,7 +271,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
|
||||
|
||||
bool detectWayland(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(wayland, &instance.config.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
@@ -131,177 +130,6 @@ static void applyBetterWM(FFDisplayServerResult* result, const char* processName
|
||||
ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName);
|
||||
}
|
||||
|
||||
static void getKDE(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "plasmashell");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
|
||||
|
||||
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", &result->deVersion}
|
||||
});
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", &result->deVersion}
|
||||
});
|
||||
}
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
{
|
||||
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"plasmashell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // plasmashell 5.27.5
|
||||
ffStrbufSubstrAfterLastC(&result->deVersion, ' ');
|
||||
}
|
||||
|
||||
|
||||
applyBetterWM(result, getenv("KDEWM"));
|
||||
}
|
||||
|
||||
static void getGnome(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "gnome-shell");
|
||||
const char* sessionMode = getenv("GNOME_SHELL_SESSION_MODE");
|
||||
if (sessionMode && ffStrEquals(sessionMode, "classic"))
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC);
|
||||
else
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME);
|
||||
|
||||
ffParsePropFileData("gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
|
||||
|
||||
if (result->deVersion.length == 0)
|
||||
{
|
||||
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"gnome-shell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // GNOME Shell 44.1
|
||||
ffStrbufSubstrAfterLastC(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getCinnamon(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "cinnamon");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
|
||||
ffParsePropFileData("applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
|
||||
}
|
||||
|
||||
static void getMate(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "mate-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY major = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY minor = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY micro = ffStrbufCreate();
|
||||
|
||||
ffParsePropFileDataValues("mate-about/mate-version.xml", 3, (FFpropquery[]) {
|
||||
{"<platform>", &major},
|
||||
{"<minor>", &minor},
|
||||
{"<micro>", µ}
|
||||
});
|
||||
|
||||
ffParseSemver(&result->deVersion, &major, &minor, µ);
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
{
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"mate-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
|
||||
ffStrbufTrim(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getXFCE4(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "xfce4-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
|
||||
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if(result->deVersion.length == 0)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/");
|
||||
if (dirp)
|
||||
{
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5]))
|
||||
continue;
|
||||
ffStrbufAppendS(&result->deVersion, &entry->d_name[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
{
|
||||
//This is somewhat slow
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"xfce4-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(&result->deVersion, '(');
|
||||
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
|
||||
ffStrbufTrim(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getLXQt(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "lxqt-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
|
||||
ffParsePropFileData("gconfig/lxqt.pc", "Version:", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
{
|
||||
//This is really, really, really slow. Thank you, LXQt developers
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"lxqt-session",
|
||||
"-v",
|
||||
NULL
|
||||
});
|
||||
|
||||
result->deVersion.length = 0; //don't set '\0' byte
|
||||
ffParsePropLines(result->deVersion.chars , "liblxqt", &result->deVersion);
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY wmProcessNameBuffer = ffStrbufCreate();
|
||||
|
||||
ffParsePropFileConfig("lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
|
||||
applyBetterWM(result, wmProcessNameBuffer.chars);
|
||||
}
|
||||
|
||||
static void getBudgie(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
|
||||
ffParsePropFileData("budgie/budgie-version.xml", "<str>", &result->deVersion);
|
||||
}
|
||||
|
||||
static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
|
||||
{
|
||||
if(!ffStrSet(name))
|
||||
@@ -312,19 +140,33 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
|
||||
strcasecmp(name, "plasma") == 0 ||
|
||||
strcasecmp(name, "plasmashell") == 0 ||
|
||||
strcasecmp(name, "plasmawayland") == 0
|
||||
) getKDE(result);
|
||||
) {
|
||||
ffStrbufSetStatic(&result->deProcessName, "plasmashell");
|
||||
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
|
||||
applyBetterWM(result, getenv("KDEWM"));
|
||||
}
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "Gnome") == 0 ||
|
||||
strcasecmp(name, "ubuntu:GNOME") == 0 ||
|
||||
strcasecmp(name, "ubuntu") == 0 ||
|
||||
strcasecmp(name, "gnome-shell") == 0
|
||||
) getGnome(result);
|
||||
) {
|
||||
ffStrbufSetStatic(&result->deProcessName, "gnome-shell");
|
||||
const char* sessionMode = getenv("GNOME_SHELL_SESSION_MODE");
|
||||
if (sessionMode && ffStrEquals(sessionMode, "classic"))
|
||||
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC);
|
||||
else
|
||||
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_GNOME);
|
||||
}
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "X-Cinnamon") == 0 ||
|
||||
strcasecmp(name, "Cinnamon") == 0
|
||||
) getCinnamon(result);
|
||||
) {
|
||||
ffStrbufSetS(&result->deProcessName, "cinnamon");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
|
||||
}
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "XFCE") == 0 ||
|
||||
@@ -332,26 +174,41 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
|
||||
strcasecmp(name, "XFCE4") == 0 ||
|
||||
strcasecmp(name, "X-XFCE4") == 0 ||
|
||||
strcasecmp(name, "xfce4-session") == 0
|
||||
) getXFCE4(result);
|
||||
) {
|
||||
ffStrbufSetS(&result->deProcessName, "xfce4-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
|
||||
}
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "MATE") == 0 ||
|
||||
strcasecmp(name, "X-MATE") == 0 ||
|
||||
strcasecmp(name, "mate-session") == 0
|
||||
) getMate(result);
|
||||
) {
|
||||
ffStrbufSetS(&result->deProcessName, "mate-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
|
||||
}
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "LXQt") == 0 ||
|
||||
strcasecmp(name, "X-LXQT") == 0 ||
|
||||
strcasecmp(name, "lxqt-session") == 0
|
||||
) getLXQt(result);
|
||||
) {
|
||||
ffStrbufSetS(&result->deProcessName, "lxqt-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
|
||||
FF_STRBUF_AUTO_DESTROY wmProcessNameBuffer = ffStrbufCreate();
|
||||
ffParsePropFileConfig("lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
|
||||
applyBetterWM(result, wmProcessNameBuffer.chars);
|
||||
}
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "Budgie") == 0 ||
|
||||
strcasecmp(name, "X-Budgie") == 0 ||
|
||||
strcasecmp(name, "budgie-desktop") == 0 ||
|
||||
strcasecmp(name, "Budgie:GNOME") == 0
|
||||
) getBudgie(result);
|
||||
) {
|
||||
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
|
||||
}
|
||||
}
|
||||
|
||||
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
|
||||
|
||||
@@ -100,7 +100,7 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect
|
||||
|
||||
void ffdsConnectXcb(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xcb, &instance.config.libXcb, , "libxcb" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD(xcb, &instance.config.library.libXcb, , "libxcb" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_connect,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_get_setup,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_setup_roots_iterator,)
|
||||
@@ -429,7 +429,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
|
||||
|
||||
void ffdsConnectXcbRandr(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xcbRandr, &instance.config.libXcbRandr, , "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD(xcbRandr, &instance.config.library.libXcbRandr, , "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_connect,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_get_setup,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_setup_roots_iterator,)
|
||||
|
||||
@@ -60,7 +60,7 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl
|
||||
|
||||
void ffdsConnectXlib(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(x11, &instance.config.libX11, , "libX11" FF_LIBRARY_EXTENSION, 7, "libX11-xcb" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD(x11, &instance.config.library.libX11, , "libX11" FF_LIBRARY_EXTENSION, 7, "libX11-xcb" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XOpenDisplay,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay,)
|
||||
|
||||
@@ -338,7 +338,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
|
||||
void ffdsConnectXrandr(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xrandr, &instance.config.libXrandr, , "libXrandr" FF_LIBRARY_EXTENSION, 3)
|
||||
FF_LIBRARY_LOAD(xrandr, &instance.config.library.libXrandr, , "libXrandr" FF_LIBRARY_EXTENSION, 3)
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(xrandr, XOpenDisplay,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xrandr, XCloseDisplay,)
|
||||
|
||||
@@ -6,6 +6,11 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
|
||||
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
|
||||
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
|
||||
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
|
||||
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
|
||||
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
|
||||
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
|
||||
const char* FF_GPU_VENDOR_NAME_REDHAT = "RedHat";
|
||||
const char* FF_GPU_VENDOR_NAME_ORACLE = "Oracle";
|
||||
|
||||
static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsigned length)
|
||||
{
|
||||
@@ -19,6 +24,7 @@ static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsign
|
||||
|
||||
const char* ffGetGPUVendorString(unsigned vendorId)
|
||||
{
|
||||
// https://devicehunt.com/all-pci-vendors
|
||||
if(vendorId == 0x106b)
|
||||
return FF_GPU_VENDOR_NAME_APPLE;
|
||||
if(arrayContains((const unsigned[]) {0x1002, 0x1022}, vendorId, 2))
|
||||
@@ -27,6 +33,16 @@ const char* ffGetGPUVendorString(unsigned vendorId)
|
||||
return FF_GPU_VENDOR_NAME_INTEL;
|
||||
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
|
||||
return FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
else if(arrayContains((const unsigned[]) {0x15ad}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_VMWARE;
|
||||
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_REDHAT;
|
||||
else if(arrayContains((const unsigned[]) {0x1ab8}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_PARALLEL;
|
||||
else if(arrayContains((const unsigned[]) {0x1414}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_MICROSOFT;
|
||||
else if(arrayContains((const unsigned[]) {0x108e}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_ORACLE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ extern const char* FF_GPU_VENDOR_NAME_APPLE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_AMD;
|
||||
extern const char* FF_GPU_VENDOR_NAME_INTEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
|
||||
extern const char* FF_GPU_VENDOR_NAME_REDHAT;
|
||||
extern const char* FF_GPU_VENDOR_NAME_ORACLE;
|
||||
|
||||
typedef struct FFGPUMemory
|
||||
{
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/gpu/gpu_nvidia.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
@@ -35,7 +37,7 @@ typedef struct PCIData
|
||||
|
||||
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
@@ -45,11 +47,11 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
|
||||
ffStrbufRecalculateLength(&gpu->vendor);
|
||||
|
||||
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
}
|
||||
|
||||
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
@@ -110,34 +112,36 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
pci->ffpci_fill_info(device, PCI_FILL_DRIVER);
|
||||
ffStrbufAppendS(&gpu->driver, pci->ffpci_get_string_property(device, PCI_FILL_DRIVER));
|
||||
|
||||
if(gpu->driver.length > 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
if (gpu->driver.length == 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppendS(&path, "/module/version");
|
||||
ffAppendFileBuffer(path.chars, &gpu->driver);
|
||||
ffStrbufTrimRight(&gpu->driver, ' ');
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device)
|
||||
{
|
||||
const FFTempsResult* tempsResult = ffDetectTemps();
|
||||
const FFlist* tempsResult = ffDetectTemps();
|
||||
|
||||
for(uint32_t i = 0; i < tempsResult->values.length; i++)
|
||||
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
|
||||
{
|
||||
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
|
||||
|
||||
//The kernel exposes the device class multiplied by 256 for some reason
|
||||
if(tempValue->deviceClass == device->device_class * 256)
|
||||
{
|
||||
@@ -236,8 +240,23 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml))
|
||||
{
|
||||
char pciDeviceId[32];
|
||||
snprintf(pciDeviceId, sizeof(pciDeviceId) - 1, "%04x:%02x:%02x.%d", device->domain, device->bus, device->dev, device->func);
|
||||
|
||||
ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) { .pciBusId = pciDeviceId }, (FFGpuNvidiaResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->useNvml ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
}, "libnvidia-ml.so");
|
||||
|
||||
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if(options->temp)
|
||||
if(options->temp && gpu->temperature != gpu->temperature)
|
||||
pciDetectTemp(gpu, device);
|
||||
#endif
|
||||
}
|
||||
@@ -270,7 +289,7 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
PCIData pci;
|
||||
|
||||
FF_LIBRARY_LOAD(libpci, &instance.config.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(libpci, &instance.config.library.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_alloc);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_init);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_scan_bus);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "gpu_nvidia.h"
|
||||
|
||||
#include "3rdparty/nvml/nvml.h"
|
||||
#include "common/library.h"
|
||||
|
||||
struct FFNvmlData {
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetCount_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByIndex_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByPciBusId_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetPciInfo_v3)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
|
||||
|
||||
bool inited;
|
||||
} nvmlData;
|
||||
|
||||
const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult result, const char* soName)
|
||||
{
|
||||
if (!nvmlData.inited)
|
||||
{
|
||||
nvmlData.inited = true;
|
||||
FF_LIBRARY_LOAD(libnvml, NULL, "dlopen nvml failed", soName , 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlInit_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlShutdown)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCount_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByIndex_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByPciBusId_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetPciInfo_v3)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
|
||||
|
||||
if (ffnvmlInit_v2() != NVML_SUCCESS)
|
||||
{
|
||||
nvmlData.ffnvmlDeviceGetNumGpuCores = NULL;
|
||||
return "nvmlInit_v2() failed";
|
||||
}
|
||||
atexit((void*) ffnvmlShutdown);
|
||||
libnvml = NULL; // don't close nvml
|
||||
}
|
||||
|
||||
if (nvmlData.ffnvmlDeviceGetNumGpuCores == NULL)
|
||||
return "loading nvml library failed";
|
||||
|
||||
nvmlDevice_t device = NULL;
|
||||
if (cond.pciBusId)
|
||||
{
|
||||
nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(cond.pciBusId, &device);
|
||||
if (ret != NVML_SUCCESS)
|
||||
return "nvmlDeviceGetHandleByPciBusId_v2() failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t count;
|
||||
if (nvmlData.ffnvmlDeviceGetCount_v2(&count) != NVML_SUCCESS)
|
||||
return "nvmlDeviceGetCount_v2() failed";
|
||||
|
||||
for (uint32_t i = 0; i < count; i++, device = NULL)
|
||||
{
|
||||
if (nvmlData.ffnvmlDeviceGetHandleByIndex_v2(i, &device) != NVML_SUCCESS)
|
||||
continue;
|
||||
|
||||
nvmlPciInfo_t pciInfo;
|
||||
if (nvmlData.ffnvmlDeviceGetPciInfo_v3(device, &pciInfo) != NVML_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (pciInfo.pciDeviceId != cond.pciDeviceId || pciInfo.pciSubSystemId != cond.pciSubSystemId)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
if (!device) return "Device not found";
|
||||
}
|
||||
|
||||
if (result.temp)
|
||||
{
|
||||
uint32_t value;
|
||||
if (nvmlData.ffnvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &value) == NVML_SUCCESS)
|
||||
*result.temp = value;
|
||||
}
|
||||
|
||||
if (result.memory)
|
||||
{
|
||||
nvmlMemory_v2_t memory = { .version = nvmlMemory_v2 };
|
||||
if (nvmlData.ffnvmlDeviceGetMemoryInfo_v2(device, &memory) == NVML_SUCCESS)
|
||||
{
|
||||
result.memory->total = memory.used + memory.free;
|
||||
result.memory->used = memory.used;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.coreCount)
|
||||
nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "gpu.h"
|
||||
|
||||
// Use pciBusId if not NULL; use pciDeviceId and pciSubSystemId otherwise
|
||||
typedef struct FFGpuNvidiaCondition
|
||||
{
|
||||
// "domain:bus:device.function"
|
||||
const char* pciBusId;
|
||||
// (deviceId << 16) | vendorId
|
||||
uint32_t pciDeviceId;
|
||||
uint32_t pciSubSystemId;
|
||||
} FFGpuNvidiaCondition;
|
||||
|
||||
// detect x if not NULL
|
||||
typedef struct FFGpuNvidiaResult
|
||||
{
|
||||
double* temp;
|
||||
FFGPUMemory* memory;
|
||||
uint32_t* coreCount;
|
||||
} FFGpuNvidiaResult;
|
||||
|
||||
const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult result, const char* soName);
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/gpu/gpu_nvidia.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
@@ -12,9 +13,11 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) };
|
||||
wchar_t regKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
|
||||
const uint32_t regKeyPrefixLength = (uint32_t) wcslen(regKey);
|
||||
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regKeyPrefixLength;
|
||||
wchar_t regDirectxKey[MAX_PATH] = L"SOFTWARE\\Microsoft\\DirectX\\{";
|
||||
const uint32_t regDirectxKeyPrefixLength = (uint32_t) wcslen(regDirectxKey);
|
||||
wchar_t regControlVideoKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
|
||||
const uint32_t regControlVideoKeyPrefixLength = (uint32_t) wcslen(regControlVideoKey);
|
||||
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regControlVideoKeyPrefixLength;
|
||||
|
||||
for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i)
|
||||
{
|
||||
@@ -43,27 +46,61 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
|
||||
if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{')
|
||||
{
|
||||
wmemcpy(regKey + regKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, 100 - regKeyPrefixLength + 1);
|
||||
wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}\\0000"));
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regKey, &hKey, NULL)) continue;
|
||||
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue;
|
||||
|
||||
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
|
||||
ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL);
|
||||
|
||||
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
|
||||
if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
|
||||
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}"));
|
||||
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
|
||||
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
|
||||
{
|
||||
uint64_t dedicatedVideoMemory = 0;
|
||||
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
|
||||
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
|
||||
uint64_t dedicatedSystemMemory, sharedSystemMemory;
|
||||
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
|
||||
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
|
||||
{
|
||||
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
|
||||
gpu->shared.total = sharedSystemMemory;
|
||||
}
|
||||
}
|
||||
else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
|
||||
{
|
||||
uint32_t vmem = 0;
|
||||
if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL))
|
||||
gpu->dedicated.total = vmem;
|
||||
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml))
|
||||
{
|
||||
uint32_t vendorId, deviceId, subSystemId;
|
||||
// See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html
|
||||
// displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1"
|
||||
if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x", &vendorId, &deviceId, &subSystemId) == 3)
|
||||
{
|
||||
ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) {
|
||||
.pciDeviceId = (deviceId << 16) | vendorId,
|
||||
.pciSubSystemId = subSystemId,
|
||||
}, (FFGpuNvidiaResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->useNvml ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
}, "nvml.dll");
|
||||
}
|
||||
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
extern "C" {
|
||||
#include "common/library.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/gpu/gpu_nvidia.h"
|
||||
}
|
||||
|
||||
#include <wsl/winadapter.h>
|
||||
@@ -92,7 +93,20 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId)))
|
||||
{
|
||||
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
|
||||
ffStrbufAppendS(&gpu->vendor, vendorStr);
|
||||
ffStrbufSetStatic(&gpu->vendor, vendorStr);
|
||||
|
||||
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->useNvml)
|
||||
{
|
||||
ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) {
|
||||
.pciBusId = nullptr,
|
||||
.pciDeviceId = (hardwareId.deviceID << 16) | hardwareId.vendorID,
|
||||
.pciSubSystemId = hardwareId.subSysID
|
||||
}, (FFGpuNvidiaResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->useNvml ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ static inline void applyGTKSettings(FFGTKResult* result, const char* themeName,
|
||||
|
||||
static void detectGTKFromSettings(FFGTKResult* result)
|
||||
{
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static const char* themeName = NULL;
|
||||
static const char* iconsName = NULL;
|
||||
static const char* fontName = NULL;
|
||||
@@ -47,11 +45,8 @@ static void detectGTKFromSettings(FFGTKResult* result)
|
||||
|
||||
static bool init = false;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
if(init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
|
||||
return;
|
||||
}
|
||||
@@ -103,7 +98,6 @@ static void detectGTKFromSettings(FFGTKResult* result)
|
||||
wallpaper = ffSettingsGet("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
}
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
|
||||
}
|
||||
|
||||
@@ -178,14 +172,10 @@ static void detectGTK(const char* version, FFGTKResult* result)
|
||||
}
|
||||
|
||||
#define FF_DETECT_GTK_IMPL(version) \
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
|
||||
static FFGTKResult result; \
|
||||
static bool init = false; \
|
||||
ffThreadMutexLock(&mutex); \
|
||||
if(init){ \
|
||||
ffThreadMutexUnlock(&mutex);\
|
||||
if(init) \
|
||||
return &result; \
|
||||
} \
|
||||
init = true; \
|
||||
ffStrbufInit(&result.theme); \
|
||||
ffStrbufInit(&result.icons); \
|
||||
@@ -194,7 +184,6 @@ static void detectGTK(const char* version, FFGTKResult* result)
|
||||
ffStrbufInit(&result.cursorSize); \
|
||||
ffStrbufInit(&result.wallpaper); \
|
||||
detectGTK(#version, &result); \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &result;
|
||||
|
||||
const FFGTKResult* ffDetectGTK2(void)
|
||||
|
||||
@@ -138,14 +138,9 @@ const FFQtResult* ffDetectQt(void)
|
||||
{
|
||||
static FFQtResult result;
|
||||
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
ffThreadMutexLock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.widgetStyle);
|
||||
@@ -161,6 +156,5 @@ const FFQtResult* ffDetectQt(void)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT) == 0)
|
||||
detectLXQt(&result);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,15 @@ static const char* getProductName(const FFstrbuf* hwModel)
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Mac");
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,4")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,5")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(ffStrEquals(version, "15,6") ||
|
||||
ffStrEquals(version, "15,8") ||
|
||||
ffStrEquals(version, "15,10")) return "MacBook Pro (14-inch, Nov 2023, Three Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "15,7") ||
|
||||
ffStrEquals(version, "15,9") ||
|
||||
ffStrEquals(version, "15,11")) return "MacBook Pro (16-inch, Nov 2023, Three Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,15")) return "MacBook Air (15-inch, M2, 2023)";
|
||||
if(ffStrEquals(version, "14,14")) return "Mac Studio (M2 Ultra, 2023, Two Thunderbolt 4 front ports)";
|
||||
if(ffStrEquals(version, "14,13")) return "Mac Studio (M2 Max, 2023, Two USB-C front ports)";
|
||||
|
||||
@@ -28,6 +28,10 @@ static void getHostProductName(FFstrbuf* name)
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
|
||||
ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name);
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
|
||||
//does a clear before the read
|
||||
ffReadFileBuffer("/tmp/sysinfo/model", name);
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
|
||||
@@ -6,18 +6,12 @@
|
||||
#include "common/thread.h"
|
||||
|
||||
#define FF_DETECTION_INTERNAL_GUARD(ResultType, ...) \
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
|
||||
static ResultType result; \
|
||||
static bool init = false; \
|
||||
ffThreadMutexLock(&mutex); \
|
||||
if(init) \
|
||||
{ \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &result; \
|
||||
} \
|
||||
init = true; \
|
||||
__VA_ARGS__; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &result; \
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,13 +55,13 @@ static const char* getSshdVersion(FFstrbuf* version)
|
||||
|
||||
static const char* getSddmVersion(FFstrbuf* version)
|
||||
{
|
||||
FF_LIBRARY_LOAD(zlib, &instance.config.libZ, "dlopen libz failed", "libz" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzopen);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzread);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzerror);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gztell);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose);
|
||||
FF_LIBRARY_LOAD(zlib, &instance.config.library.libZ, "dlopen libz failed", "libz" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzopen)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzread)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzerror)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gztell)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose)
|
||||
|
||||
gzFile file = ffgzopen("/usr/share/man/man1/sddm.1.gz", "rb");
|
||||
if (file == Z_NULL)
|
||||
|
||||
@@ -80,8 +80,17 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
continue;
|
||||
|
||||
struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
char addressBuffer[INET_ADDRSTRLEN + 4];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
|
||||
struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;
|
||||
int cidr = __builtin_popcount(inet_netof(netmask->sin_addr));
|
||||
if (cidr != 0)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%d", cidr);
|
||||
}
|
||||
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute);
|
||||
}
|
||||
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||
|
||||
@@ -105,8 +105,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
if (ifa->Address.lpSockaddr->sa_family == AF_INET)
|
||||
{
|
||||
SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
char addressBuffer[INET_ADDRSTRLEN + 4];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
|
||||
if (ifa->OnLinkPrefixLength)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength);
|
||||
}
|
||||
|
||||
addNewIp(results, name, addressBuffer, AF_INET, newIp, isDefaultRoute);
|
||||
newIp = false;
|
||||
}
|
||||
|
||||
@@ -161,8 +161,8 @@ static const char* getMedia(FFMediaResult* result)
|
||||
|
||||
// FIXME: This is shared for both player and media module.
|
||||
// However it uses an option in one specific module
|
||||
if(instance.config.playerName.length > 0)
|
||||
getCustomBus(&data, &instance.config.playerName, result);
|
||||
if(instance.config.general.playerName.length > 0)
|
||||
getCustomBus(&data, &instance.config.general.playerName, result);
|
||||
else
|
||||
getBestBus(&data, result);
|
||||
|
||||
|
||||
@@ -11,17 +11,12 @@ const char* ffDetectMemory(FFMemoryResult* ram)
|
||||
if (sysctl((int[]){ CTL_HW, HW_MEMSIZE }, 2, &ram->bytesTotal, &length, NULL, 0))
|
||||
return "Failed to read hw.memsize";
|
||||
|
||||
uint32_t pagesize;
|
||||
length = sizeof(pagesize);
|
||||
if (sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &pagesize, &length, NULL, 0))
|
||||
return "Failed to read hw.pagesize";
|
||||
|
||||
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
|
||||
vm_statistics64_data_t vmstat;
|
||||
if(host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) (&vmstat), &count) != KERN_SUCCESS)
|
||||
return "Failed to read host_statistics64";
|
||||
|
||||
ram->bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * pagesize;
|
||||
ram->bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * instance.state.platform.pageSize;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,12 @@ const char* ffDetectMemory(FFMemoryResult* ram)
|
||||
if (sysctl((int[]){ CTL_HW, HW_PHYSMEM }, 2, &ram->bytesTotal, &length, NULL, 0))
|
||||
return "Failed to read hw.physmem";
|
||||
|
||||
uint32_t pageSize;
|
||||
length = sizeof(pageSize);
|
||||
if (sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &pageSize, &length, NULL, 0))
|
||||
return "Failed to read hw.pagesize";
|
||||
|
||||
// vm.stats.vm.* are int values
|
||||
int32_t pagesFree = ffSysctlGetInt("vm.stats.vm.v_free_count", 0)
|
||||
+ ffSysctlGetInt("vm.stats.vm.v_inactive_count", 0)
|
||||
+ ffSysctlGetInt("vm.stats.vm.v_cache_count", 0);
|
||||
|
||||
ram->bytesUsed = ram->bytesTotal - (uint64_t) pagesFree * pageSize;
|
||||
ram->bytesUsed = ram->bytesTotal - (uint64_t) pagesFree * instance.state.platform.pageSize;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result)
|
||||
|
||||
OpenCLData data;
|
||||
|
||||
FF_LIBRARY_LOAD(opencl, &instance.config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed",
|
||||
FF_LIBRARY_LOAD(opencl, &instance.config.library.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed",
|
||||
#ifdef _WIN32
|
||||
"OpenCL"FF_LIBRARY_EXTENSION, -1,
|
||||
#endif
|
||||
|
||||
@@ -122,7 +122,7 @@ static const char* eglPrint(FFOpenGLResult* result)
|
||||
{
|
||||
EGLData eglData;
|
||||
|
||||
FF_LIBRARY_LOAD(egl, &instance.config.libEGL, "dlopen egl failed", "libEGL" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD(egl, &instance.config.library.libEGL, "dlopen egl failed", "libEGL" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
|
||||
@@ -239,7 +239,7 @@ static const char* glxPrint(FFOpenGLResult* result)
|
||||
{
|
||||
GLXData data;
|
||||
|
||||
FF_LIBRARY_LOAD(glx, &instance.config.libGLX, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD(glx, &instance.config.library.libGLX, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXChooseVisual);
|
||||
@@ -303,7 +303,7 @@ static const char* osMesaPrint(FFOpenGLResult* result)
|
||||
{
|
||||
OSMesaData data;
|
||||
|
||||
FF_LIBRARY_LOAD(osmesa, &instance.config.libOSMesa, "dlopen osmesa failed", "libOSMesa" FF_LIBRARY_EXTENSION, 8);
|
||||
FF_LIBRARY_LOAD(osmesa, &instance.config.library.libOSMesa, "dlopen osmesa failed", "libOSMesa" FF_LIBRARY_EXTENSION, 8);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent);
|
||||
|
||||
+22
-22
@@ -35,10 +35,10 @@ static bool detectOSCodeName(FFOSResult* os)
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 14: ffStrbufAppendS(&os->codename, "Sonoma"); return true;
|
||||
case 13: ffStrbufAppendS(&os->codename, "Ventura"); return true;
|
||||
case 12: ffStrbufAppendS(&os->codename, "Monterey"); return true;
|
||||
case 11: ffStrbufAppendS(&os->codename, "Big Sur"); return true;
|
||||
case 14: ffStrbufSetStatic(&os->codename, "Sonoma"); return true;
|
||||
case 13: ffStrbufSetStatic(&os->codename, "Ventura"); return true;
|
||||
case 12: ffStrbufSetStatic(&os->codename, "Monterey"); return true;
|
||||
case 11: ffStrbufSetStatic(&os->codename, "Big Sur"); return true;
|
||||
case 10: {
|
||||
version = str_end + 1;
|
||||
num = strtoul(version, &str_end, 10);
|
||||
@@ -46,23 +46,23 @@ static bool detectOSCodeName(FFOSResult* os)
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 16: ffStrbufAppendS(&os->codename, "Big Sur"); return true;
|
||||
case 15: ffStrbufAppendS(&os->codename, "Catalina"); return true;
|
||||
case 14: ffStrbufAppendS(&os->codename, "Mojave"); return true;
|
||||
case 13: ffStrbufAppendS(&os->codename, "High Sierra"); return true;
|
||||
case 12: ffStrbufAppendS(&os->codename, "Sierra"); return true;
|
||||
case 11: ffStrbufAppendS(&os->codename, "El Capitan"); return true;
|
||||
case 10: ffStrbufAppendS(&os->codename, "Yosemite"); return true;
|
||||
case 9: ffStrbufAppendS(&os->codename, "Mavericks"); return true;
|
||||
case 8: ffStrbufAppendS(&os->codename, "Mountain Lion"); return true;
|
||||
case 7: ffStrbufAppendS(&os->codename, "Lion"); return true;
|
||||
case 6: ffStrbufAppendS(&os->codename, "Snow Leopard"); return true;
|
||||
case 5: ffStrbufAppendS(&os->codename, "Leopard"); return true;
|
||||
case 4: ffStrbufAppendS(&os->codename, "Tiger"); return true;
|
||||
case 3: ffStrbufAppendS(&os->codename, "Panther"); return true;
|
||||
case 2: ffStrbufAppendS(&os->codename, "Jaguar"); return true;
|
||||
case 1: ffStrbufAppendS(&os->codename, "Puma"); return true;
|
||||
case 0: ffStrbufAppendS(&os->codename, "Cheetah"); return true;
|
||||
case 16: ffStrbufSetStatic(&os->codename, "Big Sur"); return true;
|
||||
case 15: ffStrbufSetStatic(&os->codename, "Catalina"); return true;
|
||||
case 14: ffStrbufSetStatic(&os->codename, "Mojave"); return true;
|
||||
case 13: ffStrbufSetStatic(&os->codename, "High Sierra"); return true;
|
||||
case 12: ffStrbufSetStatic(&os->codename, "Sierra"); return true;
|
||||
case 11: ffStrbufSetStatic(&os->codename, "El Capitan"); return true;
|
||||
case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); return true;
|
||||
case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); return true;
|
||||
case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); return true;
|
||||
case 7: ffStrbufSetStatic(&os->codename, "Lion"); return true;
|
||||
case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); return true;
|
||||
case 5: ffStrbufSetStatic(&os->codename, "Leopard"); return true;
|
||||
case 4: ffStrbufSetStatic(&os->codename, "Tiger"); return true;
|
||||
case 3: ffStrbufSetStatic(&os->codename, "Panther"); return true;
|
||||
case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); return true;
|
||||
case 1: ffStrbufSetStatic(&os->codename, "Puma"); return true;
|
||||
case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ void ffDetectOSImpl(FFOSResult* os)
|
||||
parseSystemVersion(os);
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS"))
|
||||
ffStrbufAppendS(&os->id, "macos");
|
||||
ffStrbufSetStatic(&os->id, "macos");
|
||||
|
||||
if(os->version.length == 0)
|
||||
ffSysctlGetString("kern.osproductversion", &os->version);
|
||||
|
||||
@@ -133,13 +133,13 @@ static void getDebianVersion(FFOSResult* result)
|
||||
|
||||
static void detectOS(FFOSResult* os)
|
||||
{
|
||||
if(instance.config.osFile.length > 0)
|
||||
if(instance.config.general.osFile.length > 0)
|
||||
{
|
||||
parseFile(instance.config.osFile.chars, os);
|
||||
parseFile(instance.config.general.osFile.chars, os);
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance.config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
|
||||
if(instance.config.general.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
|
||||
{
|
||||
if(os->id.length == 0)
|
||||
ffStrbufAppendS(&os->id, "bedrock");
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result);
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options);
|
||||
|
||||
const char* ffDetectPackages(FFPackagesResult* result)
|
||||
const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
ffDetectPackagesImpl(result);
|
||||
ffDetectPackagesImpl(result, options);
|
||||
|
||||
for(uint32_t i = 0; i < offsetof(FFPackagesResult, all) / sizeof(uint32_t); ++i)
|
||||
result->all += ((uint32_t *)result)[i];
|
||||
|
||||
@@ -36,6 +36,6 @@ typedef struct FFPackagesResult
|
||||
FFstrbuf pacmanBranch;
|
||||
} FFPackagesResult;
|
||||
|
||||
const char* ffDetectPackages(FFPackagesResult* result);
|
||||
const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* options);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -68,7 +68,7 @@ static uint32_t getMacPortsPackages()
|
||||
return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT"/opt/local");
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result)
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
{
|
||||
getBrewPackages(result);
|
||||
result->port = getMacPortsPackages();
|
||||
|
||||
@@ -226,7 +226,7 @@ static uint32_t getFlatpak(FFstrbuf* baseDir, const char* dirname)
|
||||
|
||||
static uint32_t getRpmFromLibrpm(void)
|
||||
{
|
||||
FF_LIBRARY_LOAD(rpm, &instance.config.librpm, 0, "librpm" FF_LIBRARY_EXTENSION, 12)
|
||||
FF_LIBRARY_LOAD(rpm, &instance.config.library.librpm, 0, "librpm" FF_LIBRARY_EXTENSION, 12)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
|
||||
@@ -327,7 +327,7 @@ static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* package
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result)
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(512);
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
|
||||
|
||||
@@ -105,11 +105,11 @@ static void detectWinget(FFPackagesResult* result)
|
||||
result->winget = count;
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result)
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
detectScoop(result);
|
||||
detectChoco(result);
|
||||
detectPacman(result);
|
||||
if (instance.config.allowSlowOperations)
|
||||
if (options->winget)
|
||||
detectWinget(result);
|
||||
}
|
||||
|
||||
@@ -49,14 +49,23 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
|
||||
}, 0, NULL, &dataSize) == kAudioHardwareNoError && dataSize > 0)
|
||||
continue;
|
||||
|
||||
uint32_t connected;
|
||||
dataSize = sizeof(connected);
|
||||
uint32_t dataSource;
|
||||
dataSize = sizeof(dataSource);
|
||||
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
|
||||
kAudioDevicePropertyJackIsConnected,
|
||||
kAudioDevicePropertyDataSource,
|
||||
kAudioObjectPropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
}, 0, NULL, &dataSize, &connected) == kAudioHardwareNoError)
|
||||
if (!connected) continue;
|
||||
}, 0, NULL, &dataSize, &dataSource) == kAudioHardwareNoError && dataSource == 'hdpn')
|
||||
{
|
||||
uint32_t connected;
|
||||
dataSize = sizeof(connected);
|
||||
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
|
||||
kAudioDevicePropertyJackIsConnected,
|
||||
kAudioObjectPropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
}, 0, NULL, &dataSize, &connected) == kAudioHardwareNoError)
|
||||
if (!connected) continue;
|
||||
}
|
||||
|
||||
FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices);
|
||||
device->main = deviceId == mainDeviceId;
|
||||
|
||||
@@ -38,7 +38,7 @@ static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *u
|
||||
|
||||
static const char* detectSound(FFlist* devices)
|
||||
{
|
||||
FF_LIBRARY_LOAD(pulse, &instance.config.libPulse, "Failed to load libpulse" FF_LIBRARY_EXTENSION, "libpulse" FF_LIBRARY_EXTENSION, 0)
|
||||
FF_LIBRARY_LOAD(pulse, &instance.config.library.libPulse, "Failed to load libpulse" FF_LIBRARY_EXTENSION, "libpulse" FF_LIBRARY_EXTENSION, 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_new)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_get_api)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_iterate)
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
{
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetNativeSystemInfo(&sysInfo);
|
||||
|
||||
ULONG size = sizeof(SYSTEM_PAGEFILE_INFORMATION);
|
||||
SYSTEM_PAGEFILE_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PAGEFILE_INFORMATION*)malloc(size);
|
||||
while(true)
|
||||
@@ -24,8 +21,10 @@ const char* ffDetectSwap(FFSwapResult* swap)
|
||||
return "NtQuerySystemInformation(SystemPagefileInformation, size) failed";
|
||||
break;
|
||||
}
|
||||
swap->bytesUsed = (uint64_t)pstart->TotalUsed * sysInfo.dwPageSize;
|
||||
swap->bytesTotal = (uint64_t)pstart->CurrentSize * sysInfo.dwPageSize;
|
||||
|
||||
uint32_t pageSize = instance.state.platform.pageSize;
|
||||
swap->bytesUsed = (uint64_t)pstart->TotalUsed * pageSize;
|
||||
swap->bytesTotal = (uint64_t)pstart->CurrentSize * pageSize;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -41,33 +41,23 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value)
|
||||
return value->name.length > 0 || value->deviceClass > 0;
|
||||
}
|
||||
|
||||
const FFTempsResult* ffDetectTemps(void)
|
||||
const FFlist* ffDetectTemps(void)
|
||||
{
|
||||
static FFTempsResult result;
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
static FFlist result;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
if(result.elementSize > 0)
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffListInitA(&result.values, sizeof(FFTempValue), 16);
|
||||
ffListInitA(&result, sizeof(FFTempValue), 16);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&baseDir, "/sys/class/hwmon/");
|
||||
|
||||
uint32_t baseDirLength = baseDir.length;
|
||||
|
||||
DIR* dirp = opendir(baseDir.chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
|
||||
if(dirp == NULL)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
@@ -78,20 +68,17 @@ const FFTempsResult* ffDetectTemps(void)
|
||||
ffStrbufAppendS(&baseDir, entry->d_name);
|
||||
ffStrbufAppendC(&baseDir, '/');
|
||||
|
||||
FFTempValue* temp = ffListAdd(&result.values);
|
||||
FFTempValue* temp = ffListAdd(&result);
|
||||
ffStrbufInit(&temp->name);
|
||||
temp->deviceClass = 0;
|
||||
if(!parseHwmonDir(&baseDir, temp))
|
||||
{
|
||||
ffStrbufDestroy(&temp->name);
|
||||
--result.values.length;
|
||||
--result.length;
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,6 @@ typedef struct FFTempValue
|
||||
double value;
|
||||
} FFTempValue;
|
||||
|
||||
typedef struct FFTempsResult
|
||||
{
|
||||
FFlist values; //List of FFTempValue
|
||||
} FFTempsResult;
|
||||
|
||||
const FFTempsResult* ffDetectTemps();
|
||||
const FFlist* /* List of FFTempValue */ ffDetectTemps();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -242,35 +242,32 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul
|
||||
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
|
||||
|
||||
FFpropquery fontQuery[] = {
|
||||
{"font_family ", &fontName},
|
||||
{"font_size ", &fontSize},
|
||||
};
|
||||
|
||||
if(instance.config.allowSlowOperations)
|
||||
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
|
||||
if(!ffProcessAppendStdOut(&buf, (char* const[]){
|
||||
exe->chars,
|
||||
"+kitten",
|
||||
"query-terminal",
|
||||
NULL,
|
||||
}))
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
|
||||
if(!ffProcessAppendStdOut(&buf, (char* const[]){
|
||||
exe->chars,
|
||||
"+kitten",
|
||||
"query-terminal",
|
||||
NULL,
|
||||
}))
|
||||
{
|
||||
ffParsePropLines(buf.chars, "font_family: ", &fontName);
|
||||
ffParsePropLines(buf.chars, "font_size: ", &fontSize);
|
||||
ffFontInitValues(&result->font, fontName.chars, fontSize.chars);
|
||||
return true;
|
||||
}
|
||||
ffParsePropLines(buf.chars, "font_family: ", &fontName);
|
||||
ffParsePropLines(buf.chars, "font_size: ", &fontSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFpropquery fontQuery[] = {
|
||||
{"font_family ", &fontName},
|
||||
{"font_size ", &fontSize},
|
||||
};
|
||||
|
||||
ffParsePropFileConfigValues("kitty/kitty.conf", 2, fontQuery);
|
||||
|
||||
if(fontName.length == 0)
|
||||
ffStrbufSetS(&fontName, "monospace");
|
||||
if(fontSize.length == 0)
|
||||
ffStrbufSetS(&fontSize, "11.0");
|
||||
}
|
||||
|
||||
if(!ffParsePropFileConfigValues("kitty/kitty.conf", 2, fontQuery))
|
||||
return false;
|
||||
|
||||
if(fontName.length == 0)
|
||||
ffStrbufSetS(&fontName, "monospace");
|
||||
if(fontSize.length == 0)
|
||||
ffStrbufSetS(&fontSize, "11.0");
|
||||
|
||||
ffFontInitValues(&result->font, fontName.chars, fontSize.chars);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const char* detectTermux(FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
#ifdef FF_HAVE_FREETYPE
|
||||
|
||||
FF_LIBRARY_LOAD(freetype, &instance.config.libfreetype, "dlopen libfreetype"FF_LIBRARY_EXTENSION " failed", "libfreetype"FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD(freetype, &instance.config.library.libfreetype, "dlopen libfreetype"FF_LIBRARY_EXTENSION " failed", "libfreetype"FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(freetype, FT_Init_FreeType);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(freetype, FT_New_Face);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(freetype, FT_Done_Face);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "common/settings.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/mallocHelper.h"
|
||||
@@ -124,15 +125,36 @@ static void detectXFCETerminal(FFTerminalFontResult* terminalFont)
|
||||
FF_STRBUF_AUTO_DESTROY useSysFont = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
|
||||
|
||||
ffParsePropFileConfigValues("xfce4/terminal/terminalrc", 2, (FFpropquery[]) {
|
||||
{"FontUseSystem = ", &useSysFont},
|
||||
{"FontName = ", &fontName}
|
||||
const char* path = "xfce4/xfconf/xfce-perchannel-xml/xfce4-terminal.xml";
|
||||
bool configFound = ffParsePropFileConfigValues(path, 2, (FFpropquery[]) {
|
||||
{"<property name=\"font-use-system\" type=\"bool\" value=\"", &useSysFont},
|
||||
{"<property name=\"font-name\" type=\"string\" value=\"", &fontName}
|
||||
});
|
||||
|
||||
if (configFound)
|
||||
{
|
||||
ffStrbufSubstrBeforeLastC(&useSysFont, '"');
|
||||
ffStrbufSubstrBeforeLastC(&fontName, '"');
|
||||
}
|
||||
else
|
||||
{
|
||||
path = "xfce4/terminal/terminalrc";
|
||||
configFound = ffParsePropFileConfigValues(path, 2, (FFpropquery[]) {
|
||||
{"FontUseSystem = ", &useSysFont},
|
||||
{"FontName = ", &fontName}
|
||||
});
|
||||
}
|
||||
|
||||
if (!configFound)
|
||||
{
|
||||
ffStrbufSetStatic(&terminalFont->error, "Couldn't find xfce4/xfconf/xfce-perchannel-xml/xfce4-terminal.xml or xfce4/terminal/terminalrc");
|
||||
return;
|
||||
}
|
||||
|
||||
if(useSysFont.length == 0 || ffStrbufIgnCaseCompS(&useSysFont, "false") == 0)
|
||||
{
|
||||
if(fontName.length == 0)
|
||||
ffStrbufAppendS(&terminalFont->error, "Couldn't find FontName in .config/xfce4/terminal/terminalrc");
|
||||
ffStrbufAppendF(&terminalFont->error, "Couldn't find FontName in %s", path);
|
||||
else
|
||||
ffFontInitPango(&terminalFont->font, fontName.chars);
|
||||
}
|
||||
@@ -250,6 +272,38 @@ static void detectXterm(FFTerminalFontResult* terminalFont)
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
}
|
||||
|
||||
static void detectSt(FFTerminalFontResult* terminalFont, uint32_t pid)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY size = ffStrbufCreateF("/proc/%u/cmdline", pid);
|
||||
FF_STRBUF_AUTO_DESTROY font = ffStrbufCreate();
|
||||
if (!ffAppendFileBuffer(size.chars, &font))
|
||||
{
|
||||
ffStrbufAppendF(&terminalFont->error, "Failed to open %s", size.chars);
|
||||
return;
|
||||
}
|
||||
|
||||
const char* p = memmem(font.chars, font.length, "\0-f", sizeof("\0-f")); // find parameter of `-f`
|
||||
if (!p)
|
||||
{
|
||||
ffStrbufAppendF(&terminalFont->error, "st was not executed with `-f` parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufSubstrAfter(&font, (uint32_t) (p + (sizeof("\0-f") - 1) - font.chars));
|
||||
ffStrbufRecalculateLength(&font);
|
||||
|
||||
// `monospace:size=15` || `monospace` || `:size=15`
|
||||
uint32_t index = ffStrbufFirstIndexS(&font, ":size=");
|
||||
if (index != font.length)
|
||||
{
|
||||
ffStrbufSetS(&size, font.chars + index + strlen(":size="));
|
||||
ffStrbufSubstrBefore(&font, index);
|
||||
}
|
||||
else
|
||||
ffStrbufClear(&size);
|
||||
ffFontInitValues(&terminalFont->font, font.chars, size.chars);
|
||||
}
|
||||
|
||||
void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "konsole"))
|
||||
@@ -276,4 +330,6 @@ void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FF
|
||||
detectQTerminal(terminalFont);
|
||||
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "xterm"))
|
||||
detectXterm(terminalFont);
|
||||
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "st"))
|
||||
detectSt(terminalFont, terminalShell->terminalPid);
|
||||
}
|
||||
|
||||
@@ -284,6 +284,36 @@ FF_MAYBE_UNUSED static bool getTerminalVersionXterm(FFstrbuf* exe, FFstrbuf* ver
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionUrxvt(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if(ffProcessAppendStdErr(version, (char* const[]){
|
||||
"urxvt", // Don't use exe because of urxvtd
|
||||
"-invalid",
|
||||
NULL
|
||||
})) return false;
|
||||
|
||||
//urxvt: "invalid": unknown or malformed option.
|
||||
//rxvt-unicode (urxvt) v9.31 - released: 2023-01-02
|
||||
ffStrbufSubstrAfterFirstS(version, "(urxvt) v");
|
||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
||||
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionSt(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if(ffProcessAppendStdErr(version, (char* const[]){
|
||||
exe->chars,
|
||||
"-v",
|
||||
NULL
|
||||
})) return false;
|
||||
|
||||
//st 0.9
|
||||
ffStrbufSubstrAfterFirstC(version, ' ');
|
||||
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
const char* env = getenv("TERMINAL_VERSION_STRING");
|
||||
@@ -371,6 +401,16 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
if(ffStrbufIgnCaseEqualS(processName, "xterm"))
|
||||
return getTerminalVersionXterm(exe, version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "st"))
|
||||
return getTerminalVersionSt(exe, version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "urxvt") ||
|
||||
ffStrbufIgnCaseEqualS(processName, "urxvtd") ||
|
||||
ffStrbufIgnCaseEqualS(processName, "rxvt") ||
|
||||
ffStrbufIgnCaseEqualS(processName, "rxvt-unicode")
|
||||
)
|
||||
return getTerminalVersionUrxvt(exe, version);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -415,6 +455,22 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
}
|
||||
}
|
||||
|
||||
termProgramVersion = getenv("LC_TERMINAL_VERSION");
|
||||
if(termProgramVersion)
|
||||
{
|
||||
const char* termProgram = getenv("LC_TERMINAL");
|
||||
if(termProgram)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, termProgram) || // processName ends with `.exe` on Windows
|
||||
(ffStrEquals(termProgram, "vscode") && ffStrbufStartsWithIgnCaseS(processName, "code")) ||
|
||||
(ffStrStartsWith(termProgram, "iTerm") && ffStrbufStartsWithIgnCaseS(processName, "iTermServer-"))
|
||||
) {
|
||||
ffStrbufSetS(version, termProgramVersion);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
return getFileVersion(exe->chars, version);
|
||||
|
||||
@@ -139,6 +139,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
|
||||
strcasecmp(name, "sshd") == 0 ||
|
||||
strcasecmp(name, "gdb") == 0 ||
|
||||
strcasecmp(name, "lldb") == 0 ||
|
||||
strcasecmp(name, "login") == 0 ||
|
||||
strcasecmp(name, "guake-wrapped") == 0 ||
|
||||
strcasestr(name, "debug") != NULL ||
|
||||
strcasestr(name, "command-not-found") != NULL ||
|
||||
@@ -236,8 +237,7 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
//Termux
|
||||
if(!ffStrSet(term) && (
|
||||
getenv("TERMUX_VERSION") != NULL ||
|
||||
getenv("TERMUX_MAIN_PACKAGE_FORMAT") != NULL ||
|
||||
getenv("TMUX_TMPDIR") != NULL
|
||||
getenv("TERMUX_MAIN_PACKAGE_FORMAT") != NULL
|
||||
)) term = "com.termux";
|
||||
#endif
|
||||
|
||||
@@ -252,6 +252,9 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
if(!ffStrSet(term))
|
||||
term = getenv("TERM_PROGRAM");
|
||||
|
||||
if(!ffStrSet(term))
|
||||
term = getenv("LC_TERMINAL");
|
||||
|
||||
//Normal Terminal
|
||||
if(!ffStrSet(term))
|
||||
term = getenv("TERM");
|
||||
@@ -311,15 +314,10 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* vers
|
||||
|
||||
const FFTerminalShellResult* ffDetectTerminalShell()
|
||||
{
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
static FFTerminalShellResult result;
|
||||
static bool init = false;
|
||||
ffThreadMutexLock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -363,19 +361,20 @@ const FFTerminalShellResult* ffDetectTerminalShell()
|
||||
ffStrbufInitS(&result.shellPrettyName, result.shellExeName);
|
||||
}
|
||||
|
||||
if(result.terminalExeName[0] == '.' && ffStrEndsWith(result.terminalExeName, "-wrapper"))
|
||||
if(result.terminalExeName[0] == '.' && ffStrEndsWith(result.terminalExeName, "-wrapped"))
|
||||
{
|
||||
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
|
||||
// We use terminalProcessName when detecting version and font, overriding it for simplication
|
||||
ffStrbufSetNS(
|
||||
&result.terminalProcessName,
|
||||
(uint32_t) (strlen(result.terminalExeName) - strlen(".-wrapper")),
|
||||
(uint32_t) (strlen(result.terminalExeName) - strlen(".-wrapped")),
|
||||
result.terminalExeName + 1);
|
||||
}
|
||||
|
||||
|
||||
if(ffStrbufEqualS(&result.terminalProcessName, "wezterm-gui"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "WezTerm");
|
||||
if(ffStrbufStartsWithS(&result.terminalProcessName, "tmux:"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "tmux");
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
@@ -388,6 +387,11 @@ const FFTerminalShellResult* ffDetectTerminalShell()
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Terminal");
|
||||
else if(ffStrbufStartsWithS(&result.terminalProcessName, "kgx"))
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Console");
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "urxvt") ||
|
||||
ffStrbufEqualS(&result.terminalProcessName, "urxvtd") ||
|
||||
ffStrbufEqualS(&result.terminalProcessName, "rxvt")
|
||||
)
|
||||
ffStrbufInitStatic(&result.terminalPrettyName, "rxvt-unicode");
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
@@ -408,6 +412,5 @@ const FFTerminalShellResult* ffDetectTerminalShell()
|
||||
ffStrbufInit(&result.terminalVersion);
|
||||
fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
{
|
||||
ffStrbufClear(&result->shellPrettyName);
|
||||
|
||||
HANDLE snapshot;
|
||||
FF_AUTO_CLOSE_FD HANDLE snapshot = NULL;
|
||||
while(!(snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid)) && GetLastError() == ERROR_BAD_LENGTH) {}
|
||||
|
||||
if(snapshot)
|
||||
@@ -147,7 +147,6 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
}
|
||||
if(result->shellPrettyName.length == 0)
|
||||
ffStrbufAppendS(&result->shellPrettyName, "Command Prompt");
|
||||
@@ -355,15 +354,10 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* vers
|
||||
|
||||
const FFTerminalShellResult* ffDetectTerminalShell(void)
|
||||
{
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
static FFTerminalShellResult result;
|
||||
static bool init = false;
|
||||
ffThreadMutexLock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.shellProcessName);
|
||||
@@ -381,7 +375,7 @@ const FFTerminalShellResult* ffDetectTerminalShell(void)
|
||||
|
||||
uint32_t ppid;
|
||||
if(!getProcessInfo(0, &ppid, NULL, NULL, NULL))
|
||||
goto exit;
|
||||
return &result;
|
||||
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
if(ppid)
|
||||
@@ -393,7 +387,5 @@ const FFTerminalShellResult* ffDetectTerminalShell(void)
|
||||
ffStrbufInit(&result.terminalVersion);
|
||||
fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
|
||||
|
||||
exit:
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user