mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 52de8df1f9 | |||
| be99c4ca6e | |||
| 8133c3365f | |||
| 6226ccc70e | |||
| 88917cb14f | |||
| a93e2aafdb | |||
| 5848b5fc24 | |||
| 934b6291e3 | |||
| 90068ab474 | |||
| 5567e6cc5e | |||
| 8b3017c0d9 | |||
| f9f15ba844 | |||
| b282ac5d47 | |||
| 6577884417 | |||
| c4ee606955 | |||
| 59c80820f2 | |||
| c11e14f7e1 | |||
| ab6a770155 | |||
| 0e99486efe | |||
| f82f3002e4 | |||
| 0bed182784 | |||
| d39be955b1 | |||
| 3b2790cccc | |||
| 3ea0406b69 | |||
| 6429c20466 | |||
| 88ebeb21e2 | |||
| f28f5e2874 | |||
| 637c37e81c | |||
| b2c779dea9 | |||
| 89d636447b | |||
| 3dc51d5f88 | |||
| 60ff89c794 | |||
| f973572c5a | |||
| ea78665971 | |||
| 80b48dd2d1 | |||
| df6eed7a02 | |||
| c9ac09f9eb | |||
| 67597e4566 | |||
| 611de77980 | |||
| 0fde835629 | |||
| f373e07847 | |||
| 89e4403cc8 | |||
| c68d21e215 | |||
| f14cd2c6e8 | |||
| d58d786c83 | |||
| 9f37557177 | |||
| aa63c4f5f2 | |||
| a378d2ad62 | |||
| 2ab2dd4d48 | |||
| 2a83b86ba4 | |||
| d967d05019 | |||
| 9ef8580d93 | |||
| 813b80c5a8 | |||
| ddce9b2357 | |||
| 9342d74c93 | |||
| d6028370e7 | |||
| e425d7df63 | |||
| a4a2ae7d67 | |||
| 99aa0638cc | |||
| 1a9e637134 | |||
| f322405c04 | |||
| e4202635af | |||
| 2f13ee3814 | |||
| 2bfde87f84 | |||
| f38a51c9bc | |||
| 28ec935c42 | |||
| d939f95c69 | |||
| e0fd5111fe | |||
| 4736031538 | |||
| 66085c087e | |||
| e0253d71c0 | |||
| dadd4bfab6 | |||
| 2f3861e732 | |||
| 851f271ed5 | |||
| d3e40f625b | |||
| 7c1991c2e3 | |||
| b8048ee488 | |||
| b99f54b9f4 | |||
| b38d7a4919 | |||
| 45f7e2c0b2 | |||
| 5a8dda27ff | |||
| 1ea3264b13 | |||
| 852a729581 | |||
| 0f454b7140 | |||
| 9c47a3a9e7 | |||
| 4adf7fda28 | |||
| e2fc83fd48 | |||
| dd41dfa000 | |||
| 14d6157901 | |||
| 74586a9df1 | |||
| c5d4b20729 | |||
| b152b383a2 | |||
| ae26692ef6 | |||
| 4f807f26a9 | |||
| 4bef801337 | |||
| 41240e9460 | |||
| 3bb82423b3 | |||
| b87df82d58 | |||
| c145ce49a5 | |||
| 8c4fb5d6d4 | |||
| eae0fee032 | |||
| 4472a13f41 |
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Vendored
+12
@@ -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
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.31.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.33.0_source.buildinfo universe/utils optional
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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>",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -11,4 +11,4 @@ typedef struct FFBluetoothResult
|
||||
bool connected;
|
||||
} FFBluetoothResult;
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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, ¶m) < 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -8,6 +8,7 @@ typedef struct FFSoundDevice
|
||||
{
|
||||
FFstrbuf identifier;
|
||||
FFstrbuf name;
|
||||
FFstrbuf platformApi;
|
||||
uint8_t volume; // 0-100%
|
||||
bool main;
|
||||
bool active;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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/"))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
.7J~
|
||||
~G@^ .^.
|
||||
:5&&&&##B?. !B&G7
|
||||
7B##&&B##BBP~ ^P&@&##P~
|
||||
$2^YGP5PBPPP5YY55?: .7GGGB#BPPP7.
|
||||
.?PPPPPPPPPP55YYY5Y!.^YPPPPPP5YYY5J~
|
||||
!PPPPPPPPPPPPPP5YYYY5JY5PPPPPPP55YY55?:
|
||||
^YPPPPPPPPPPPPPPPPYYYYYYYYY5PPPPPPP5YYY5Y!.
|
||||
.7PPPPPPPPPPPPPPPPPP5YYYYYYYYY55PPPPP5YYYYY5J~
|
||||
!5GPPPPPPPPPPPPPPPPPPPP55555555YY5PPPPPP5555555?:
|
||||
7777777777777777777777777!!!!!!!!!77777777!!!!!7!:
|
||||
@@ -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/:.`
|
||||
@@ -0,0 +1,12 @@
|
||||
___╓╓___
|
||||
_▄▄▓▓▀▀╜╜╨▀▓▓▓╗_
|
||||
╓▓▓▀² `╙▓▓╖
|
||||
╣▓▀ _▄▓▓▓▓▓▓W_ ╙▓▓
|
||||
╣▓╜ ,▓▓▓▓▓▓▓▓▓▓▓▓_ ²▓▓
|
||||
╒▓▌ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║▓m
|
||||
╞▓▓ í▓▓▓▓▓▓▓▓▓▓▓▓▓▓h ╞▓╡
|
||||
²▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║▓h
|
||||
║▓▄ ╙▓▓▓▓▓▓▓▓▓▓╜ ƒ▓▓
|
||||
╙▓▓_ ⁿ╙╨╝╝╝╜² _╢▓╜
|
||||
╙▓▓╗__ _╗▓▓╜
|
||||
`╙╝▓▓▓▓▓▓▓▓╝╙
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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"},
|
||||
}))
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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"))
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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/");
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffGetFileVersion(const wchar_t* filePath, FFstrbuf* version);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user