Compare commits

...

102 Commits

Author SHA1 Message Date
Carter Li 52de8df1f9 Merge pull request #1492 from fastfetch-cli/dev
Release: v2.34.0
2025-01-09 09:02:12 +08:00
李通洲 be99c4ca6e Media (Linux): remove unused variables 2025-01-09 08:50:56 +08:00
李通洲 8133c3365f Doc: update JSON schema [ci skip] 2025-01-08 22:29:49 +08:00
李通洲 6226ccc70e Processing (Windows): fix get current process 2025-01-08 20:37:35 +08:00
李通洲 88917cb14f OpenGL (EGL): try GLES 2.0+; then fallback to 1.1 if failed 2025-01-08 20:13:01 +08:00
Carter Li a93e2aafdb Release: v2.34.0 2025-01-08 16:26:06 +08:00
李通洲 5848b5fc24 OpenGL (Android): enable support 2025-01-08 16:09:41 +08:00
李通洲 934b6291e3 OpenGL (Android): request GLES 2+ 2025-01-08 15:38:55 +08:00
李通洲 90068ab474 Battery (NetBSD): fix battery percentage detection 2025-01-08 13:46:08 +08:00
Carter Li 5567e6cc5e Packages (Linux): rename am-user to appman 2025-01-08 10:56:55 +08:00
Carter Li 8b3017c0d9 Packages (Linux): remove possible final newlines in am config 2025-01-08 10:28:13 +08:00
Carter Li f9f15ba844 General: don't suppress the output of preRun
Fix #1489
2025-01-08 09:46:41 +08:00
Carter Li b282ac5d47 Packages (Linux): support am-user
Fix #771
2025-01-08 09:46:12 +08:00
Carter Li 6577884417 WMDE: detect Sway by env variables 2025-01-08 08:50:53 +08:00
李通洲 c4ee606955 CPU (Android): check for MTK D9X00 SOCs 2025-01-08 08:39:09 +08:00
Bahar KURT 59c80820f2 feat: Add Rhino Linux ASCII (#1487)
Cramp all additions into one commit because I like to do it that
way. xD

Co-authored-by: Bahar KURT <kurtbahartr@users.noreply.github.com>
2025-01-07 21:30:22 +08:00
李通洲 c11e14f7e1 CMake (Android): set rpath for system Android libs
So that Vulkan & OpenCL can find them
2025-01-07 15:38:47 +08:00
Carter Li ab6a770155 Sound: detect platform API
Ref: #1454
2025-01-07 15:38:38 +08:00
李通洲 0e99486efe Processing (Windows): early return if OpenProcess failed 2025-01-07 08:35:57 +08:00
Eshan Roy f82f3002e4 Logo (Builtin): add snigdhaos ascii (#1485)
* feat: add snigdhaos ascii

* feat: insert builtin data
2025-01-06 23:49:48 +08:00
Angel Gustavo Lopez 0bed182784 fixing fastfetch wrong colors for xray_os logo (#1486) 2025-01-06 19:54:38 +08:00
Carter Li d39be955b1 Doc: update changelog [ci skip] 2025-01-06 14:39:29 +08:00
CaKrome 3b2790cccc CI (Linux): add Linux ppc64le platform (#1484) 2025-01-06 13:55:13 +08:00
Carter Li 3ea0406b69 CPU (Linux): fix var content was unexpectedly modified 2025-01-06 10:57:29 +08:00
李通洲 6429c20466 OS: prefer pretty names
Hopefully we can end the controversy.

Fix #1483 #1038
2025-01-06 08:58:14 +08:00
李通洲 88ebeb21e2 CPU: fix core count output in multi-package platforms
Fix #1413
2025-01-05 19:38:16 +08:00
Carter Li f28f5e2874 CPU (Linux): detect TZ temp if CPU temp is not available 2025-01-05 17:28:01 +08:00
Carter Li 637c37e81c Packages (macOS): remove redundant tokens 2025-01-05 17:28:01 +08:00
Simon Quigley b2c779dea9 Logo (Builtin): add the Lubuntu logo (#1481)
* Add the Lubuntu logo

* Lubuntu uses LXQt, not LXDE
2025-01-05 11:08:27 +08:00
李通洲 89d636447b Doc: update README [ci skip] 2025-01-03 13:56:48 +08:00
Carter Li 3dc51d5f88 FFstrbuf: improve performance of copying static strings 2025-01-03 10:59:01 +08:00
Carter Li 60ff89c794 Terminal (Linux): fix detection of pk-command-not-found
Fix #1467
2025-01-03 10:32:16 +08:00
Carter Li f973572c5a TerminalShell (Linux): relax detection of terminals in NixOS
Fix #1479
2025-01-03 10:18:44 +08:00
Carter Li ea78665971 Doc: update README.md 2025-01-03 10:16:38 +08:00
Carter Li 80b48dd2d1 Logo (Image): mark ghostty supports kitty image protocol 2025-01-03 09:55:38 +08:00
Carter Li df6eed7a02 TerminalSize (Linux): enable fast path when stdout is redirected. 2025-01-03 09:50:59 +08:00
李通洲 c9ac09f9eb WM (Linux): detect WM version 2025-01-02 20:19:15 +08:00
Carter Li 67597e4566 WM (Linux): add sway version detection 2025-01-02 16:36:31 +08:00
李通洲 611de77980 Terminal (macOS): improve performance of kitty version 2025-01-02 16:35:53 +08:00
李通洲 0fde835629 WM (Windows): detect version of DWM 2025-01-02 16:35:53 +08:00
李通洲 f373e07847 WM (Linux): don't crash if no wm is detected 2025-01-02 16:35:53 +08:00
李通洲 89e4403cc8 WM (macOS): add WindowServer version detection 2025-01-02 16:35:53 +08:00
李通洲 c68d21e215 WM: report version field in custom and JSON output 2025-01-02 16:35:53 +08:00
Christopher Kaster f14cd2c6e8 WM: Add support for detecting window manager versions, add support for Hyprland version (#1472) 2025-01-02 10:13:28 +08:00
Carter Li d58d786c83 Logo (Image): add --kitty-icat; honor --logo-height if set 2024-12-31 15:43:01 +08:00
Carter Li 9f37557177 Logo (Image): support generate image data via kitten icat 2024-12-31 15:30:26 +08:00
李通洲 aa63c4f5f2 Revert "GPU: support detection by EGLext"
Works only for NVIDIA GPUs

This reverts commits 9ef8580d93 and 9342d74c93.
2024-12-31 13:57:06 +08:00
李通洲 a378d2ad62 Brightness (FreeBSD): fix backlight name detection 2024-12-30 11:12:06 +08:00
Carter Li 2ab2dd4d48 TerminalFont (macOS): fix ghostty font detection; default to JetBrains Mono
Ref: https://github.com/fastfetch-cli/fastfetch/issues/1466#issuecomment-2564379883
2024-12-30 10:43:28 +08:00
Peter Zmanovsky 2a83b86ba4 Platform (Linux): fix exe path detection (#1468)
On error, -1 is returned from readlink()
2024-12-29 09:53:20 +08:00
李通洲 d967d05019 Bluetooth (DragonFly): disable module to fix build 2024-12-28 22:13:49 +08:00
李通洲 9ef8580d93 GPU (EGLext): fix build on old systems 2024-12-28 21:50:08 +08:00
Carter Li 813b80c5a8 TerminalFont: support Ghostty
Fix #1466
2024-12-28 15:34:41 +08:00
Carter Li ddce9b2357 GPU: rename ffGetGPUVendorString to ffGPUGetVendorString 2024-12-28 15:26:17 +08:00
Carter Li 9342d74c93 GPU: support detection by EGLext
Support multi-gpus
2024-12-28 15:25:22 +08:00
Carter Li d6028370e7 Bluetooth (FreeBSD): add support (not tested) 2024-12-27 14:49:15 +08:00
李通洲 e425d7df63 CI: update *BSD versions 2024-12-27 14:11:53 +08:00
李通洲 a4a2ae7d67 Host (macOS): fix thunderbolt version of new MBPs
Fix #1465
2024-12-27 14:07:17 +08:00
Carter Li 99aa0638cc Packaging: update debian stuff [ci skip] 2024-12-26 09:47:44 +08:00
Carter Li 1a9e637134 Merge pull request #1464 from fastfetch-cli/dev
Release: v2.33.0
2024-12-26 09:37:25 +08:00
李通洲 f322405c04 Release: v2.33.0 2024-12-26 09:08:33 +08:00
Carter Li e4202635af Doc: update changelog [ci skip] 2024-12-25 10:47:36 +08:00
Carter Li 2f13ee3814 Media (Linux): set player name manually for musikcube 2024-12-25 10:47:36 +08:00
Carter Li 2bfde87f84 Logo (Builtin): add GoralixOS
Fix #1462
2024-12-25 10:47:36 +08:00
Carter Li f38a51c9bc Media: make it able to print player info in custom format 2024-12-25 09:04:10 +08:00
Carter Li 28ec935c42 Media (Linux): report player name 2024-12-25 08:50:28 +08:00
李通洲 d939f95c69 Vulkan (Android): hard code path of libvulkan.so, so that users don't need to install vulkan-loader wrapper of termux 2024-12-24 21:20:03 +08:00
李通洲 e0fd5111fe Media (Linux): Fix #1461 (WIP) 2024-12-24 19:38:43 +08:00
李通洲 4736031538 Doc: update changelog [ci skip] 2024-12-22 22:19:02 +08:00
李通洲 66085c087e Logo (Builtin): add NurOS
Fix #1456
2024-12-22 21:48:18 +08:00
李通洲 e0253d71c0 Doc: add comments for running fastfetch in root 2024-12-22 20:45:51 +08:00
李通洲 dadd4bfab6 DiskIO (OpenBSD): remove debug output 2024-12-22 20:43:36 +08:00
李通洲 2f3861e732 PhysicalMemory: clean up garbage data 2024-12-22 20:27:27 +08:00
李通洲 851f271ed5 CPU (NetBSD): fix typo 2024-12-22 14:20:32 +08:00
Carter Li d3e40f625b Battery (OpenBSD): fix build 2024-12-22 09:30:42 +08:00
Carter Li 7c1991c2e3 Battery (NetBSD): add support 2024-12-21 23:54:30 +08:00
李通洲 b8048ee488 Bluetooth (BSD): disable
bluez is Linux specific
2024-12-21 23:54:30 +08:00
李通洲 b99f54b9f4 CPU (NetBSD): trim CPU vendor 2024-12-21 23:54:30 +08:00
Carter Li b38d7a4919 Brightness (NetBSD): don't error out if the screen idx isn't 0 2024-12-21 23:54:30 +08:00
李通洲 45f7e2c0b2 Version (NetBSD): report sysname 2024-12-21 23:54:30 +08:00
李通洲 5a8dda27ff CPU (NetBSD): support temp and frequency detection 2024-12-21 23:54:30 +08:00
李通洲 1ea3264b13 SMBIOS (NetBSD): add more data 2024-12-21 23:54:30 +08:00
Carter Li 852a729581 Battary (NetBSD): some basic investigation of acpi battery detection 2024-12-21 23:54:30 +08:00
Carter Li 0f454b7140 Battery (OpenBSD): add support 2024-12-21 23:54:30 +08:00
Carter Li 9c47a3a9e7 Brightness (OpenBSD): add support
Requires root permission. Not tested
2024-12-21 23:54:30 +08:00
李通洲 4adf7fda28 Brightness (NetBSD): add support for builtin display 2024-12-21 23:54:30 +08:00
李通洲 e2fc83fd48 Bluetooth (Windows): silence compiler warnings 2024-12-21 23:54:30 +08:00
Robin Candau dd41dfa000 CMake: Add a cmake option to make flashfetch target optional (#1455)
Introduces the `-DBUILD_FLASHFETCH='ON'/'OFF'` build option so one can skip the `flashfetch` target (both from executable and install targets, option at `ON` by default to preserve compatibility with the current default behavior).
This is useful when distributing pre-built downstream packages (e.g. for Linux distributions packaging `fastfetch`) as building and shipping the `flashfetch` binary in such pre-built packages serves little to no purpose.
2024-12-21 23:53:02 +08:00
Carter Li 14d6157901 PhysicalDisk (Linux): fix interconnect type detection
Regression of b5a9d64

Fix #1453
2024-12-20 16:38:30 +08:00
Carter Li 74586a9df1 Bluetooth (Linux): improve performance
1. ignore unpaired devices
2. ignore disconnected devices when `showDisconnected == false`
2024-12-20 15:57:17 +08:00
Carter Li c5d4b20729 TerminalShell (Android): ignore proot 2024-12-20 15:57:17 +08:00
李通洲 b152b383a2 Bluetooth (Windows): optimise
1. don't report disconnected devices if `showDisconnected == false`
2. don't report unknown devices
3. don't report errors when no devices found
2024-12-20 15:57:17 +08:00
李通洲 ae26692ef6 Bluetooth (macOS): don't report disconnected devices if showDisconnected == false 2024-12-20 15:57:17 +08:00
Carter Li 4f807f26a9 Bluetooth (Linux): improve performance when showDisconnected == false
If no connected devices found, no dbus calls will be emitted

Fix #1450
2024-12-20 15:57:02 +08:00
Carter Li 4bef801337 BluetoothRadio (Linux): improve performance by reducing size of dbus response 2024-12-20 15:56:48 +08:00
李通洲 41240e9460 FFlist: fix return value of ffListPop 2024-12-20 11:12:14 +08:00
JohnTheCoolingFan 3bb82423b3 OS (Linux): Refactor Armbian version detection and add support for ubuntu-based armbian detection (#1447)
* Add support for detection of Armbian as Ubuntu flavor

Ubuntu can be used to build Armbian, it is one of the official bases for
Armbian. This allows the detection of Armbian in case it is based on
Ubuntu.

* Refactor Armbian detection

* Armbian: set idLike to id before setting id to "armbian"

* Tidy up detectArmbianVersion
2024-12-19 16:18:42 +08:00
李通洲 b87df82d58 Shell (Windows): use $POWERSHELL_VERSION if available 2024-12-19 11:00:16 +08:00
Carter Li c145ce49a5 Merge pull request #1446 from fastfetch-cli/dev
Release: v2.32.1
2024-12-18 14:41:21 +08:00
李通洲 8c4fb5d6d4 Release: v2.32.1 2024-12-18 14:25:44 +08:00
李通洲 eae0fee032 Packages (OpenBSD): fix a typo that prevents package counting from working 2024-12-18 14:24:13 +08:00
Carter Li 4472a13f41 Packaging: update debian stuff 2024-12-18 14:22:56 +08:00
98 changed files with 1635 additions and 526 deletions
+38 -2
View File
@@ -232,6 +232,41 @@ jobs:
name: fastfetch-linux-riscv64
path: ./fastfetch-*.*
linux-ppc64le:
name: Linux-ppc64le
runs-on: ubuntu-22.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: run VM
uses: uraimo/run-on-arch-action@v2
id: runcmd
with:
arch: ppc64le
distro: ubuntu20.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-ppc64le
path: ./fastfetch-*.*
musl-amd64:
name: Musl-amd64
runs-on: ubuntu-latest
@@ -377,7 +412,7 @@ jobs:
architecture: x86-64
cpu_count: 4
shell: bash
version: '14.1'
version: '14.2'
run: |
uname -a
sudo pkg update
@@ -449,7 +484,7 @@ jobs:
architecture: x86-64
cpu_count: 4
shell: bash
version: '7.5'
version: '7.6'
run: |
uname -a
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio hwdata py3-requests
@@ -578,6 +613,7 @@ jobs:
- linux-aarch64
- linux-armv7
- linux-riscv64
- linux-ppc64le
- musl-amd64
- macos-universal
- freebsd-amd64
+74
View File
@@ -1,3 +1,77 @@
# 2.34.0
Changes:
* We now print distro pretty name if available (OS)
* This is a long requested feature. However, it may break some distros. File a bug with the content of `/etc/os-release` if it breaks your distro.
Bugfixes:
* Fix thunderbolt version of new MBPs (#1465, Host, macOS)
* Fix backlight name detection on FreeBSD (Brightness, FreeBSD)
* Fix Terminal detection when running fastfetch in `pk-command-not-found` (#1467, Terminal, Linux)
* Relax detection of terminals in NixOS (#1479, Terminal, Linux)
* Should fix konsole, ghostty and maybe others
* Fix core count output in multi-package platforms (CPU)
* Don't suppress the output of `preRun` (#1489)
* Fix battery percentage detection (Battery, NetBSD)
Features:
* Support ghostty terminal font detection (TerminalFont, Linux / macOS)
* Support `kitty-icat` image protocol, which uses `kitten icat` to generate image data
* Pros: support tmux; support gif animations; good performance
* Cons: due to the limitation of `kitten icat`, we need to clear the screen before displaying the image logo
* Support WM version detection (WM)
* In Linux, Hyprland & sway are supported currently
* Improve performance when stdout is redirected (TerminalSize)
* Report thermal zone temp if CPU temp is not available (CPU, Linux)
* Report sound server (Pipewire or PulseAudio) if available (#1454, Sound, Linux)
* Enable OpenGL & OpenCL detection on Android (OpenGL / OpenCL, Android)
* Detect & report MediaTek Dimensity 9000+ SOC name (CPU, Android)
* Support appman (am-user) package manager detection (Packages, Linux)
Logo:
* Add Lubuntu
* Update Xray_os
* Add SnigdhaOS
* Add Rhino Linux
# 2.33.0
Changes:
* Introduce a new CMake flag `-DBUILD_FLASHFETCH=OFF` to disable building flashfetch binaries
* Package managers are encouraged to enable it. See <https://github.com/fastfetch-cli/fastfetch/discussions/627> for detail
Bugfixes:
* Fix interconnect type detection (#1453, PhysicalDisk, Linux)
* Regression of v2.28
* Don't report `proot` as terminal (Terminal, Android)
* Remove a debug output (DiskIO, OpenBSD)
* Fix media detection for some players (#1461, Media, Linux)
* Regression of v2.32
Features:
* Use `$POWERSHELL_VERSION` as PowerShell version if available (Shell, Windows)
* Fetching Windows PowerShell version can be very slow. Add `$env:POWERSHELL_VERSION = $PSVersionTable.PSVersion.ToString()` in `$PROFILE` before running `fastfetch` to improve the performance of `Shell` module
* Add support for ubuntu-based armbian detection (#1447, OS, Linux)
* Improve performance of Bluetooth detection (Bluetooth)
* We no longer report disconnected bluetooth devices in `--format json` when `--bluetooth-show-disconnected` isn't specified
* Support brightness level detection for builtin displays (Brightness, OpenBSD / NetBSD)
* Requires root permission on OpenBSD
* Support battery level detection (Battery, OpenBSD / NetBSD)
* Support CPU temperature detection in NetBSD (CPU, NetBSD)
* Hard code path of `libvulkan.so` for Android
* So that users don't need to install the vulkan-loader wrapper of termux
Logo:
* Add NurOS
* Add GoralixOS
# 2.32.1
A hotfix for OpenBSD. No changes to other platforms.
Bugfixes:
* Fix package count detection on OpenBSD (Packages, OpenBSD)
# 2.32.0
Bugfixes:
+72 -34
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.32.0
VERSION 2.34.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -70,8 +70,8 @@ cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR F
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS" OFF)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
@@ -86,6 +86,7 @@ cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR Open
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
option(BUILD_FLASHFETCH "Build flashfetch" ON) # Also build the flashfetch binary
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
option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
@@ -533,7 +534,7 @@ 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/wm/wm_linux.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
@@ -616,8 +617,7 @@ elseif(FreeBSD)
src/common/sysctl.c
src/detection/battery/battery_bsd.c
src/detection/bios/bios_bsd.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_bsd.c
src/detection/bootmgr/bootmgr_bsd.c
src/detection/brightness/brightness_bsd.c
@@ -689,6 +689,15 @@ elseif(FreeBSD)
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
if(DragonFly)
list(APPEND LIBFASTFETCH_SRC
src/detection/bluetooth/bluetooth_nosupport.c
)
else()
list(APPEND LIBFASTFETCH_SRC
src/detection/bluetooth/bluetooth_bsd.c
)
endif()
elseif(NetBSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
@@ -697,13 +706,13 @@ elseif(NetBSD)
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_nosupport.c
src/detection/battery/battery_nbsd.c
src/detection/bios/bios_nbsd.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_nbsd.c
src/detection/bootmgr/bootmgr_nosupport.c
src/detection/brightness/brightness_nosupport.c
src/detection/brightness/brightness_nbsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_nbsd.c
src/detection/cpu/cpu_nbsd.c
@@ -779,13 +788,13 @@ elseif(OpenBSD)
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_nosupport.c
src/detection/battery/battery_obsd.c
src/detection/bios/bios_nosupport.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_nosupport.c
src/detection/bootmgr/bootmgr_nosupport.c
src/detection/brightness/brightness_nosupport.c
src/detection/brightness/brightness_obsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_obsd.c
@@ -913,7 +922,7 @@ elseif(APPLE)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.m
src/detection/wifi/wifi_apple.m
src/detection/wm/wm_apple.c
src/detection/wm/wm_apple.m
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_apple.m
src/detection/camera/camera_apple.m
@@ -994,6 +1003,7 @@ elseif(WIN32)
src/util/windows/registry.c
src/util/windows/unicode.c
src/util/windows/wmi.cpp
src/util/windows/version.c
src/util/platform/FFPlatform_windows.c
src/util/binary_windows.c
)
@@ -1132,6 +1142,14 @@ else()
endif()
endif()
if(ANDROID)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib64 -Wl,-rpath,/system/lib64")
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib -Wl,-rpath,/system/lib")
endif()
endif()
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
ERROR_VARIABLE LD_MUSL_RESULT)
@@ -1467,6 +1485,7 @@ elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "usbhid"
PRIVATE "bluetooth"
)
if(NOT DragonFly)
target_link_libraries(libfastfetch
@@ -1485,6 +1504,7 @@ elseif(OpenBSD)
elseif(NetBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "prop"
)
elseif(SunOS)
target_link_libraries(libfastfetch
@@ -1611,41 +1631,52 @@ target_link_libraries(fastfetch
PRIVATE libfastfetch
)
add_executable(flashfetch
src/flashfetch.c
)
target_compile_definitions(flashfetch
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
)
target_link_libraries(flashfetch
PRIVATE libfastfetch
)
# Prevent fastfetch from linking to libstdc++
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
if(WIN32)
target_sources(fastfetch
PRIVATE src/util/windows/version.rc
)
target_sources(flashfetch
PRIVATE src/util/windows/version.rc
)
elseif(APPLE)
target_link_options(fastfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
target_link_options(flashfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
endif()
if(BINARY_LINK_TYPE STREQUAL "static")
target_link_options(fastfetch PRIVATE "-static")
target_link_options(flashfetch PRIVATE "-static")
endif()
# Apply all above parameters to flashfetch if it is built
if (BUILD_FLASHFETCH)
add_executable(flashfetch
src/flashfetch.c
)
target_compile_definitions(flashfetch
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
)
target_link_libraries(flashfetch
PRIVATE libfastfetch
)
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
if(WIN32)
target_sources(flashfetch
PRIVATE src/util/windows/version.rc
)
elseif(APPLE)
target_link_options(flashfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
endif()
if(BINARY_LINK_TYPE STREQUAL "static")
target_link_options(flashfetch PRIVATE "-static")
endif()
endif()
###################
@@ -1687,10 +1718,17 @@ endif()
include(GNUInstallDirs)
install(
TARGETS fastfetch flashfetch
TARGETS fastfetch
DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
if (TARGET flashfetch)
install(
TARGETS flashfetch
DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
endif()
if (TARGET ffwinrt)
install(
TARGETS ffwinrt
+33
View File
@@ -199,10 +199,43 @@ Try upgrading `pci.ids`: Download <https://pci-ids.ucw.cz/v2.2/pci.ids> and over
Alternatively, you may try to use `fastfetch --gpu-driver-specific`, so that `fastfetch` will try to ask the driver for GPU name if supported.
### Q: I get error `Authorization required, but no authorization protocol specified` when running fastfetch in root
Try `export XAUTHORITY=$HOME/.Xauthority`
### Q: Fastfetch cannot detect my awesome 3rd-party macOS window manager!
Try `fastfetch --wm-detect-plugin`. See also [#984](https://github.com/fastfetch-cli/fastfetch/issues/984)
### Q: How can I change the colors of my ASCII logo?
Try `fastfetch --logo-color-[1-9] <color>`. `[1-9]` is the index of color placeholders.
For example: `fastfetch --logo-color-1 red --logo-color-2 green`.
In JSONC, you can use:
```jsonc
{
"logo": {
"color": {
"1": "red",
"2": "green"
}
}
}
```
### Q: How to hide a key?
Set the key to a white space.
```jsonc
{
"key": " "
}
```
### Q: I want feature A / B / C. Will fastfetch support it?
Fastfetch is a system information tool. We only accept hardware or system level software feature requests. For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script:
+12
View File
@@ -1,3 +1,15 @@
fastfetch (2.33.0) jammy; urgency=medium
* Update to 2.33.0
-- Carter Li <zhangsongcui@live.cn> Thu, 26 Dec 2024 09:42:27 +0800
fastfetch (2.32.0) jammy; urgency=medium
* Update to 2.32.0
-- Carter Li <zhangsongcui@live.cn> Wed, 18 Dec 2024 10:39:06 +0800
fastfetch (2.31.0) jammy; urgency=medium
* Update to 2.31.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.31.0_source.buildinfo universe/utils optional
fastfetch_2.33.0_source.buildinfo universe/utils optional
+5 -4
View File
@@ -275,11 +275,11 @@
"type": "string"
},
"osFormat": {
"description": "Output format of the module `OS`. See `-h format` for formatting syntax\n 1. {sysname}: Name of the kernel\n 2. {name}: Name of the OS\n 3. {pretty-name}: Pretty name of the OS\n 4. {id}: ID of the OS\n 5. {id-like}: ID like of the OS\n 6. {variant}: Variant of the OS\n 7. {variant-id}: Variant ID of the OS\n 8. {version}: Version of the OS\n 9. {version-id}: Version ID of the OS\n 10. {codename}: Version codename of the OS\n 11. {build-id}: Build ID of the OS\n 12. {arch}: Architecture of the OS",
"description": "Output format of the module `OS`. See `-h format` for formatting syntax\n 1. {sysname}: Name of the kernel\n 2. {name}: Name of the OS\n 3. {pretty-name}: Pretty name of the OS, if available\n 4. {id}: ID of the OS\n 5. {id-like}: ID like of the OS\n 6. {variant}: Variant of the OS\n 7. {variant-id}: Variant ID of the OS\n 8. {version}: Version of the OS\n 9. {version-id}: Version ID of the OS\n 10. {codename}: Version codename of the OS\n 11. {build-id}: Build ID of the OS\n 12. {arch}: Architecture of the OS",
"type": "string"
},
"packagesFormat": {
"description": "Output format of the module `Packages`. See `-h format` for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am}: Number of am packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {nix-all}: Total number of all nix packages\n 38. {flatpak-all}: Total number of all flatpak app packages\n 39. {brew-all}: Total number of all brew packages\n 40. {guix-all}: Total number of all guix packages",
"description": "Output format of the module `Packages`. See `-h format` for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {nix-all}: Total number of all nix packages\n 39. {flatpak-all}: Total number of all flatpak app packages\n 40. {brew-all}: Total number of all brew packages\n 41. {guix-all}: Total number of all guix packages",
"type": "string"
},
"physicaldiskFormat": {
@@ -315,7 +315,7 @@
"type": "string"
},
"soundFormat": {
"description": "Output format of the module `Sound`. See `-h format` for formatting syntax\n 1. {is-main}: Is main sound device\n 2. {name}: Device name\n 3. {volume-percentage}: Volume (in percentage num)\n 4. {identifier}: Identifier\n 5. {volume-percentage-bar}: Volume (in percentage bar)",
"description": "Output format of the module `Sound`. See `-h format` for formatting syntax\n 1. {is-main}: Is main sound device\n 2. {name}: Device name\n 3. {volume-percentage}: Volume (in percentage num)\n 4. {identifier}: Identifier\n 5. {volume-percentage-bar}: Volume (in percentage bar)\n 6. {platform-api}: Platform API used",
"type": "string"
},
"swapFormat": {
@@ -375,7 +375,7 @@
"type": "string"
},
"wmFormat": {
"description": "Output format of the module `WM`. See `-h format` for formatting syntax\n 1. {process-name}: WM process name\n 2. {pretty-name}: WM pretty name\n 3. {protocol-name}: WM protocol name\n 4. {plugin-name}: WM plugin name",
"description": "Output format of the module `WM`. See `-h format` for formatting syntax\n 1. {process-name}: WM process name\n 2. {pretty-name}: WM pretty name\n 3. {protocol-name}: WM protocol name\n 4. {plugin-name}: WM plugin name\n 5. {version}: WM version",
"type": "string"
},
"wifiFormat": {
@@ -432,6 +432,7 @@
"sixel",
"kitty",
"kitty-direct",
"kitty-icat",
"iterm",
"chafa",
"raw",
+3
View File
@@ -169,6 +169,9 @@ bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFst
? GetCurrentProcess()
: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (hProcess == NULL)
return false;
if (gui)
*gui = GetGuiResources(hProcess, GR_GDIOBJECTS) > 0;
+10 -1
View File
@@ -186,7 +186,8 @@
"data-raw": "Text data, printed as is",
"sixel": "Image file, printed as sixel codes",
"kitty": "Image file, printed as kitty graphics protocol",
"kitty_direct": "Image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)",
"kitty-direct": "Image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)",
"kitty-icat": "Image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed",
"iterm": "Image file, printed as iterm graphics protocol",
"chafa": "Image file, printed as ascii art using libchafa",
"raw": "Image file, printed as raw binary string",
@@ -351,6 +352,14 @@
"type": "path"
}
},
{
"long": "kitty-icat",
"desc": "Short for --logo-type kitty-icat --logo <path>",
"remark": "See \"--help logo-type\" for more info",
"arg": {
"type": "path"
}
},
{
"long": "iterm",
"desc": "Short for --logo-type iterm --logo <path>",
+107
View File
@@ -0,0 +1,107 @@
#include "battery.h"
#include "common/io/io.h"
#include "util/FFstrbuf.h"
#include "util/stringUtils.h"
#include <prop/prop_array.h>
#include <prop/prop_bool.h>
#include <prop/prop_dictionary.h>
#include <prop/prop_object.h>
#include <sys/envsys.h>
#include <prop/proplib.h>
#include <paths.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
bool acConnected = false;
{
prop_array_t acad = prop_dictionary_get(root, "acpiacad0");
if (acad)
{
prop_dictionary_t dict = prop_array_get(acad, 0);
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &acConnected);
}
}
prop_object_iterator_t itKey = prop_dictionary_iterator(root);
for (prop_dictionary_keysym_t key; (key = prop_object_iterator_next(itKey)) != NULL; )
{
if (!ffStrStartsWith(prop_dictionary_keysym_value(key), "acpibat")) continue;
prop_array_t bat = prop_dictionary_get_keysym(root, key);
uint32_t max = 0, curr = 0, dischargeRate = 0;
bool charging = false, critical = false;
prop_object_iterator_t iter = prop_array_iterator(bat);
for (prop_dictionary_t dict; (dict = prop_object_iterator_next(iter)) != NULL;)
{
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
continue;
const char* desc = NULL;
if (!prop_dictionary_get_string(dict, "description", &desc))
continue;
if (ffStrEquals(desc, "present"))
{
int value = 0;
if (prop_dictionary_get_int(dict, "cur-value", &value) && value == 0)
continue;
}
else if (ffStrEquals(desc, "charging"))
{
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &charging);
}
else if (ffStrEquals(desc, "charge"))
{
prop_dictionary_get_uint32(dict, "max-value", &max);
prop_dictionary_get_uint32(dict, "cur-value", &curr);
const char* state = NULL;
if (prop_dictionary_get_string(dict, "state", &state) && ffStrEquals(state, "critical"))
critical = true;
}
else if (ffStrEquals(desc, "discharge rate"))
{
prop_dictionary_get_uint(dict, "cur-value", &dischargeRate);
}
}
if (max > 0)
{
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->timeRemaining = -1;
battery->capacity = (double) curr / (double) max * 100.;
if (charging)
ffStrbufAppendS(&battery->status, "Charging, ");
else if (dischargeRate)
ffStrbufAppendS(&battery->status, "Discharging, ");
if (critical)
ffStrbufAppendS(&battery->status, "Critical, ");
if (acConnected)
ffStrbufAppendS(&battery->status, "AC Connected");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
prop_object_iterator_release(itKey);
return NULL;
}
+52
View File
@@ -0,0 +1,52 @@
#include "battery.h"
#include "common/io/io.h"
#include <machine/apmvar.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result)
{
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY);
if (devfd < 0) return "open(dev/apm, O_RDONLY) failed";
struct apm_power_info info = {};
if (ioctl(devfd, APM_IOC_GETPOWER, &info) < 0)
return "ioctl(APM_IOC_GETPOWER) failed";
if (info.battery_state == APM_BATTERY_ABSENT)
return NULL;
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(result);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
battery->timeRemaining = -1;
battery->capacity = info.battery_life;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
if (info.ac_state == APM_AC_ON)
ffStrbufAppendS(&battery->status, "AC Connected");
else if (info.ac_state == APM_AC_BACKUP)
ffStrbufAppendS(&battery->status, "Backup In Use");
else if (info.ac_state == APM_AC_OFF)
{
battery->timeRemaining = (int) info.minutes_left * 60;
ffStrbufAppendS(&battery->status, "Discharging");
}
if (info.battery_state == APM_BATT_CRITICAL || info.battery_state == APM_BATT_CHARGING)
{
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
ffStrbufAppendS(&battery->status, info.battery_state == APM_BATT_CRITICAL ? "Critical" : "Charging");
}
return NULL;
}
+1 -1
View File
@@ -11,4 +11,4 @@ typedef struct FFBluetoothResult
bool connected;
} FFBluetoothResult;
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */);
+4 -1
View File
@@ -10,7 +10,7 @@
@property (nonatomic) uint8_t batteryPercentSingle;
@end
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
if(!ioDevices)
@@ -18,6 +18,9 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
for(IOBluetoothDevice* ioDevice in ioDevices)
{
if (!options->showDisconnected && !ioDevice.isConnected)
continue;
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
+25
View File
@@ -0,0 +1,25 @@
#include "bluetooth.h"
#define L2CAP_SOCKET_CHECKED
#include <bluetooth.h>
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices)
{
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, bt_devremote_name_gen(dev->devname, &dev->bdaddr));
ffStrbufInitS(&device->address, bt_ntoa(&dev->bdaddr, NULL));
ffStrbufUpperCase(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = true;
return 0;
}
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
// struct hostent* ent = bt_gethostent();
if (bt_devenum((void*) enumDev, devices) < 0)
return "bt_devenum() failed";
return 0;
}
+68 -22
View File
@@ -3,6 +3,7 @@
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/io/io.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
@@ -44,16 +45,16 @@ array [ //root
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
static bool detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return true;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
return true;
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
@@ -74,6 +75,13 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
}
else if(ffStrEquals(deviceProperty, "Connected"))
ffDBusGetBool(dbus, &dictIter, &device->connected);
else if(ffStrEquals(deviceProperty, "Paired"))
{
bool paired = true;
ffDBusGetBool(dbus, &dictIter, &paired);
if (!paired) return false;
}
return true;
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
@@ -103,32 +111,37 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
do
{
detectBluetoothValue(dbus, &arrayIter, device);
bool shouldContinue = detectBluetoothValue(dbus, &arrayIter, device);
if (!shouldContinue)
{
ffStrbufClear(&device->name);
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return NULL;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
return NULL;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
// We don't want adapter objects
if(!ffStrContains(objectPath, "/dev_"))
return;
return NULL;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
return NULL;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
@@ -145,16 +158,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}
return device;
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter, int32_t connectedCount)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
@@ -164,11 +171,25 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
FFBluetoothResult* device = detectBluetoothObject(devices, dbus, &arrayIter);
if (device)
{
if(device->name.length == 0 || (connectedCount > 0 && !device->connected))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}
if (device->connected && --connectedCount == 0)
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices)
static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
{
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
@@ -186,18 +207,43 @@ static const char* detectBluetooth(FFlist* devices)
return "Failed to get root iterator of GetManagedObjects";
}
detectBluetoothRoot(devices, &dbus, &rootIter);
detectBluetoothRoot(devices, &dbus, &rootIter, connectedCount);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
static uint32_t connectedDevices(void)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
return 0;
uint32_t result = 0;
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (strchr(entry->d_name, ':') != NULL)
++result;
}
return result;
}
#endif
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
int32_t connectedCount = -1;
if (!options->showDisconnected)
{
connectedCount = (int32_t) connectedDevices();
if (connectedCount == 0)
return NULL;
}
return detectBluetooth(devices, connectedCount);
#else
return "Fastfetch was compiled without DBus support";
#endif
@@ -1,6 +1,6 @@
#include "bluetooth.h"
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
return "Not supported on this platform";
}
+5 -4
View File
@@ -7,7 +7,7 @@
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
// Actually bluetoothapis.dll, but it's missing on Windows 7
FF_LIBRARY_LOAD(bluetoothapis, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
@@ -20,13 +20,14 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) {
.fReturnConnected = TRUE,
.fReturnRemembered = TRUE,
.fReturnAuthenticated = TRUE,
.fReturnUnknown = TRUE,
.fReturnRemembered = options->showDisconnected,
.fReturnAuthenticated = options->showDisconnected,
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)
}, &btdi);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return NULL;
return "BluetoothFindFirstDevice() failed";
}
@@ -55,7 +55,7 @@ const char* ffBluetoothDetectBattery(FFlist* devices)
on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); });
IWbemClassObject* pResultObject = nullptr;
if (FAILED(pCallResult->GetResultObject(WBEM_INFINITE, &pResultObject)))
if (FAILED(pCallResult->GetResultObject((LONG) WBEM_INFINITE, &pResultObject)))
continue;
on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); });
@@ -3,56 +3,47 @@
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/io/io.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
/* Example dbus reply:
array [
dict entry(
object path "/org/bluez/hci0"
array [
dict entry(
string "org.bluez.Adapter1"
array [
dict entry(
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "xxxxxxxx"
)
dict entry(
string "Powered"
variant boolean true
)
dict entry(
string "PowerState"
variant string "on"
)
dict entry(
string "Manufacturer"
variant uint16 2
)
dict entry(
string "Version"
variant byte 12
)
]
)
]
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "xxxxxxxx"
)
dict entry(
string "Powered"
variant boolean true
)
dict entry(
string "PowerState"
variant string "on"
)
dict entry(
string "Manufacturer"
variant uint16 2
)
dict entry(
string "Version"
variant byte 12
)
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
static const char* detectBluetoothProperty(FFBluetoothRadioResult* device, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return "Expected dict entry";
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
return "Expected dict entry key to be a string";
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
@@ -77,121 +68,73 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
ffDBusGetBool(dbus, &dictIter, &device->discoverable);
else if(ffStrEquals(deviceProperty, "Pairable"))
ffDBusGetBool(dbus, &dictIter, &device->connectable);
return NULL;
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const char* hciName, FFDBusData* dbus)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
char objPath[300];
snprintf(objPath, sizeof(objPath), "/org/bluez/%s", hciName);
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
DBusMessage* properties = ffDBusGetMethodReply(dbus, "org.bluez", objPath, "org.freedesktop.DBus.Properties", "GetAll", "org.bluez.Adapter1");
if(!properties)
return "Failed to call org.freedesktop.DBus.Properties.GetAll";
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(!ffStrContains(propertyType, ".Adapter"))
return; //We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
do
DBusMessageIter rootIter;
if(!dbus->lib->ffdbus_message_iter_init(properties, &rootIter))
{
detectBluetoothValue(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We want adapter objects
if(!ffStrStartsWith(objectPath, "/org/bluez/hci") || ffStrContains(objectPath, "/dev_"))
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
do
{
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
--devices->length;
dbus->lib->ffdbus_message_unref(properties);
return "Failed to get root iterator of org.freedesktop.DBus.Properties.GetAll";
}
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
if(dbus->lib->ffdbus_message_iter_get_arg_type(&rootIter) != DBUS_TYPE_ARRAY)
{
dbus->lib->ffdbus_message_unref(properties);
return "Expected array";
}
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
dbus->lib->ffdbus_message_iter_recurse(&rootIter, &arrayIter);
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
detectBluetoothProperty(device, dbus, &arrayIter);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
dbus->lib->ffdbus_message_unref(properties);
return NULL;
}
static const char* detectBluetooth(FFlist* devices)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
return "Failed to open /sys/class/bluetooth";
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
if(!managedObjects)
return "Failed to call GetManagedObjects";
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
dbus.lib->ffdbus_message_unref(managedObjects);
return "Failed to get root iterator of GetManagedObjects";
if (entry->d_name[0] == '.')
continue;
if (strchr(entry->d_name, ':') != NULL) // ignore connected devices
continue;
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
detectBluetoothRoot(device, entry->d_name, &dbus);
}
detectBluetoothRoot(devices, &dbus, &rootIter);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
@@ -202,7 +145,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
#else
FF_UNUSED(devices)
FF_UNUSED(devices)
return "Fastfetch was compiled without DBus support";
#endif
}
+2
View File
@@ -10,6 +10,8 @@ const char* ffDetectBoard(FFBoardResult* board)
ffCleanUpSmbiosValue(&board->version);
if (ffSysctlGetString("machdep.dmi.board-vendor", &board->vendor) == NULL)
ffCleanUpSmbiosValue(&board->vendor);
if (ffSysctlGetString("machdep.dmi.board-serial", &board->serial) == NULL)
ffCleanUpSmbiosValue(&board->serial);
return NULL;
}
+1 -1
View File
@@ -34,7 +34,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
brightness->current = status.brightness;
struct backlight_info info;
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
if(ioctl(blfd, BACKLIGHTGETINFO, &info) == 0)
ffStrbufAppendS(&brightness->name, info.name);
else
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
@@ -0,0 +1,25 @@
#include "brightness.h"
#include "common/sysctl.h"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
// https://man.netbsd.org/NetBSD-10.1/acpiout.4#DESCRIPTION
char key[] = "hw.acpi.acpiout0.brightness";
char* pn = key + strlen("hw.acpi.acpiout");
for (uint32_t i = 0; i <= 9; ++i)
{
*pn = (char) ('0' + i);
int value = ffSysctlGetInt(key, -1);
if (value == -1) continue;
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitF(&brightness->name, "acpiout%d", i);
brightness->max = 100;
brightness->min = 0;
brightness->current = value;
}
return NULL;
}
@@ -0,0 +1,30 @@
#include "brightness.h"
#include "common/io/io.h"
#include <dev/wscons/wsconsio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
FF_AUTO_CLOSE_FD int devfd = open("/dev/ttyC0", O_RDONLY);
if (devfd < 0) return "open(dev/ttyC0, O_RDONLY) failed";
struct wsdisplay_param param = {
.param = WSDISPLAYIO_PARAM_BRIGHTNESS,
};
if (ioctl(devfd, WSDISPLAYIO_GETPARAM, &param) < 0)
return "ioctl(WSDISPLAYIO_GETPARAM) failed";
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitStatic(&brightness->name, "wsdisplay");
brightness->max = param.max;
brightness->min = param.min;
brightness->current = param.curval;
return NULL;
}
+2
View File
@@ -10,6 +10,8 @@ const char* ffDetectChassis(FFChassisResult* chassis)
ffCleanUpSmbiosValue(&chassis->version);
if (ffSysctlGetString("machdep.dmi.chassis-vendor", &chassis->vendor) == NULL)
ffCleanUpSmbiosValue(&chassis->vendor);
if (ffSysctlGetString("machdep.dmi.chassis-serial", &chassis->serial) == NULL)
ffCleanUpSmbiosValue(&chassis->serial);
return NULL;
}
+47 -1
View File
@@ -44,12 +44,20 @@ static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer)
if(
ffStrbufContainS(buffer, "cpu") ||
ffStrbufEqualS(buffer, "k10temp") || // AMD
ffStrbufEqualS(buffer, "fam15h_power") || // AMD
ffStrbufEqualS(buffer, "coretemp") // Intel
) return value / 1000.;
return 0.0/0.0;
}
static double detectTZTemp(FFstrbuf* buffer)
{
if (ffReadFileBuffer("/sys/class/thermal/thermal_zone0/temp", buffer))
return ffStrbufToDouble(buffer) / 1000.;
return 0.0/0.0;
}
static double detectCPUTemp(void)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
@@ -79,7 +87,7 @@ static double detectCPUTemp(void)
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
return 0.0/0.0;
return detectTZTemp(&buffer);
}
#ifdef __ANDROID__
@@ -136,6 +144,36 @@ static void detectQualcomm(FFCPUResult* cpu)
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 1 [SM4375]");
}
static void detectMediaTek(FFCPUResult* cpu)
{
// https://en.wikipedia.org/wiki/List_of_MediaTek_systems_on_chips
if (ffStrbufEqualS(&cpu->name, "MT6991"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9400 [MT6991]");
else if (ffStrbufEqualS(&cpu->name, "MT6991Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9400 [MT6991Z]");
else if (ffStrbufEqualS(&cpu->name, "MT6989Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300+ [MT6989Z]");
else if (ffStrbufEqualS(&cpu->name, "MT8796Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300+ [MT8796Z]");
else if (ffStrbufEqualS(&cpu->name, "MT6989"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300 [MT6989]");
else if (ffStrbufEqualS(&cpu->name, "MT8796"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9300 [MT8796]");
else if (ffStrbufEqualS(&cpu->name, "MT6985W"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9200+ [MT6985W]");
else if (ffStrbufEqualS(&cpu->name, "MT6985"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9200 [MT6985]");
else if (ffStrbufEqualS(&cpu->name, "MT6983W"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000+ [MT6983W]");
else if (ffStrbufEqualS(&cpu->name, "MT8798Z/T"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000+ [MT8798Z/T]");
else if (ffStrbufEqualS(&cpu->name, "MT6983Z"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000 [MT6983Z]");
else if (ffStrbufEqualS(&cpu->name, "MT8798Z/C"))
ffStrbufSetStatic(&cpu->name, "MediaTek Dimensity 9000 [MT8798Z/C]");
}
static void detectAndroid(FFCPUResult* cpu)
{
if (cpu->name.length == 0)
@@ -153,6 +191,8 @@ static void detectAndroid(FFCPUResult* cpu)
if (ffStrbufEqualS(&cpu->vendor, "QTI") && ffStrbufStartsWithS(&cpu->name, "SM"))
detectQualcomm(cpu);
else if (ffStrbufEqualS(&cpu->vendor, "MTK") && ffStrbufStartsWithS(&cpu->name, "MT"))
detectMediaTek(cpu);
}
#endif
@@ -188,6 +228,7 @@ static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
{
// https://github.com/Dr-Noob/cpufetch/issues/213#issuecomment-1927782105
ffStrbufSetStatic(&cpu->name, "Virtualized Apple Silicon");
ffStrbufGetlineRestore(&line, &len, cpuinfo);
return;
}
name = applePartId2name(partId);
@@ -243,7 +284,10 @@ static const char* parseCpuInfo(
&& cpu->name.length > 0 // #1202 #1204
#endif
)
{
ffStrbufGetlineRestore(&line, &len, cpuinfo);
break;
}
(void)(
// arm64 doesn't have "model name"; arm32 does have "model name" but its value is not useful.
@@ -512,6 +556,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
#if __x86_64__ || __i386__
cpu->packages = getPackageCount(&cpuinfo);
if (cpu->packages > 1)
cpu->coresPhysical *= cpu->packages;
#endif
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
+38 -26
View File
@@ -1,26 +1,42 @@
#include "cpu.h"
#include "common/sysctl.h"
#include <sys/sysctl.h>
#include "common/io/io.h"
#include <sys/envsys.h>
#include <prop/proplib.h>
#include <paths.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
static const char* detectCpuTemp(double* current)
{
int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed";
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
return NULL;
}
prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
static const char* detectThermalTemp(double* current)
{
int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed";
prop_array_t array = prop_dictionary_get(root, "coretemp0");
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
if (!array) array = prop_dictionary_get(root, "viac7temp0");
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
if (!array) return "No temp data found in root dictionary";
if (prop_array_count(array) != 2)
return "Unexpected `xtemp0` data";
prop_dictionary_t dict = prop_array_get(array, 0);
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
return "Unexpected `xtemp0[0]`";
int temp = 0; // in µK
if (!prop_dictionary_get_int(dict, "cur-value", &temp))
return "Failed to get temperature";
*current = temp / 1e6 - 273.15;
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
return NULL;
}
@@ -32,26 +48,22 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
return "sysctlbyname(machdep.cpu_brand) failed";
}
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL)
ffStrbufTrimRightSpace(&cpu->vendor);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresLogical = cpu->coresPhysical;
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.ncpuonline", cpu->coresLogical);
ffCPUDetectSpeedByCpuid(cpu);
{
struct clockinfo info;
size_t length = sizeof(info);
if (sysctl((int[]) {CTL_KERN, KERN_CLOCKRATE}, 2, &info, &length, NULL, 0) == 0)
cpu->frequencyBase = (uint32_t) info.hz / 1000;
}
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
if (freq > cpu->frequencyBase)
cpu->frequencyBase = freq;
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
{
if (detectCpuTemp(&cpu->temperature) != NULL)
detectThermalTemp(&cpu->temperature);
}
if (options->temp) detectCpuTemp(&cpu->temperature);
return NULL;
}
-2
View File
@@ -13,8 +13,6 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
return "sysctl({HW_DISKSTATS}, NULL) failed";
uint32_t nDrive = (uint32_t) (len / sizeof(struct diskstats));
printf("C: %d\n", nDrive);
struct diskstats* stats = malloc(len);
if (sysctl(mib, ARRAY_SIZE(mib), stats, &len, NULL, 0) < 0)
+3
View File
@@ -62,6 +62,9 @@ static const char* parseEnv(void)
if(getenv("HYPRLAND_CMD") != NULL)
return "Hyprland";
if(getenv("SWAYSOCK") != NULL)
return "Sway";
#ifdef __linux__
if(
getenv("WAYLAND_DISPLAY") != NULL &&
+1 -1
View File
@@ -16,7 +16,7 @@ const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
const char* FF_GPU_VENDOR_NAME_REDHAT = "RedHat";
const char* FF_GPU_VENDOR_NAME_ORACLE = "Oracle";
const char* ffGetGPUVendorString(unsigned vendorId)
const char* ffGPUGetVendorString(unsigned vendorId)
{
// https://devicehunt.com/all-pci-vendors
switch (vendorId)
+1 -1
View File
@@ -46,7 +46,7 @@ typedef struct FFGPUResult
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGetGPUVendorString(unsigned vendorId);
const char* ffGPUGetVendorString(unsigned vendorId);
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__)
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
+1 -1
View File
@@ -161,7 +161,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
int vendorId;
if(ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL)
{
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
const char* vendorStr = ffGPUGetVendorString((unsigned) vendorId);
ffStrbufAppendS(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL)
gpu->type = FF_GPU_TYPE_INTEGRATED;
+1 -1
View File
@@ -38,7 +38,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
struct pci_conf* pc = &confs[i];
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(pc->pc_vendor));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor));
ffStrbufInit(&gpu->name);
ffStrbufInitS(&gpu->driver, pc->pd_name);
ffStrbufInit(&gpu->platformApi);
+2 -2
View File
@@ -15,7 +15,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_slot_match_iterator_create)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_device_next)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_system_cleanup)
{
// Requires root access
// Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci`
@@ -31,7 +31,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(dev->vendor_id));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->vendor_id));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
+1 -1
View File
@@ -435,7 +435,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
return "Invalid PCI device path";
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
+1 -1
View File
@@ -51,7 +51,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
uint32_t revision = (uint32_t) strtoul(pclass, NULL, 16);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
+2 -2
View File
@@ -72,7 +72,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
{
uint32_t vendorId = 0;
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
@@ -147,7 +147,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
{
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
}
detectFn(
+1 -1
View File
@@ -104,7 +104,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
DXCoreHardwareID hardwareId;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId)))
{
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
const char* vendorStr = ffGPUGetVendorString((unsigned) hardwareId.vendorID);
ffStrbufSetStatic(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && (options->driverSpecific || options->temp))
+4 -4
View File
@@ -109,11 +109,11 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
const char* version = hwModel->chars + strlen("Mac");
if(ffStrEquals(version, "16,3")) return "iMac (24-inch, 2024, Four Thunderbolt / USB 4 ports)";
if(ffStrEquals(version, "16,2")) return "iMac (24-inch, 2024, Two Thunderbolt / USB 4 ports)";
if(ffStrEquals(version, "16,1") ||
ffStrEquals(version, "16,6") ||
ffStrEquals(version, "16,8")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)";
if(ffStrEquals(version, "16,1")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)";
if(ffStrEquals(version, "16,6") ||
ffStrEquals(version, "16,8")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 5 ports)";
if(ffStrEquals(version, "16,7") ||
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 4 ports)";
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 5 ports)";
if(ffStrEquals(version, "16,15") ||
ffStrEquals(version, "16,10")) return "Mac mini (2024)";
if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)";
+4
View File
@@ -12,6 +12,10 @@ const char* ffDetectHost(FFHostResult* host)
ffCleanUpSmbiosValue(&host->vendor);
if (ffSysctlGetString("machdep.dmi.system-version", &host->version) == NULL)
ffCleanUpSmbiosValue(&host->version);
if (ffSysctlGetString("machdep.dmi.system-serial", &host->serial) == NULL)
ffCleanUpSmbiosValue(&host->serial);
if (ffSysctlGetString("machdep.dmi.system-uuid", &host->uuid) == NULL)
ffCleanUpSmbiosValue(&host->uuid);
return NULL;
}
+15 -16
View File
@@ -78,7 +78,7 @@ static bool parseMprisMetadata(FFDBusData* data, DBusMessageIter* rootIterator,
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
{
// Get all properties at once to reduce the number of IPCs
DBusMessage* reply = ffDBusGetAllProperties(data, busName, "/org/mpris/MediaPlayer2", "");
DBusMessage* reply = ffDBusGetAllProperties(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player");
if(reply == NULL)
return false;
@@ -93,8 +93,6 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
DBusMessageIter arrayIterator;
data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
FF_STRBUF_AUTO_DESTROY desktopIdentity = ffStrbufCreate();
while(true)
{
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
@@ -112,10 +110,6 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
parseMprisMetadata(data, &dictIterator, result);
else if(ffStrEquals(key, "PlaybackStatus"))
ffDBusGetString(data, &dictIterator, &result->status);
else if(ffStrEquals(key, "Identity"))
ffDBusGetString(data, &dictIterator, &result->player);
else if(ffStrEquals(key, "DesktopEntry"))
ffDBusGetString(data, &dictIterator, &desktopIdentity);
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
}
@@ -128,17 +122,22 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
return false;
}
if (result->player.length == 0)
//Set short bus name
ffStrbufAppendS(&result->playerId, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
//We found a song, get the player name
if (ffStrbufStartsWithS(&result->playerId, "musikcube.instance"))
{
if (desktopIdentity.length > 0)
{
ffStrbufDestroy(&result->player);
ffStrbufInitMove(&result->player, &desktopIdentity);
}
else
{
// dbus calls are EXTREMELY slow on musikcube, so we set the player name manually
ffStrbufSetStatic(&result->player, "musikcube");
}
else
{
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player);
if(result->player.length == 0)
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player);
if(result->player.length == 0)
ffStrbufAppend(&result->player, &result->playerId);
}
}
data->lib->ffdbus_message_unref(reply);
+1 -1
View File
@@ -112,7 +112,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
{
cl_uint vendorId;
if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(vendorId), &vendorId, NULL) == CL_SUCCESS)
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
if (gpu->vendor.length == 0 && data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS)
ffStrbufSetS(&gpu->vendor, buffer);
}
+7
View File
@@ -4,6 +4,13 @@
#include <string.h>
#if __ANDROID__ && !defined(FF_HAVE_EGL)
// On Android, installing OpenGL headers is enough (mesa-dev)
#if __has_include(<EGL/egl.h>)
#define FF_HAVE_EGL 1
#endif
#endif
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
#define FF_HAVE_GL 1
+12 -6
View File
@@ -3,7 +3,7 @@
#if __has_include(<GL/gl.h>)
#include <GL/gl.h>
#elif __has_include(<OpenGL/gl.h>)
#elif __APPLE__
#define GL_SILENCE_DEPRECATION 1
#include <OpenGL/gl.h>
#else
@@ -64,9 +64,14 @@ static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data)
return NULL;
}
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data, bool gles)
{
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){
EGL_CONTEXT_CLIENT_VERSION, gles ? 2 : 1, // Try GLES 2.0+ first
EGL_NONE
});
if(data->context == EGL_NO_CONTEXT && gles) // Some ANGLE builds support GLES 1.1 only
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
if(data->context == EGL_NO_CONTEXT)
return "eglCreateContext returned EGL_NO_CONTEXT";
@@ -78,10 +83,11 @@ static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
{
// try use OpenGL API. If failed, use the default API (usually OpenGL ES)
data->ffeglBindAPI(EGL_OPENGL_API);
bool gles = !data->ffeglBindAPI(EGL_OPENGL_API);
EGLint eglConfigCount;
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
if(eglConfigCount == 0)
return "eglGetConfigs returned 0 configs";
@@ -94,7 +100,7 @@ static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
if(data->surface == EGL_NO_SURFACE)
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
const char* error = eglHandleSurface(result, data);
const char* error = eglHandleSurface(result, data, gles);
data->ffeglDestroySurface(data->display, data->surface);
return error;
}
@@ -148,7 +154,7 @@ const char* ffOpenGLDetectByEGL(FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
FF_SUPPRESS_IO();
// FF_SUPPRESS_IO();
return eglHandleData(result, &eglData);
}
-2
View File
@@ -5,8 +5,6 @@ void ffDetectOSImpl(FFOSResult* os)
{
ffStrbufSetStatic(&os->name, "Android");
ffStrbufSetStatic(&os->prettyName, "Android");
ffStrbufSetStatic(&os->id, "android");
ffSettingsGetAndroidProperty("ro.build.version.release", &os->version);
+11 -13
View File
@@ -54,18 +54,18 @@ static bool detectOSCodeName(FFOSResult* os)
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"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true;
case 7: ffStrbufSetStatic(&os->codename, "Lion"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 5: ffStrbufSetStatic(&os->codename, "Leopard"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 4: ffStrbufSetStatic(&os->codename, "Tiger"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); 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"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 1: ffStrbufSetStatic(&os->codename, "Puma"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); 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;
}
}
}
@@ -106,8 +106,6 @@ void ffDetectOSImpl(FFOSResult* os)
if(os->buildID.length == 0)
ffSysctlGetString("kern.osversion", &os->buildID);
if(os->prettyName.length == 0)
ffStrbufSetStatic(&os->prettyName, "macOS");
ffStrbufAppend(&os->versionID, &os->version);
if(!detectOSCodeName(os))
+31 -23
View File
@@ -46,13 +46,33 @@ static bool parseOsRelease(const char* fileName, FFOSResult* result)
});
}
// Common logic for detecting Armbian image version
FF_MAYBE_UNUSED static bool detectArmbianVersion(FFOSResult* result)
{
if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Official Armbian release images
ffStrbufSetS(&result->name, "Armbian");
else if (ffStrbufStartsWithS(&result->prettyName, "Armbian-unofficial ")) // Unofficial Armbian image built from source
ffStrbufSetS(&result->name, "Armbian (custom build)");
else
return false;
ffStrbufSet(&result->idLike, &result->id);
ffStrbufSetS(&result->id, "armbian");
ffStrbufClear(&result->versionID);
uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1;
uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' ');
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
return true;
}
FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
{
const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
if(!ffStrSet(xdgConfigDirs))
return;
if(ffStrbufStartsWithS(&result->prettyName, "Linux Lite "))
if (detectArmbianVersion(result))
return;
else if(ffStrbufStartsWithS(&result->prettyName, "Linux Lite "))
{
ffStrbufSetS(&result->name, "Linux Lite");
ffStrbufSetS(&result->id, "linuxlite");
@@ -60,6 +80,14 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Linux Lite "));
return;
}
else if(ffStrbufStartsWithS(&result->prettyName, "Rhino Linux "))
{
ffStrbufSetS(&result->name, "Rhino Linux");
ffStrbufSetS(&result->id, "rhinolinux");
ffStrbufSetS(&result->idLike, "ubuntu");
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Rhino Linux "));
return;
}
if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu"))
{
@@ -79,7 +107,7 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
return;
}
if(ffStrContains(xdgConfigDirs, "lxde") || ffStrContains(xdgConfigDirs, "lubuntu"))
if(ffStrContains(xdgConfigDirs, "lxqt") || ffStrContains(xdgConfigDirs, "lubuntu"))
{
ffStrbufSetS(&result->name, "Lubuntu");
ffStrbufSetS(&result->prettyName, "Lubuntu");
@@ -164,28 +192,8 @@ FF_MAYBE_UNUSED static void getDebianVersion(FFOSResult* result)
FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
{
if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Armbian 24.2.1 bookworm
{
ffStrbufSetS(&result->name, "Armbian");
ffStrbufSetS(&result->id, "armbian");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufClear(&result->versionID);
uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1;
uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' ');
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
if (detectArmbianVersion(result))
return true;
}
else if (ffStrbufStartsWithS(&result->prettyName, "Armbian-unofficial ")) // Unofficial Armbian image built from source
{
ffStrbufSetS(&result->name, "Armbian (custom build)");
ffStrbufSetS(&result->id, "armbian");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufClear(&result->versionID);
uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1;
uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' ');
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
return true;
}
else if (ffStrbufStartsWithS(&result->name, "Loc-OS"))
{
ffStrbufSetS(&result->id, "locos");
+3 -4
View File
@@ -13,6 +13,7 @@ void ffDetectOSImpl(FFOSResult* os)
const wchar_t* rawName = BrandingFormatString(L"%WINDOWS_LONG%");
ffStrbufSetWS(&os->variant, rawName);
GlobalFree((HGLOBAL)rawName);
ffStrbufSet(&os->prettyName, &os->variant);
ffStrbufTrimRight(&os->variant, ' ');
//WMI returns the "Microsoft" prefix while BrandingFormatString doesn't. Make them consistent.
@@ -22,14 +23,12 @@ void ffDetectOSImpl(FFOSResult* os)
if(ffStrbufStartsWithS(&os->variant, "Windows "))
{
ffStrbufAppendS(&os->name, "Windows");
ffStrbufAppendS(&os->prettyName, "Windows");
ffStrbufSubstrAfter(&os->variant, strlen("Windows ") - 1);
if(ffStrbufStartsWithS(&os->variant, "Server "))
{
ffStrbufAppendS(&os->name, " Server");
ffStrbufAppendS(&os->prettyName, " Server");
ffStrbufSubstrAfter(&os->variant, strlen(" Server") - 1);
}
@@ -38,7 +37,7 @@ void ffDetectOSImpl(FFOSResult* os)
ffStrbufSubstrAfter(&os->variant, index);
// Windows Server 20xx Rx
if(ffStrbufEndsWithC(&os->prettyName, 'r'))
if(ffStrbufEndsWithC(&os->name, 'r'))
{
if(os->variant.chars[0] == 'R' &&
ffCharIsDigit(os->variant.chars[1]) &&
@@ -56,6 +55,6 @@ void ffDetectOSImpl(FFOSResult* os)
ffStrbufClear(&os->variant);
}
ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars);
ffStrbufAppendF(&os->id, "%s %s", os->name.chars, os->version.chars);
ffStrbufSetStatic(&os->idLike, "Windows");
}
+2 -1
View File
@@ -4,7 +4,8 @@
typedef struct FFPackagesResult
{
uint32_t am;
uint32_t amSystem;
uint32_t amUser;
uint32_t apk;
uint32_t brew;
uint32_t brewCask;
+1 -1
View File
@@ -52,7 +52,7 @@ static void getBrewPackages(FFPackagesResult* result)
static uint32_t countMacPortsPackages(const char* dirname)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname);
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/var/macports/software");
ffStrbufAppendS(&baseDir, "/var/macports/software");
return getNumElements(baseDir.chars, DT_DIR);
}
+42 -18
View File
@@ -386,7 +386,29 @@ static uint32_t getRpmFromLibrpm(void)
#endif //FF_HAVE_RPM
static uint32_t getAM(FFstrbuf* baseDir)
static uint32_t getAMPackages(FFstrbuf* baseDir)
{
uint32_t baseLength = baseDir->length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
if (!dirp) return 0;
uint32_t result = 0;
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
if (entry->d_type == DT_DIR)
{
ffStrbufAppendF(baseDir, "/%s/remove", entry->d_name);
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
++result;
ffStrbufSubstrBefore(baseDir, baseLength);
}
}
return result;
}
static uint32_t getAMSystem(FFstrbuf* baseDir)
{
// #771
uint32_t baseDirLength = baseDir->length;
@@ -401,28 +423,27 @@ static uint32_t getAM(FFstrbuf* baseDir)
{
++result; // `am` itself is counted as a package too
ffStrbufSubstrBefore(baseDir, optDirLength);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
if(dirp)
{
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
if (entry->d_type == DT_DIR)
{
ffStrbufAppendF(baseDir, "/%s/AM-updater", entry->d_name);
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
++result;
ffStrbufSubstrBefore(baseDir, optDirLength);
}
}
}
result = getAMPackages(baseDir);
}
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
static uint32_t getAMUser(void)
{
// check if $XDG_CONFIG_HOME/appman/appman-config exists
FFstrbuf* baseDir = FF_LIST_GET(FFstrbuf, instance.state.platform.configDirs, 0);
uint32_t baseLen = baseDir->length;
ffStrbufAppendS(baseDir, "appman/appman-config");
FF_STRBUF_AUTO_DESTROY packagesPath = ffStrbufCreate();
if (ffReadFileBuffer(baseDir->chars, &packagesPath))
ffStrbufTrimRightSpace(&packagesPath);
ffStrbufSubstrBefore(baseDir, baseLen);
return packagesPath.length > 0 ? getAMPackages(&packagesPath) : 0;
}
static int compareHash(const void* a, const void* b)
{
return memcmp(a, b, 32);
@@ -565,7 +586,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
}
if (!(options->disabled & FF_PACKAGES_FLAG_PALUDIS_BIT)) packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
if (!(options->disabled & FF_PACKAGES_FLAG_OPKG_BIT)) packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:", "opkg"); // openwrt
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->am = getAM(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->amSystem = getAMSystem(baseDir);
if (!(options->disabled & FF_PACKAGES_FLAG_SORCERY_BIT)) packageCounts->sorcery += getNumStrings(baseDir, "/var/state/sorcery/packages", ":installed:", "sorcery");
if (!(options->disabled & FF_PACKAGES_FLAG_GUIX_BIT))
{
@@ -678,4 +699,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
result->flatpakUser = getFlatpakPackages(&baseDir, "/.local/share");
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT))
result->amUser = getAMUser();
}
+1 -1
View File
@@ -27,7 +27,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
{
result->pkg = getNumElementsImpl(FASTFETCH_TARGET_DIR_ROOT
#if __OpenBSD
#if __OpenBSD__
"/var/db/pkg"
#else
"/usr/pkg/pkgdb"
+20 -16
View File
@@ -80,24 +80,28 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
{
ffStrbufInit(&device->interconnect);
char pathSysDeviceReal[PATH_MAX];
ssize_t pathLength = readlinkat(dfd, "device", pathSysDeviceReal, ARRAY_SIZE(pathSysDeviceReal) - 1);
if (pathLength > 0)
if (ffStrStartsWith(devName, "nvme"))
ffStrbufSetStatic(&device->interconnect, "NVMe");
else
{
pathSysDeviceReal[pathLength] = '\0';
if (strstr(pathSysDeviceReal, "/usb") != NULL)
ffStrbufSetS(&device->interconnect, "USB");
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
ffStrbufSetS(&device->interconnect, "NVMe");
else if (strstr(pathSysDeviceReal, "/ata") != NULL)
ffStrbufSetS(&device->interconnect, "ATA");
else if (strstr(pathSysDeviceReal, "/scsi") != NULL)
ffStrbufSetS(&device->interconnect, "SCSI");
else
char pathSysDeviceLink[64];
snprintf(pathSysDeviceLink, ARRAY_SIZE(pathSysDeviceLink), "/sys/block/%s/device", devName);
char pathSysDeviceReal[PATH_MAX];
if (realpath(pathSysDeviceLink, pathSysDeviceReal))
{
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
ffStrbufTrimRightSpace(&device->interconnect);
if (strstr(pathSysDeviceReal, "/usb") != NULL)
ffStrbufSetStatic(&device->interconnect, "USB");
else if (strstr(pathSysDeviceReal, "/ata") != NULL)
ffStrbufSetStatic(&device->interconnect, "ATA");
else if (strstr(pathSysDeviceReal, "/scsi") != NULL)
ffStrbufSetStatic(&device->interconnect, "SCSI");
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
ffStrbufSetStatic(&device->interconnect, "NVMe");
else
{
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
ffStrbufTrimRightSpace(&device->interconnect);
}
}
}
}
@@ -23,6 +23,7 @@ static inline const char* getVendorString(unsigned vendorId)
void FFPhysicalMemoryUpdateVendorString(FFPhysicalMemoryResult* device)
{
if (device->vendor.length == 0) return;
if (ffStrbufEqualS(&device->vendor, "Unknown"))
{
ffStrbufClear(&device->vendor);
@@ -191,6 +191,7 @@ const char* ffDetectPhysicalMemory(FFlist* result)
device->maxSpeed = data->Speed == 0xFFFF ? data->ExtendedSpeed : data->Speed;
ffStrbufSetStatic(&device->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&device->vendor);
FFPhysicalMemoryUpdateVendorString(device);
ffStrbufSetStatic(&device->serial, ffSmbiosLocateString(strings, data->SerialNumber));
+1
View File
@@ -8,6 +8,7 @@ typedef struct FFSoundDevice
{
FFstrbuf identifier;
FFstrbuf name;
FFstrbuf platformApi;
uint8_t volume; // 0-100%
bool main;
bool active;
+1
View File
@@ -73,6 +73,7 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
device->volume = FF_SOUND_VOLUME_UNKNOWN;
ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId);
ffStrbufInit(&device->name);
ffStrbufInitStatic(&device->platformApi, "Core Audio");
ffCfStrGetString(name, &device->name);
uint32_t muted;
+2 -1
View File
@@ -39,7 +39,8 @@ const char* ffDetectSound(FFlist* devices)
FFSoundDevice* device = ffListAdd(devices);
ffStrbufInitS(&device->identifier, path);
ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info);
ffStrbufTrimRightSpace(&device->name);
ffStrbufTrimRightSpace(&device->name);
ffStrbufInitStatic(&device->platformApi, "OSS");
device->volume = mutemask & SOUND_MASK_VOLUME
? 0
: ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2;
+14 -9
View File
@@ -13,6 +13,7 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo
FFSoundDevice* device = ffListAdd(userdata);
ffStrbufInitS(&device->identifier, i->name);
ffStrbufInitS(&device->platformApi, "PulseAudio");
ffStrbufTrimRightSpace(&device->identifier);
ffStrbufInitS(&device->name, i->description);
ffStrbufTrimRightSpace(&device->name);
@@ -22,20 +23,24 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo
device->main = false;
}
static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *userdata)
static void paServerInfoCallback(FF_MAYBE_UNUSED pa_context *c, const pa_server_info *i, void *userdata)
{
FF_UNUSED(c);
if(!i) return;
if(!i)
return;
FF_STRBUF_AUTO_DESTROY api = ffStrbufCreate();
const char* realServer = strstr(i->server_name, "(on ");
if (realServer)
{
ffStrbufSetS(&api, realServer + strlen("(on "));
ffStrbufTrimRight(&api, ')');
}
else
ffStrbufSetF(&api, "%s %s", i->server_name, i->server_version);
FF_LIST_FOR_EACH(FFSoundDevice, device, *(FFlist*)userdata)
{
if(ffStrbufEqualS(&device->identifier, i->default_sink_name))
{
device->main = true;
break;
}
device->main = ffStrbufEqualS(&device->identifier, i->default_sink_name);
ffStrbufSet(&device->platformApi, &api);
}
}
+1
View File
@@ -65,6 +65,7 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
device->volume = FF_SOUND_VOLUME_UNKNOWN;
ffStrbufInitWS(&device->identifier, immDeviceId);
ffStrbufInit(&device->name);
ffStrbufInitStatic(&device->platformApi, "Core Audio APIs");
{
PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName;
+31
View File
@@ -48,6 +48,35 @@ static void detectAlacritty(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
static void detectGhostty(FFTerminalFontResult* terminalFont)
{
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
FFpropquery fontQueryToml[] = {
{"font-family =", &fontName},
{"font-size =", &fontSize},
};
if (
#if __APPLE__
!ffParsePropFileConfigValues("com.mitchellh.ghostty/config", 2, fontQueryToml) &&
#endif
!ffParsePropFileConfigValues("ghostty/config", 2, fontQueryToml)
) {
ffStrbufAppendS(&terminalFont->error, "Couldn't find file `ghostty/config`");
return;
}
if(fontName.length == 0)
ffStrbufAppendS(&fontName, "JetBrains Mono");
if(fontSize.length == 0)
ffStrbufAppendS(&fontSize, "13");
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont)
{
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
@@ -230,6 +259,8 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
detectTabby(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "contour"))
detectContour(&terminal->exe, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "ghostty"))
detectGhostty(terminalFont);
#ifndef _WIN32
else if(ffStrbufStartsWithIgnCaseS(&terminal->exe, "/dev/pts/"))
+61 -36
View File
@@ -15,41 +15,18 @@
#define _PATH_LOCALBASE "/usr/local"
#elif __NetBSD__
#define _PATH_LOCALBASE "/usr/pkg"
#endif
#elif _WIN32
#ifdef _WIN32
#include "util/windows/version.h"
#include <windows.h>
#include "util/mallocHelper.h"
#include <winver.h>
static bool getFileVersion(const char* exePath, FFstrbuf* version)
static bool getFileVersion(const FFstrbuf* exePath, FFstrbuf* version)
{
DWORD handle;
DWORD size = GetFileVersionInfoSizeA(exePath, &handle);
if(size > 0)
{
FF_AUTO_FREE void* versionData = malloc(size);
if(GetFileVersionInfoA(exePath, handle, size, versionData))
{
VS_FIXEDFILEINFO* verInfo;
UINT len;
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
{
ffStrbufAppendF(version, "%u.%u.%u.%u",
(unsigned)(( verInfo->dwFileVersionMS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwFileVersionMS >> 0 ) & 0xffff),
(unsigned)(( verInfo->dwFileVersionLS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwFileVersionLS >> 0 ) & 0xffff)
);
return true;
}
}
}
return false;
wchar_t exePathW[PATH_MAX];
int len = MultiByteToWideChar(CP_UTF8, 0, exePath->chars, (int)exePath->length, exePathW, ARRAY_SIZE(exePathW));
if (len <= 0) return false;
return ffGetFileVersion(exePathW, version);
}
#endif
static bool getExeVersionRaw(FFstrbuf* exe, FFstrbuf* version)
@@ -109,8 +86,17 @@ static bool getShellVersionFish(FFstrbuf* exe, FFstrbuf* version)
static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
{
// Requires manually setting $POWERSHELL_VERSION
// $env:POWERSHELL_VERSION = $PSVersionTable.PSVersion.ToString(); fastfetch.exe
const char* env = getenv("POWERSHELL_VERSION");
if (env)
{
ffStrbufSetS(version, env);
return true;
}
#ifdef _WIN32
if(getFileVersion(exe->chars, version))
if(getFileVersion(exe, version))
{
ffStrbufSubstrBeforeLastC(version, '.');
return true;
@@ -249,6 +235,13 @@ static bool getShellVersionZsh(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* versi
#ifdef _WIN32
static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
{
const char* env = getenv("POWERSHELL_VERSION");
if (env)
{
ffStrbufSetS(version, env);
return true;
}
return ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-NoLogo",
@@ -296,7 +289,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath,
if(ffStrEqualsIgnCase(exeName, "powershell") || ffStrEqualsIgnCase(exeName, "powershell_ise"))
return getShellVersionWinPowerShell(exe, version);
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
#endif
return false;
@@ -605,6 +598,38 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
}
}
}
#elif __APPLE__
if (ffStrbufEndsWithS(exe, "/kitty.app/Contents/MacOS/kitty"))
{
ffStrbufSet(version, exe);
ffStrbufSubstrBeforeLastC(version, '/');
ffStrbufSubstrBeforeLastC(version, '/');
ffStrbufAppendS(version, "/Info.plist");
char buf[4096];
ssize_t size = ffReadFileData(version->chars, ARRAY_SIZE(buf) - 1, buf);
if (size > 0)
{
buf[size] = '\0';
const char* p = strstr(buf, "<key>CFBundleShortVersionString</key>");
if (p)
{
p += strlen("<key>CFBundleShortVersionString</key>");
p = strchr(p, '>');
if (p)
{
p++;
const char* end = strchr(p, '<');
if (end)
{
ffStrbufSetNS(version, (uint32_t) (end - p), p);
return true;
}
}
}
}
ffStrbufClear(version);
}
#endif
char versionHex[64];
@@ -690,7 +715,7 @@ static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
return true;
}
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
}
static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
@@ -700,7 +725,7 @@ static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
if(version->length)
return true;
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
}
#endif
@@ -859,7 +884,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
#ifdef _WIN32
return getFileVersion(exe->chars, version);
return getFileVersion(exe, version);
#else
@@ -56,7 +56,10 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "fastfetch") || //994
ffStrbufEqualS(&result->processName, "flashfetch") ||
ffStrbufContainS(&result->processName, "debug") ||
ffStrbufContainS(&result->processName, "not-found") ||
ffStrbufContainS(&result->processName, "command-not-") ||
#ifdef __ANDROID__
ffStrbufEqualS(&result->processName, "proot") ||
#endif
ffStrbufEndsWithS(&result->processName, ".sh")
)
{
@@ -105,6 +108,9 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "login") ||
ffStrbufEqualS(&result->processName, "clifm") || // https://github.com/leo-arch/clifm/issues/289
ffStrbufEqualS(&result->processName, "chezmoi") || // #762
#ifdef __ANDROID__
ffStrbufEqualS(&result->processName, "proot") ||
#endif
#ifdef __linux__
ffStrbufStartsWithS(&result->processName, "flatpak-") || // #707
#endif
@@ -307,11 +313,11 @@ static void setShellInfoDetails(FFShellResult* result)
static void setTerminalInfoDetails(FFTerminalResult* result)
{
if(ffStrbufStartsWithC(&result->processName, '.') && ffStrbufEndsWithS(&result->processName, "-wrapped"))
if(ffStrbufStartsWithC(&result->processName, '.') && ffStrbufContainS(&result->processName, "-wrap"))
{
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
// We use processName when detecting version and font, overriding it for simplification
ffStrbufSubstrBefore(&result->processName, result->processName.length - (uint32_t) strlen("-wrapped"));
ffStrbufSubstrBeforeLastC(&result->processName, '-');
ffStrbufSubstrAfter(&result->processName, 0);
}
@@ -5,39 +5,13 @@
#include "util/mallocHelper.h"
#include "util/windows/registry.h"
#include "util/windows/unicode.h"
#include "util/windows/version.h"
#include "util/stringUtils.h"
#include <windows.h>
#include <wchar.h>
#include <tlhelp32.h>
static bool getProductVersion(const wchar_t* filePath, FFstrbuf* version)
{
DWORD handle;
DWORD size = GetFileVersionInfoSizeW(filePath, &handle);
if(size > 0)
{
FF_AUTO_FREE void* versionData = malloc(size);
if(GetFileVersionInfoW(filePath, handle, size, versionData))
{
VS_FIXEDFILEINFO* verInfo;
UINT len;
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
{
ffStrbufAppendF(version, "%u.%u.%u.%u",
(unsigned)(( verInfo->dwProductVersionMS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionMS >> 0 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 0 ) & 0xffff)
);
return true;
}
}
}
return false;
}
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, const FFstrbuf* exePath, FFstrbuf* version);
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
@@ -113,7 +87,7 @@ static void setShellInfoDetails(FFShellResult* result)
if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0)
{
ffStrbufAppendS(&result->prettyName, " (with Clink ");
getProductVersion(module.szExePath, &result->prettyName);
ffGetFileVersion(module.szExePath, &result->prettyName);
ffStrbufAppendC(&result->prettyName, ')');
break;
}
@@ -2,6 +2,7 @@
#include "common/io/io.h"
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef __sun
@@ -11,7 +12,11 @@
bool ffDetectTerminalSize(FFTerminalSizeResult* result)
{
struct winsize winsize = {};
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
static int ttyfd = STDOUT_FILENO;
if (!isatty(ttyfd))
ttyfd = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
ioctl(ttyfd, TIOCGWINSZ, &winsize);
if (winsize.ws_row == 0 || winsize.ws_col == 0)
ffGetTerminalResponse("\e[18t", 2, "\e[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
+2
View File
@@ -40,6 +40,8 @@
#define FF_SYSNAME "SunOS"
#elif defined(__OpenBSD__)
#define FF_SYSNAME "OpenBSD"
#elif defined(__NetBSD__)
#define FF_SYSNAME "NetBSD"
#else
#define FF_SYSNAME "unknown"
#endif
+7 -7
View File
@@ -39,13 +39,13 @@ static void applyDriverName(VkPhysicalDeviceDriverPropertiesKHR* properties, FFs
static const char* detectVulkan(FFVulkanResult* result)
{
FF_LIBRARY_LOAD(vulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed",
#ifdef __APPLE__
"libMoltenVK"FF_LIBRARY_EXTENSION, -1
#elif defined(_WIN32)
"vulkan-1"FF_LIBRARY_EXTENSION, -1
FF_LIBRARY_LOAD(vulkan, "dlopen libvulkan" FF_LIBRARY_EXTENSION " failed",
#if __APPLE__
"libMoltenVK" FF_LIBRARY_EXTENSION, -1
#elif _WIN32
"vulkan-1" FF_LIBRARY_EXTENSION, -1
#else
"libvulkan"FF_LIBRARY_EXTENSION, 2
"libvulkan" FF_LIBRARY_EXTENSION, 2
#endif
)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr)
@@ -218,7 +218,7 @@ static const char* detectVulkan(FFVulkanResult* result)
ffStrbufInitS(&gpu->name, physicalDeviceProperties.properties.deviceName);
gpu->type = physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID));
ffStrbufInitS(&gpu->vendor, ffGPUGetVendorString(physicalDeviceProperties.properties.vendorID));
ffStrbufInitS(&gpu->driver, driverProperties.driverInfo);
VkPhysicalDeviceMemoryProperties memoryProperties = {};
+1
View File
@@ -3,3 +3,4 @@
#include "fastfetch.h"
const char* ffDetectWMPlugin(FFstrbuf* pluginName);
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FFWMOptions* options);
@@ -5,6 +5,7 @@
#include "util/stringUtils.h"
#include <ctype.h>
#import <Foundation/Foundation.h>
const char* ffDetectWMPlugin(FFstrbuf* pluginName)
{
@@ -38,3 +39,19 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName)
return NULL;
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "WindowServer"))
{
NSError* error;
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"file:///System/Library/CoreServices/WindowManager.app/Contents/version.plist"]
error:&error];
ffStrbufInitS(result, ((NSString*) dict[@"CFBundleVersion"]).UTF8String);
}
return NULL;
}
+113
View File
@@ -0,0 +1,113 @@
#include "wm.h"
#include "common/processing.h"
#include "common/io/io.h"
#include "detection/displayserver/displayserver.h"
#include "util/binary.h"
#include "util/path.h"
#include "util/stringUtils.h"
const char* ffDetectWMPlugin(FF_MAYBE_UNUSED FFstrbuf* pluginName)
{
return "Not supported on this platform";
}
static bool extractHyprlandVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (line[0] != 'v') return true;
int count = 0;
sscanf(line + 1, "%*d.%*d.%*d%n", &count);
if (count == 0) return true;
ffStrbufSetNS((FFstrbuf*) userdata, len - 1, line + 1);
return false;
}
static const char* getHyprland(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("Hyprland", &path);
if (error) return "Failed to find Hyprland executable path";
if (ffBinaryExtractStrings(path.chars, extractHyprlandVersion, result, (uint32_t) strlen("v0.0.0")) == NULL)
return NULL;
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // Hyprland 0.46.2 built from branch v0.46.2-b at... long and multi line
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufSubstrBeforeFirstC(result, ' ');
return NULL;
}
return "Failed to run command `Hyprland --version`";
}
static bool extractSwayVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (!ffStrStartsWith(line, "sway version ")) return true;
ffStrbufSetNS((FFstrbuf*) userdata, len - (uint32_t) strlen("sway version "), line + strlen("sway version "));
return false;
}
static const char* getSway(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("sway", &path);
if (error) return "Failed to find sway executable path";
if (ffBinaryExtractStrings(path.chars, extractSwayVersion, result, (uint32_t) strlen("v0.0.0")) == NULL)
{
ffStrbufTrimRightSpace(result);
return NULL;
}
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // sway version 1.10
ffStrbufSubstrAfterLastC(result, ' ');
ffStrbufTrimRightSpace(result);
return NULL;
}
return "Failed to run command `sway --version`";
}
static const char* getWslg(FFstrbuf* result)
{
if (!ffAppendFileBuffer("/mnt/wslg/versions.txt", result))
return "Failed to read /mnt/wslg/versions.txt";
if (!ffStrbufStartsWithS(result, "WSLg "))
return "Failed to find WSLg version";
ffStrbufSubstrBeforeFirstC(result, '\n');
ffStrbufSubstrBeforeFirstC(result, '+');
ffStrbufSubstrAfterFirstC(result, ':');
ffStrbufTrimLeft(result, ' ');
return NULL;
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "Hyprland"))
return getHyprland(result);
if (ffStrbufEqualS(wmName, "sway"))
return getSway(result);
if (ffStrbufEqualS(wmName, "WSLg"))
return getWslg(result);
return "Unsupported WM";
}
+5
View File
@@ -4,3 +4,8 @@ const char* ffDetectWMPlugin(FF_MAYBE_UNUSED FFstrbuf* pluginName)
{
return "Not supported on this platform";
}
const char* ffDetectWMVersion(FF_MAYBE_UNUSED const FFstrbuf* wmName, FF_MAYBE_UNUSED FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
return "Not supported on this platform";
}
+22
View File
@@ -3,6 +3,7 @@ extern "C"
#include "wm.h"
#include "common/io/io.h"
#include "detection/terminalshell/terminalshell.h"
#include "util/windows/version.h"
}
#include "util/windows/com.hpp"
@@ -64,3 +65,24 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName)
}
return NULL;
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
if (ffStrbufEqualS(wmName, "dwm.exe"))
{
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(FOLDERID_System, KF_FLAG_DEFAULT, NULL, &pPath)))
{
wchar_t fullPath[MAX_PATH];
wcscpy(fullPath, pPath);
wcscat(fullPath, L"\\dwm.exe");
ffGetFileVersion(fullPath, result);
}
CoTaskMemFree(pPath);
return NULL;
}
return "Not supported on this platform";
}
+11
View File
@@ -0,0 +1,11 @@
.7J~
~G@&#5^ .^.
:5&&&&##B?. !B&G7
7B##&&B##BBP~ ^P&@&##P~
$2^YGP5PBPPP5YY55?: .7GGGB#BPPP7.
.?PPPPPPPPPP55YYY5Y!.^YPPPPPP5YYY5J~
!PPPPPPPPPPPPPP5YYYY5JY5PPPPPPP55YY55?:
^YPPPPPPPPPPPPPPPPYYYYYYYYY5PPPPPPP5YYY5Y!.
.7PPPPPPPPPPPPPPPPPP5YYYYYYYYY55PPPPP5YYYYY5J~
!5GPPPPPPPPPPPPPPPPPPPP55555555YY5PPPPPP5555555?:
7777777777777777777777777!!!!!!!!!77777777!!!!!7!:
+20
View File
@@ -0,0 +1,20 @@
`.:/ossyyyysso/:.
`.:yyyyyyyyyyyyyyyyyy:.`
.:yyyyyyyyyyyyyyyyyyyyyyyy:.
.:yyyyyyyyyyyyyyyyyyyyyyyyyyyy:.
-yyyyyyyyyyyyyy${c2}+hNMMMNh+${c1}yyyyyyyyy-
:yy${c2}mNy+${c1}yyyyyyyy${c2}+Nmso++smMdhyysoo+${c1}yy:
-yy${c2}+MMMmmy${c1}yyyyyy${c2}hh${c1}yyyyyyyyyyyyyyyyyyy-
.yyyy${c2}NMN${c1}yy${c2}shhs${c1}yyy${c2}+o${c1}yyyyyyyyyyyyyyyyyyyy.
:yyyy${c2}oNM+${c1}yyyy${c2}+sso${c1}yyyyyyy${c2}ss${c1}yyyyyyyyyyyyy:
:yyyyy${c2}+dNs${c1}yyyyyyy${c2}++${c1}yyyyy${c2}oN+${c1}yyyyyyyyyyyy:
:yyyyy${c2}oMMmhysso${c1}yyyyyyyyyy${c2}mN+${c1}yyyyyyyyyyy:
:yyyyyy${c2}hMm${c1}yyyyy${c2}+++${c1}yyyyyyy${c2}+MN${c1}yyyyyyyyyyy:
.yyyyyyy${c2}ohmy+${c1}yyyyyyyyyyyyy${c2}NMh${c1}yyyyyyyyyy.
-yyyyyyyyyy${c2}++${c1}yyyyyyyyyyyy${c2}MMh${c1}yyyyyyyyy-
:yyyyyyyyyyyyyyyyyyyyy${c2}+mMN+${c1}yyyyyyyy:
-yyyyyyyyyyyyyyyyy${c2}+sdMMd+${c1}yyyyyyyy-
.:yyyyyyyyy${c2}hmdmmNMNdy+${c1}yyyyyyyy:.
.:yyyyyyy${c2}my${c1}yyyyyyyyyyyyyyy:.
`.:yyyy${c2}s${c1}yyyyyyyyyyyyy:.`
`.:/oosyyyysso/:.`
+12
View File
@@ -0,0 +1,12 @@
___╓╓___
_▄▄▓▓▀▀╜╜╨▀▓▓▓╗_
╓▓▓▀² `╙▓▓╖
╣▓▀ _▄▓▓▓▓▓▓W_ ╙▓▓
╣▓╜ ,▓▓▓▓▓▓▓▓▓▓▓▓_ ²▓▓
╒▓▌ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║▓m
╞▓▓ í▓▓▓▓▓▓▓▓▓▓▓▓▓▓h ╞▓╡
²▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║▓h
║▓▄ ╙▓▓▓▓▓▓▓▓▓▓╜ ƒ▓▓
╙▓▓_ ⁿ╙╨╝╝╝╜² _╢▓╜
╙▓▓╗__ _╗▓▓╜
`╙╝▓▓▓▓▓▓▓▓╝╙
+12
View File
@@ -0,0 +1,12 @@
${c1} .;:;,. .:
${c1} 'coooooooo:oo.';.
${c1} ,oooooooooooooooo ;
${c1} clllcccllloooooooo;c:'o
${c1}.${c4};${c3}';:::::::::${c1}cclooooooo'
${c4}''',${c3}::::::::::::::${c1}ccclc.
${c4}.'''${c3};::::::::::${c2}l${c3}:::::::
${c4} ''''${c3},:::::::::${c2}kd${c3}.
${c4} .'''''${c3},;::${c2}ck:${c2}oW${c3};
${c4} ''''''''${c2}kXOM.
${c4} .,,:${c2}dXMK
${c4} ${c2}:k
+20
View File
@@ -0,0 +1,20 @@
WK0OO0X
WKOxk0XWNXkxN
WXOxk0N kk
WKkxOXW NxO
NX0ddk00OOOOkkkkkkkkk0
WKkxO0dOXXNNNNWWW WXKK
NxkN kxW XOxxdN
KoX WkxX WkxK Xd0
WxkW XkkX kkW NkxX
W0dK XxOWkkW XxkN
NkxX XoKWkxK Kd0
XkkN WOdN NkxX NxO
OxNKxOW XdO kk
kdk0W XoK WXkxN
WNNXKXXXXKKKK000OOdxkk0X
KdOO000KKKKXXXXX0xx0W
XoK N0kx0N
Nd0 NKOxOKW
Nkk0K0kxOKN
WXXXN
+51 -1
View File
@@ -1912,6 +1912,15 @@ static const FFlogo G[] = {
.colorKeys = FF_COLOR_FG_MAGENTA,
.colorTitle = FF_COLOR_FG_WHITE,
},
// GoralixOS
{
.names = {"GoralixOS"},
.lines = FASTFETCH_DATATEXT_LOGO_GORALIXOS,
.colors = {
FF_COLOR_FG_WHITE,
FF_COLOR_FG_LIGHT_BLACK,
},
},
// GrapheneOS
{
.names = {"GrapheneOS"},
@@ -2573,6 +2582,15 @@ static const FFlogo L[] = {
.colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_RED,
},
// Lubuntu
{
.names = {"lubuntu"},
.lines = FASTFETCH_DATATEXT_LOGO_LUBUNTU,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
},
// Lunar
{
.names = {"Lunar"},
@@ -3086,6 +3104,15 @@ static const FFlogo N[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_WHITE,
},
// NurOS
{
.names = {"NurOS"},
.lines = FASTFETCH_DATATEXT_LOGO_NUROS,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
},
// Nurunner
{
.names = {"Nurunner"},
@@ -3962,6 +3989,19 @@ static const FFlogo R[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// RhinoLinux
{
.names = {"Rhino Linux"},
.lines = FASTFETCH_DATATEXT_LOGO_RHINO,
.colors = {
FF_COLOR_FG_MAGENTA,
FF_COLOR_FG_LIGHT_BLUE,
FF_COLOR_FG_LIGHT_MAGENTA,
FF_COLOR_FG_MAGENTA,
},
.colorKeys = FF_COLOR_FG_MAGENTA,
.colorTitle = FF_COLOR_FG_MAGENTA,
},
// LAST
{},
};
@@ -4202,6 +4242,15 @@ static const FFlogo S[] = {
FF_COLOR_FG_WHITE,
},
},
// SnigdhaOS
{
.names = {"SnigdhaOS", "Snigdha"},
.lines = FASTFETCH_DATATEXT_LOGO_SMARTOS,
.colors = {
FF_COLOR_FG_CYAN,
FF_COLOR_FG_WHITE,
},
},
// Soda
{
.names = {"Soda"},
@@ -4973,9 +5022,10 @@ static const FFlogo X[] = {
.names = {"Xray_OS"},
.lines = FASTFETCH_DATATEXT_LOGO_XRAY_OS,
.colors = {
FF_COLOR_FG_256 "16",
FF_COLOR_FG_256 "15",
FF_COLOR_FG_256 "14",
FF_COLOR_FG_256 "16",
FF_COLOR_FG_256 "24",
}
},
// LAST
+125
View File
@@ -1,6 +1,7 @@
#include "image.h"
#include "common/io/io.h"
#include "common/printing.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include "util/base64.h"
#include "detection/terminalsize/terminalsize.h"
@@ -138,6 +139,127 @@ static bool printImageIterm(bool printError)
return true;
}
static bool printImageKittyIcat(bool printError)
{
const FFOptionsLogo* options = &instance.config.logo;
if (!ffPathExists(options->source.chars, FF_PATHTYPE_FILE))
{
if (printError)
fputs("Logo (kitty-icat): Failed to load image file\n", stderr);
return false;
}
fflush(stdout);
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if (options->position == FF_LOGO_POSITION_LEFT)
{
ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH",
(unsigned) options->paddingTop + 1,
(unsigned) options->paddingLeft + 1
);
}
else if (options->position == FF_LOGO_POSITION_TOP)
{
if (!options->width)
{
ffStrbufAppendNC(&buf, options->paddingTop, '\n');
ffStrbufAppendNC(&buf, options->paddingLeft, ' ');
}
else
{
if (printError)
fputs("Logo (kitty-icat): position top is not supported when logo width is set\n", stderr);
return false;
}
}
else if (options->position == FF_LOGO_POSITION_RIGHT)
{
if (printError)
fputs("Logo (kitty-icat): position right is not supported\n", stderr);
return false;
}
uint32_t prevLength = buf.length;
const char* error = NULL;
if (options->width)
{
char place[64];
snprintf(place,
ARRAY_SIZE(place),
"--place=%ux%u@%ux%u",
options->width,
options->height == 0 ? 9999 : options->height,
options->paddingLeft + 1,
options->paddingTop + 1);
error = ffProcessAppendStdOut(&buf, (char* []) {
"kitten",
"icat",
"-n",
"--align=center",
place,
"--scale-up",
options->source.chars,
NULL,
});
}
else
{
error = ffProcessAppendStdOut(&buf, (char* []) {
"kitten",
"icat",
"-n",
"--align=left",
options->source.chars,
NULL,
});
}
if (error)
{
if (printError)
fprintf(stderr, "Logo (kitty-icat): running `kitten icat` failed %s\n", error);
return false;
}
if (buf.length == prevLength)
{
if (printError)
fputs("Logo (kitty-icat): `kitten icat` returned empty output\n", stderr);
return false;
}
ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf);
if (options->position == FF_LOGO_POSITION_LEFT || options->position == FF_LOGO_POSITION_RIGHT)
{
uint16_t X = 0, Y = 0;
const char* error = ffGetTerminalResponse("\e[6n", 2, "%*[^0-9]%hu;%huR", &Y, &X);
if (error)
{
fprintf(stderr, "\nLogo (kitty-icat): fail to query cursor position: %s\n", error);
return true; // We already printed image logo, don't print ascii logo then
}
if (X < options->paddingLeft + options->width)
X = (uint16_t) (options->paddingLeft + options->width);
if (options->position == FF_LOGO_POSITION_LEFT)
instance.state.logoWidth = X + options->paddingRight - 1;
instance.state.logoHeight = Y;
fputs("\e[H", stdout);
}
else if (options->position == FF_LOGO_POSITION_TOP)
{
instance.state.logoWidth = instance.state.logoHeight = 0;
ffPrintCharTimes('\n', options->paddingRight);
}
return true;
}
static bool printImageKittyDirect(bool printError)
{
const FFOptionsLogo* options = &instance.config.logo;
@@ -957,6 +1079,9 @@ bool ffLogoPrintImageIfExists(FFLogoType type, bool printError)
if(type == FF_LOGO_TYPE_IMAGE_KITTY_DIRECT)
return printImageKittyDirect(printError);
if(type == FF_LOGO_TYPE_IMAGE_KITTY_ICAT)
return printImageKittyIcat(printError);
#if !defined(FF_HAVE_CHAFA)
if(type == FF_LOGO_TYPE_IMAGE_CHAFA)
{
+2 -1
View File
@@ -605,7 +605,8 @@ void ffLogoPrint(void)
ffStrbufIgnCaseEqualS(&terminal->processName, "kitty") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "konsole") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "wezterm") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst");
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "ghostty");
//Try to load the logo as an image. If it succeeds, print it and return.
if(logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false))
+3 -3
View File
@@ -59,7 +59,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de
void ffPrintBluetooth(FFBluetoothOptions* options)
{
FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof (FFBluetoothResult));
const char* error = ffDetectBluetooth(&devices);
const char* error = ffDetectBluetooth(options, &devices);
if(error)
{
@@ -155,11 +155,11 @@ void ffGenerateBluetoothJsonConfig(FFBluetoothOptions* options, yyjson_mut_doc*
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
}
void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
void ffGenerateBluetoothJsonResult(FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothResult));
const char* error = ffDetectBluetooth(&results);
const char* error = ffDetectBluetooth(options, &results);
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
+1 -6
View File
@@ -69,12 +69,7 @@ void ffPrintCPU(FFCPUOptions* options)
if(coreTypes.length > 0)
ffStrbufAppendF(&str, " (%s)", coreTypes.chars);
else if(cpu.coresOnline > 1)
{
if(cpu.packages > 1)
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline / 2);
else
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
}
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
uint32_t freq = cpu.frequencyMax;
if(freq == 0)
+14 -4
View File
@@ -99,6 +99,9 @@ void ffPrintMedia(FFMediaOptions* options)
FF_FORMAT_ARG(media->artist, "artist"),
FF_FORMAT_ARG(media->album, "album"),
FF_FORMAT_ARG(media->status, "status"),
FF_FORMAT_ARG(media->player, "player-name"),
FF_FORMAT_ARG(media->playerId, "player-id"),
FF_FORMAT_ARG(media->url, "url"),
}));
}
}
@@ -149,10 +152,17 @@ void ffGenerateMediaJsonResult(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_m
}
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "song", &media->song);
yyjson_mut_obj_add_strbuf(doc, obj, "artist", &media->artist);
yyjson_mut_obj_add_strbuf(doc, obj, "album", &media->album);
yyjson_mut_obj_add_strbuf(doc, obj, "status", &media->status);
yyjson_mut_val* song = yyjson_mut_obj_add_obj(doc, obj, "song");
yyjson_mut_obj_add_strbuf(doc, song, "name", &media->song);
yyjson_mut_obj_add_strbuf(doc, song, "artist", &media->artist);
yyjson_mut_obj_add_strbuf(doc, song, "album", &media->album);
yyjson_mut_obj_add_strbuf(doc, song, "status", &media->status);
yyjson_mut_val* player = yyjson_mut_obj_add_obj(doc, obj, "player");
yyjson_mut_obj_add_strbuf(doc, player, "name", &media->player);
yyjson_mut_obj_add_strbuf(doc, player, "id", &media->playerId);
yyjson_mut_obj_add_strbuf(doc, player, "url", &media->url);
}
static FFModuleBaseInfo ffModuleInfo = {
+10 -35
View File
@@ -51,38 +51,6 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
ffStrbufAppend(result, &os->variantID);
ffStrbufAppendC(result, ')');
}
//Append architecture if it is missing
if(!ffStrbufContainIgnCase(result, &instance.state.platform.sysinfo.architecture))
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &instance.state.platform.sysinfo.architecture);
}
}
static void buildOutputNixOS(const FFOSResult* os, FFstrbuf* result)
{
ffStrbufAppendS(result, "NixOS");
if(os->buildID.length > 0)
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &os->buildID);
}
if(os->codename.length > 0)
{
ffStrbufAppendS(result, " (");
ffStrbufAppendC(result, (char) toupper(os->codename.chars[0]));
ffStrbufAppendS(result, os->codename.chars + 1);
ffStrbufAppendC(result, ')');
}
if(instance.state.platform.sysinfo.architecture.length > 0)
{
ffStrbufAppendC(result, ' ');
ffStrbufAppend(result, &instance.state.platform.sysinfo.architecture);
}
}
void ffPrintOS(FFOSOptions* options)
@@ -99,11 +67,18 @@ void ffPrintOS(FFOSOptions* options)
{
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
if(ffStrbufIgnCaseCompS(&os->id, "nixos") == 0)
buildOutputNixOS(os, &result);
if(os->prettyName.length > 0)
ffStrbufAppend(&result, &os->prettyName);
else
buildOutputDefault(os, &result);
//Append architecture if it is missing
if(!ffStrbufContainIgnCase(&result, &instance.state.platform.sysinfo.architecture))
{
ffStrbufAppendC(&result, ' ');
ffStrbufAppend(&result, &instance.state.platform.sysinfo.architecture);
}
ffPrintLogoAndKey(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufPutTo(&result, stdout);
}
@@ -195,7 +170,7 @@ static FFModuleBaseInfo ffModuleInfo = {
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
{"Name of the kernel", "sysname"},
{"Name of the OS", "name"},
{"Pretty name of the OS", "pretty-name"},
{"Pretty name of the OS, if available", "pretty-name"},
{"ID of the OS", "id"},
{"ID like of the OS", "id-like"},
{"Variant of the OS", "variant"},
+8 -4
View File
@@ -62,7 +62,8 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE(paludis)
FF_PRINT_PACKAGE(winget)
FF_PRINT_PACKAGE(opkg)
FF_PRINT_PACKAGE(am)
FF_PRINT_PACKAGE_NAME(amSystem, "am")
FF_PRINT_PACKAGE_NAME(amUser, "appman")
FF_PRINT_PACKAGE(sorcery)
FF_PRINT_PACKAGE(lpkg)
FF_PRINT_PACKAGE(lpkgbuild)
@@ -108,7 +109,7 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_FORMAT_ARG(counts.paludis, "paludis"),
FF_FORMAT_ARG(counts.winget, "winget"),
FF_FORMAT_ARG(counts.opkg, "opkg"),
FF_FORMAT_ARG(counts.am, "am"),
FF_FORMAT_ARG(counts.amSystem, "am-system"),
FF_FORMAT_ARG(counts.sorcery, "sorcery"),
FF_FORMAT_ARG(counts.lpkg, "lpkg"),
FF_FORMAT_ARG(counts.lpkgbuild, "lpkgbuild"),
@@ -119,6 +120,7 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_FORMAT_ARG(counts.pacstall, "pacstall"),
FF_FORMAT_ARG(counts.mport, "mport"),
FF_FORMAT_ARG(counts.qi, "qi"),
FF_FORMAT_ARG(counts.amUser, "am-user"),
FF_FORMAT_ARG(nixAll, "nix-all"),
FF_FORMAT_ARG(flatpakAll, "flatpak-all"),
FF_FORMAT_ARG(brewAll, "brew-all"),
@@ -400,7 +402,8 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
#define FF_APPEND_PACKAGE_COUNT(name) yyjson_mut_obj_add_uint(doc, obj, #name, counts.name);
FF_APPEND_PACKAGE_COUNT(all)
FF_APPEND_PACKAGE_COUNT(am)
FF_APPEND_PACKAGE_COUNT(amSystem)
FF_APPEND_PACKAGE_COUNT(amUser)
FF_APPEND_PACKAGE_COUNT(apk)
FF_APPEND_PACKAGE_COUNT(brew)
FF_APPEND_PACKAGE_COUNT(brewCask)
@@ -469,7 +472,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Number of paludis packages", "paludis"},
{"Number of winget packages", "winget"},
{"Number of opkg packages", "opkg"},
{"Number of am packages", "am"},
{"Number of am-system packages", "am-system"},
{"Number of sorcery packages", "sorcery"},
{"Number of lpkg packages", "lpkg"},
{"Number of lpkgbuild packages", "lpkgbuild"},
@@ -480,6 +483,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Number of pacstall packages", "pacstall"},
{"Number of mport packages", "mport"},
{"Number of qi packages", "qi"},
{"Number of am-user (aka appman) packages", "am-user"},
{"Total number of all nix packages", "nix-all"},
{"Total number of all flatpak app packages", "flatpak-all"},
{"Total number of all brew packages", "brew-all"},
+1 -12
View File
@@ -118,18 +118,7 @@ void ffGeneratePlayerJsonConfig(FFPlayerOptions* options, yyjson_mut_doc* doc, y
void ffGeneratePlayerJsonResult(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
const FFMediaResult* media = ffDetectMedia();
if(media->error.length > 0)
{
yyjson_mut_obj_add_strbuf(doc, module, "error", &media->error);
return;
}
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "player", &media->player);
yyjson_mut_obj_add_strbuf(doc, obj, "playerId", &media->playerId);
yyjson_mut_obj_add_strbuf(doc, obj, "url", &media->url);
yyjson_mut_obj_add_str(doc, module, "error", "Player module is an alias of Media module");
}
static FFModuleBaseInfo ffModuleInfo = {
+3
View File
@@ -58,6 +58,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui
FF_FORMAT_ARG(percentageNum, "volume-percentage"),
FF_FORMAT_ARG(device->identifier, "identifier"),
FF_FORMAT_ARG(percentageBar, "volume-percentage-bar"),
FF_FORMAT_ARG(device->platformApi, "platform-api"),
}));
}
}
@@ -218,6 +219,7 @@ void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_m
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier);
yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &item->platformApi);
}
FF_LIST_FOR_EACH(FFSoundDevice, device, result)
@@ -241,6 +243,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"Volume (in percentage num)", "volume-percentage"},
{"Identifier", "identifier"},
{"Volume (in percentage bar)", "volume-percentage-bar"},
{"Platform API used", "platform-api"},
}))
};
+17
View File
@@ -19,12 +19,22 @@ void ffPrintWM(FFWMOptions* options)
if(options->detectPlugin)
ffDetectWMPlugin(&pluginName);
FF_STRBUF_AUTO_DESTROY version = ffStrbufCreate();
if (instance.config.general.detectVersion)
ffDetectWMVersion(&result->wmProcessName, &version, options);
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&result->wmPrettyName, stdout);
if(version.length > 0)
{
putchar(' ');
ffStrbufWriteTo(&version, stdout);
}
if(result->wmProtocolName.length > 0)
{
fputs(" (", stdout);
@@ -48,6 +58,7 @@ void ffPrintWM(FFWMOptions* options)
FF_FORMAT_ARG(result->wmPrettyName, "pretty-name"),
FF_FORMAT_ARG(result->wmProtocolName, "protocol-name"),
FF_FORMAT_ARG(pluginName, "plugin-name"),
FF_FORMAT_ARG(version, "version"),
}));
}
}
@@ -116,11 +127,16 @@ void ffGenerateWMJsonResult(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc
if(options->detectPlugin)
ffDetectWMPlugin(&pluginName);
FF_STRBUF_AUTO_DESTROY version = ffStrbufCreate();
if (instance.config.general.detectVersion)
ffDetectWMVersion(&result->wmProcessName, &version, options);
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->wmProcessName);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->wmPrettyName);
yyjson_mut_obj_add_strbuf(doc, obj, "protocolName", &result->wmProtocolName);
yyjson_mut_obj_add_strbuf(doc, obj, "pluginName", &pluginName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &version);
}
static FFModuleBaseInfo ffModuleInfo = {
@@ -136,6 +152,7 @@ static FFModuleBaseInfo ffModuleInfo = {
{"WM pretty name", "pretty-name"},
{"WM protocol name", "protocol-name"},
{"WM plugin name", "plugin-name"},
{"WM version", "version"},
}))
};
+1 -10
View File
@@ -24,16 +24,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
options->processingTimeout = (int32_t) yyjson_get_int(val);
else if (ffStrEqualsIgnCase(key, "preRun"))
{
FF_STRBUF_AUTO_DESTROY _ = ffStrbufCreate();
const char* error = ffProcessAppendStdOut(&_, (char* const[]) {
#ifdef _WIN32
"cmd.exe", "/C",
#else
"/bin/sh", "-c",
#endif
(char*) yyjson_get_str(val), NULL
});
if (error)
if (system(yyjson_get_str(val)) < 0)
return "Failed to execute preRun command";
}
else if (ffStrEqualsIgnCase(key, "detectVersion"))
+7
View File
@@ -63,6 +63,7 @@ logoType:
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
{ "kitty-icat", FF_LOGO_TYPE_IMAGE_KITTY_ICAT },
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
@@ -172,6 +173,11 @@ logoType:
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_KITTY_DIRECT;
}
else if(ffStrEqualsIgnCase(key, "--kitty-icat"))
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_KITTY_ICAT;
}
else if(ffStrEqualsIgnCase(key, "--iterm"))
{
ffOptionParseString(key, value, &options->source);
@@ -283,6 +289,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
{ "kitty-icat", FF_LOGO_TYPE_IMAGE_KITTY_ICAT },
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
+1
View File
@@ -17,6 +17,7 @@ typedef enum __attribute__((__packed__)) FFLogoType
FF_LOGO_TYPE_IMAGE_SIXEL, //image file, printed as sixel codes
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
FF_LOGO_TYPE_IMAGE_KITTY_DIRECT, //image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)
FF_LOGO_TYPE_IMAGE_KITTY_ICAT, //image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed"
FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol
FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa
FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string
+1 -1
View File
@@ -34,5 +34,5 @@ bool ffListPop(FFlist* list, void* result)
memcpy(result, ffListGet(list, list->length - 1), list->elementSize);
--list->length;
return result;
return true;
}
+16 -6
View File
@@ -225,12 +225,6 @@ void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value)
ffStrbufAppendNS(strbuf, length, value);
}
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
{
ffStrbufClear(strbuf);
ffStrbufAppendNS(strbuf, value->length, value->chars);
}
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c)
{
if(strbuf->length == 0)
@@ -576,6 +570,22 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
return true;
}
/// @brief Restore the end of a line that was modified by ffStrbufGetline.
/// @warning This function should be called before breaking an ffStrbufGetline loop.
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
{
assert(buffer && lineptr && n);
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
assert(!*lineptr || (*lineptr >= buffer->chars && *lineptr <= buffer->chars + buffer->length));
if (!*lineptr)
return;
*lineptr += *n;
if (*lineptr < buffer->chars + buffer->length)
**lineptr = '\n';
}
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf)
{
if (strbuf->allocated == 0) return false; // Doesn't work with static strings
+19 -3
View File
@@ -49,7 +49,6 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c);
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c);
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
@@ -91,6 +90,7 @@ void ffStrbufUpperCase(FFstrbuf* strbuf);
void ffStrbufLowerCase(FFstrbuf* strbuf);
bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer);
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer);
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
@@ -102,8 +102,13 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
static inline void ffStrbufInitCopy(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict src)
{
ffStrbufInitA(strbuf, src->allocated);
ffStrbufAppend(strbuf, src);
if (src->allocated == 0) // static string
memcpy(strbuf, src, sizeof(FFstrbuf));
else
{
ffStrbufInitA(strbuf, src->allocated);
ffStrbufAppend(strbuf, src);
}
}
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateCopy(const FFstrbuf* src)
@@ -209,6 +214,17 @@ static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
}
static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
{
assert(value && value != strbuf);
if (strbuf->allocated == 0 && value->allocated == 0)
{
memcpy(strbuf, value, sizeof(FFstrbuf));
return;
}
ffStrbufSetNS(strbuf, value->length, value->chars);
}
static inline void ffStrbufInit(FFstrbuf* strbuf)
{
extern char* CHAR_NULL_PTR;
+5 -2
View File
@@ -21,7 +21,8 @@ static void getExePath(FFPlatform* platform)
char exePath[PATH_MAX + 1];
#ifdef __linux__
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
exePath[exePathLen] = '\0';
if (exePathLen >= 0)
exePath[exePathLen] = '\0';
#elif defined(__APPLE__)
int exePathLen = proc_pidpath((int) getpid(), exePath, sizeof(exePath));
#elif defined(__FreeBSD__) || defined(__NetBSD__)
@@ -44,7 +45,8 @@ static void getExePath(FFPlatform* platform)
size_t exePathLen = 0;
#elif defined(__sun)
ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1);
exePath[exePathLen] = '\0';
if (exePathLen >= 0)
exePath[exePathLen] = '\0';
#endif
if (exePathLen > 0)
{
@@ -107,6 +109,7 @@ static void getCacheDir(FFPlatform* platform)
static void getConfigDirs(FFPlatform* platform)
{
// Always make sure `${XDG_CONFIG_HOME:-$HOME/.config}` is the first entry
platformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME");
ffPlatformPathAddHome(&platform->configDirs, platform, ".config/");
+6 -6
View File
@@ -31,13 +31,12 @@ static void getExePath(FFPlatform* platform)
static void getHomeDir(FFPlatform* platform)
{
PWSTR pPath;
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath)))
{
ffStrbufSetWS(&platform->homeDir, pPath);
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
CoTaskMemFree(pPath);
}
else
{
@@ -45,28 +44,29 @@ static void getHomeDir(FFPlatform* platform)
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
CoTaskMemFree(pPath);
}
static void getCacheDir(FFPlatform* platform)
{
PWSTR pPath;
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath)))
{
ffStrbufSetWS(&platform->cacheDir, pPath);
ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
CoTaskMemFree(pPath);
}
else
{
ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
}
CoTaskMemFree(pPath);
}
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
{
PWSTR pPath;
PWSTR pPath = NULL;
if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath)))
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateWS(pPath);
@@ -74,8 +74,8 @@ static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
ffStrbufEnsureEndsWithC(&buffer, '/');
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
CoTaskMemFree(pPath);
}
CoTaskMemFree(pPath);
}
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
+31
View File
@@ -0,0 +1,31 @@
#include "util/windows/version.h"
#include "util/mallocHelper.h"
#include <windows.h>
bool ffGetFileVersion(const wchar_t* filePath, FFstrbuf* version)
{
DWORD handle;
DWORD size = GetFileVersionInfoSizeW(filePath, &handle);
if(size > 0)
{
FF_AUTO_FREE void* versionData = malloc(size);
if(GetFileVersionInfoW(filePath, handle, size, versionData))
{
VS_FIXEDFILEINFO* verInfo;
UINT len;
if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD)
{
ffStrbufAppendF(version, "%u.%u.%u.%u",
(unsigned)(( verInfo->dwProductVersionMS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionMS >> 0 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 16 ) & 0xffff),
(unsigned)(( verInfo->dwProductVersionLS >> 0 ) & 0xffff)
);
return true;
}
}
}
return false;
}
+3
View File
@@ -0,0 +1,3 @@
#include "fastfetch.h"
bool ffGetFileVersion(const wchar_t* filePath, FFstrbuf* version);
+42
View File
@@ -593,6 +593,48 @@ int main(void)
VERIFY(ffStrbufRemoveDupWhitespaces(&strbuf) == false);
VERIFY(strcmp(strbuf.chars, " ") == 0);
{
ffStrbufSetStatic(&strbuf, "abcdef");
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateCopy(&strbuf);
VERIFY(newStr.allocated == 0);
VERIFY(newStr.chars == strbuf.chars);
}
{
ffStrbufSetStatic(&strbuf, "abcdef");
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateS("123456");
ffStrbufSet(&newStr, &strbuf);
VERIFY(newStr.allocated > 0);
VERIFY(newStr.chars != strbuf.chars);
VERIFY(ffStrbufEqualS(&newStr, "abcdef"));
}
{
ffStrbufSetStatic(&strbuf, "abcdefghijkl");
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateS("123456");
ffStrbufSet(&newStr, &strbuf);
VERIFY(newStr.allocated > 0);
VERIFY(newStr.chars != strbuf.chars);
VERIFY(ffStrbufEqualS(&newStr, "abcdefghijkl"));
}
{
ffStrbufClear(&strbuf);
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateCopy(&strbuf);
VERIFY(newStr.allocated == 0);
VERIFY(newStr.chars == strbuf.chars);
VERIFY(newStr.chars[0] == '\0');
}
{
ffStrbufClear(&strbuf);
FF_STRBUF_AUTO_DESTROY newStr = ffStrbufCreateS("123456");
ffStrbufSet(&newStr, &strbuf);
VERIFY(newStr.allocated > 0);
VERIFY(newStr.chars != strbuf.chars);
VERIFY(ffStrbufEqualS(&newStr, ""));
}
//Success
puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
}