mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
188 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 | |||
| 5b001d6bd6 | |||
| 1b52029fce | |||
| 2176ea2937 | |||
| ac2266c72f | |||
| 0dc40a2632 | |||
| ca975f8e81 | |||
| c4c6fe6668 | |||
| 0a00f5721e | |||
| 69f180beea | |||
| 0e9cdf75b5 | |||
| 7d7e219c0a | |||
| 4937ccfa81 | |||
| d0d29c163b | |||
| 901e0eb177 | |||
| 87446e6eef | |||
| bfaa73a2c7 | |||
| 373e288d03 | |||
| 82170ceab0 | |||
| 009a7888b5 | |||
| ab1a11c9fa | |||
| 68746275f8 | |||
| 491cfb94b6 | |||
| 79c8919431 | |||
| e98afa8315 | |||
| 86783c033b | |||
| f01944de41 | |||
| ebfdeef25c | |||
| 9a36d63d18 | |||
| e45ff546ed | |||
| 2700390371 | |||
| 5c01685d69 | |||
| d897472572 | |||
| 8410a66277 | |||
| 856d229b36 | |||
| b33692aa7d | |||
| e90c5cb241 | |||
| 03cd283755 | |||
| 58a1d965cb | |||
| 6edf763f2b | |||
| ab200d7e4a | |||
| dfe36daf79 | |||
| e9ab67b380 | |||
| f073f4882c | |||
| 692ad502df | |||
| 3004ce8565 | |||
| ee8801b54d | |||
| bbe239647b | |||
| 77c06193d6 | |||
| 90bbefe11a | |||
| 69a7e64e48 | |||
| ee564de461 | |||
| 9955e9da02 | |||
| 8b41cbd508 | |||
| 7535ce8a18 | |||
| b76eb87510 | |||
| 0cd7aeac19 | |||
| 04088b5b2c | |||
| e77c3119ca | |||
| 3463fc331f | |||
| 64287eed21 | |||
| 1b835544b6 | |||
| 55352be0cc | |||
| c0be2637a8 | |||
| 864fb918bc | |||
| 2197cfb06d | |||
| 94f8ff938b | |||
| 7000317841 | |||
| 06055cc6c3 | |||
| 601b9706b5 | |||
| d48c76b597 | |||
| 9a1d18556d | |||
| 71b073e1bf | |||
| a567268ca1 | |||
| 8b62ad72f7 | |||
| cee880cb83 | |||
| 925c3471c2 | |||
| 7948e627b0 | |||
| 4cca63a299 | |||
| 21a35769a7 | |||
| fa9290088d | |||
| 3d5133eaba | |||
| 4cbcd0f107 | |||
| fdc9bee4b3 | |||
| 16b7a4a1be | |||
| 465170428f | |||
| e953ed9d88 |
@@ -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
|
||||
@@ -274,7 +309,7 @@ jobs:
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-12
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -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,10 +484,10 @@ 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 py3-requests
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio hwdata py3-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -578,6 +613,7 @@ jobs:
|
||||
- linux-aarch64
|
||||
- linux-armv7
|
||||
- linux-riscv64
|
||||
- linux-ppc64le
|
||||
- musl-amd64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
|
||||
+134
@@ -1,3 +1,137 @@
|
||||
# 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:
|
||||
* Fix `pci.ids` file location on OpenBSD (GPU, OpenBSD)
|
||||
* It's normally unused because enumerating PCI devices on OpenBSD requires root privileges
|
||||
* Fix bssid formatting (Wifi, Linux)
|
||||
* Fix Linux Lite distro detection (#1434, OS, Linux)
|
||||
* Suppress XE driver warnings from Mesa (#1435, OpenGL, Linux)
|
||||
* Fix format parameter name (#1443, Version)
|
||||
* Don't report useless information when Wifi is disabled (Wifi, FreeBSD)
|
||||
* Currently there are issues when the SSID contains whitespaces. More fixes are expected in the future.
|
||||
* Always use physical size reported by X11 server to avoid inconsistent results (#1444, Display, Linux)
|
||||
|
||||
Features:
|
||||
* Randomly select one if the logo source expands to multiple files (#1426, Logo)
|
||||
* Report mac product name when running Linux in MacBook (Host, Linux / FreeBSD)
|
||||
* Use screen size reported in DTD if make sense (Display)
|
||||
* Detect Virtualized Apple Silicon CPUs (CPU, Linux)
|
||||
* Add detection support for fvwm and ctwm (WM, OpenBSD / NetBSD)
|
||||
* Add Armbian-unofficial detection (OS, Linux)
|
||||
* Prefer surfaceless display when connect EGL (OpenGL)
|
||||
* Improve accuracy of WM detection on FreeBSD (WM, FreeBSD)
|
||||
* Add ratpoison window manager (WM, Linux)
|
||||
|
||||
Logo:
|
||||
* Update Linux Lite
|
||||
* Add Serpent OS
|
||||
* Add Ultramarine Small
|
||||
* Update Debian
|
||||
|
||||
# 2.31.0
|
||||
|
||||
Bugfixes:
|
||||
* Improve performance of media detection; fix musikcube detection (Media, Linux)
|
||||
* After the change, `general.processingTimeout` will also control the timeout of dbus remote calls
|
||||
* Fix invalid variable names (#1408, Users)
|
||||
* Change physical size detection to use basic display parameters (#1406)
|
||||
* Fix possible sigfaults when detecting displays (#1393)
|
||||
* Fix Nvidia card type detection
|
||||
* Fix wl-restart parsing (#1422, WM, Linux)
|
||||
* Fix syntax error in completion file (#1421)
|
||||
* Fix hunging when using `ssh-agent` as command text (#1418, Command, macOS)
|
||||
|
||||
Features:
|
||||
* Remove support of xcb & xlib and xrandr extension is always required (Display)
|
||||
* Support preferred resolution & refresh rate detection
|
||||
* On macOS there is no preferred resolution reported and maximum available resolution is reported instead.
|
||||
* `--display-format {preferred-width}x{preferred-height}@{preferred-refresh-rate}`
|
||||
* Report scale factor in custom format (Display)
|
||||
* `--display-format {scale-factor}`
|
||||
* Detect current Wi-Fi channel and maximum frequency (Wifi)
|
||||
* Report processor package count (#1413, CPU)
|
||||
* Remove duplicate whitespaces in CPU name
|
||||
* Support sakura terminal version & font detection (Terminal / TerminalFont, Linux)
|
||||
|
||||
Logo:
|
||||
* Fix LMDE
|
||||
* Update MidOS
|
||||
* Add Windows Server 2025
|
||||
|
||||
# 2.30.1
|
||||
|
||||
Bugfixes:
|
||||
|
||||
+79
-44
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.30.1
|
||||
VERSION 2.34.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -57,9 +57,7 @@ include(CMakeDependentOption)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
@@ -72,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)
|
||||
@@ -88,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
|
||||
@@ -504,6 +503,7 @@ if(LINUX)
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/host/host_mac.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/initsystem/initsystem_linux.c
|
||||
src/detection/keyboard/keyboard_linux.c
|
||||
@@ -534,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
|
||||
@@ -617,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
|
||||
@@ -651,6 +650,7 @@ elseif(FreeBSD)
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/host/host_mac.c
|
||||
src/detection/lm/lm_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/initsystem/initsystem_linux.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
|
||||
@@ -883,6 +892,7 @@ elseif(APPLE)
|
||||
src/detection/gpu/gpu_apple.c
|
||||
src/detection/gpu/gpu_apple.m
|
||||
src/detection/host/host_apple.c
|
||||
src/detection/host/host_mac.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/initsystem/initsystem_linux.c
|
||||
src/detection/keyboard/keyboard_apple.c
|
||||
@@ -912,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
|
||||
@@ -951,6 +961,7 @@ elseif(WIN32)
|
||||
src/detection/dns/dns_windows.c
|
||||
src/detection/font/font_windows.c
|
||||
src/detection/gpu/gpu_windows.c
|
||||
src/detection/host/host_mac.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_windows.c
|
||||
src/detection/initsystem/initsystem_nosupport.c
|
||||
@@ -992,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
|
||||
)
|
||||
@@ -1130,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)
|
||||
@@ -1222,6 +1242,9 @@ endif()
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
message(STATUS "Enabling custom link type: ${BINARY_LINK_TYPE}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_DISABLE_DLOPEN=1)
|
||||
if(NOT WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--copy-dt-needed-entries")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
|
||||
@@ -1277,18 +1300,10 @@ ff_lib_enable(XCB_RANDR
|
||||
"xcb-randr"
|
||||
"XcbRandr"
|
||||
)
|
||||
ff_lib_enable(XCB
|
||||
"xcb"
|
||||
"Xcb"
|
||||
)
|
||||
ff_lib_enable(XRANDR
|
||||
"xrandr"
|
||||
"XRandr"
|
||||
)
|
||||
ff_lib_enable(X11
|
||||
"x11"
|
||||
"X11"
|
||||
)
|
||||
ff_lib_enable(DRM
|
||||
"libdrm"
|
||||
"Libdrm"
|
||||
@@ -1470,6 +1485,7 @@ elseif(FreeBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "usbhid"
|
||||
PRIVATE "bluetooth"
|
||||
)
|
||||
if(NOT DragonFly)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1488,6 +1504,7 @@ elseif(OpenBSD)
|
||||
elseif(NetBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "prop"
|
||||
)
|
||||
elseif(SunOS)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1614,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()
|
||||
|
||||
###################
|
||||
@@ -1690,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:
|
||||
|
||||
@@ -26,7 +26,7 @@ def main():
|
||||
for flag in data[key]:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
for i in range(1, 10):
|
||||
command_prefix = f"--logo-color-{i}[{flag["desc"]} ({i})]"
|
||||
command_prefix = f"--logo-color-{i}[{flag['desc']} ({i})]"
|
||||
print_command(command_prefix, flag)
|
||||
continue
|
||||
|
||||
@@ -34,11 +34,11 @@ def main():
|
||||
continue
|
||||
|
||||
if "short" in flag:
|
||||
command_prefix = f"-{flag["short"]}[{flag["desc"]}]"
|
||||
command_prefix = f"-{flag['short']}[{flag['desc']}]"
|
||||
print_command(command_prefix, flag)
|
||||
|
||||
if "long" in flag:
|
||||
command_prefix = f"--{flag["long"]}[{flag["desc"]}]"
|
||||
command_prefix = f"--{flag['long']}[{flag['desc']}]"
|
||||
print_command(command_prefix, flag)
|
||||
|
||||
|
||||
|
||||
Vendored
+24
@@ -1,3 +1,27 @@
|
||||
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
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 04 Dec 2024 08:41:40 +0800
|
||||
|
||||
fastfetch (2.30.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.30.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 18 Nov 2024 15:40:48 +0800
|
||||
|
||||
fastfetch (2.30.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.30.0
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.30.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.33.0_source.buildinfo universe/utils optional
|
||||
|
||||
+1407
-243
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -87,8 +87,8 @@
|
||||
"opengl",
|
||||
"opencl",
|
||||
"users",
|
||||
"bluetooth",
|
||||
"bluetoothradio",
|
||||
// "bluetooth", // doesn't work on macOS because it requires bluetooth permissions
|
||||
// "bluetoothradio",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
|
||||
+6
-4
@@ -9,7 +9,7 @@ For the format of the JSON file, see https://github.com/fastfetch-cli/fastfetch/
|
||||
"""
|
||||
|
||||
from json import load
|
||||
from datetime import date
|
||||
from datetime import datetime, timezone
|
||||
from time import time
|
||||
from re import search
|
||||
from os import environ, path
|
||||
@@ -36,8 +36,10 @@ manSection = 1
|
||||
titlePage = "Fastfetch man page"
|
||||
# date (center footer)
|
||||
# format : "Month (abbreviation) Day Year"
|
||||
todayDate = date.fromtimestamp(
|
||||
int(environ.get("SOURCE_DATE_EPOCH", time()))).strftime("%b %d %Y")
|
||||
todayDate = datetime.fromtimestamp(
|
||||
int(environ.get("SOURCE_DATE_EPOCH", time())),
|
||||
tz=timezone.utc,
|
||||
).strftime("%b %d %Y")
|
||||
# file to fastfetch version (left footer)
|
||||
pathToVersionFile = path.join(pathToCurrentDir, "../CMakeLists.txt")
|
||||
|
||||
@@ -52,7 +54,7 @@ optionSection = r"""
|
||||
Parsing is not case sensitive. E.g. \fB--logo-type\fR is
|
||||
equal to \fB--LOGO-TYPE\fR.
|
||||
|
||||
If a value is between square brakets, it is optional.
|
||||
If a value is between square brackets, it is optional.
|
||||
An optional boolean value defaults to true if not specified.
|
||||
|
||||
More detailed help messages for each options can be printed
|
||||
|
||||
+2
-2
@@ -171,7 +171,7 @@ DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const c
|
||||
if (arg)
|
||||
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
@@ -189,7 +189,7 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
|
||||
DBUS_TYPE_STRING, &property,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
|
||||
+5
-2
@@ -6,8 +6,6 @@
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#define FF_DBUS_TIMEOUT_MILLISECONDS 100
|
||||
|
||||
typedef struct FFDBusLibrary
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(dbus_bus_get)
|
||||
@@ -38,4 +36,9 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
|
||||
|
||||
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface)
|
||||
{
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface);
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
|
||||
+2
-4
@@ -42,7 +42,5 @@ typedef struct FFformatarg
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, numArgs, arguments) do {\
|
||||
static_assert(sizeof(arguments) / sizeof(*arguments) == (numArgs), "Invalid number of format arguments");\
|
||||
ffParseFormatString((buffer), (formatstr), (numArgs), (arguments));\
|
||||
} while (0)
|
||||
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, arguments) \
|
||||
ffParseFormatString((buffer), (formatstr), sizeof(arguments) / sizeof(*arguments), (arguments));
|
||||
|
||||
+7
-10
@@ -76,19 +76,21 @@ static void resetConsole(void)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI consoleHandler(DWORD signal)
|
||||
BOOL WINAPI consoleHandler(FF_MAYBE_UNUSED DWORD signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
static void exitSignalHandler(int signal)
|
||||
static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
static void chldSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
// empty; used to interrupt the poll and read syscalls
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffStart(void)
|
||||
@@ -118,6 +120,7 @@ void ffStart(void)
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
sigaction(SIGCHLD, &(struct sigaction) { .sa_handler = chldSignalHandler }, NULL);
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
@@ -179,15 +182,9 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_XCB_RANDR
|
||||
"xcb-randr\n"
|
||||
#endif
|
||||
#if FF_HAVE_XCB
|
||||
"xcb\n"
|
||||
#endif
|
||||
#if FF_HAVE_XRANDR
|
||||
"xrandr\n"
|
||||
#endif
|
||||
#if FF_HAVE_X11
|
||||
"x11\n"
|
||||
#endif
|
||||
#if FF_HAVE_DRM
|
||||
"drm\n"
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
@@ -145,10 +146,10 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
if (wordexp(in, &exp, 0) != 0)
|
||||
return false;
|
||||
|
||||
if (exp.we_wordc == 1)
|
||||
if (exp.we_wordc >= 1)
|
||||
{
|
||||
result = true;
|
||||
ffStrbufSetS(out, exp.we_wordv[0]);
|
||||
ffStrbufSetS(out, exp.we_wordv[exp.we_wordc > 1 ? ffTimeGetNow() % exp.we_wordc : 0]);
|
||||
}
|
||||
|
||||
wordfree(&exp);
|
||||
@@ -159,10 +160,10 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0)
|
||||
return false;
|
||||
|
||||
if (gb.gl_matchc == 1)
|
||||
if (gb.gl_matchc >= 1)
|
||||
{
|
||||
result = true;
|
||||
ffStrbufSetS(out, gb.gl_pathv[0]);
|
||||
ffStrbufSetS(out, gb.gl_pathv[gb.gl_matchc > 1 ? ffTimeGetNow() % gb.gl_matchc : 0]);
|
||||
}
|
||||
|
||||
globfree(&gb);
|
||||
|
||||
+15
-23
@@ -6,6 +6,20 @@ struct yyjson_val;
|
||||
struct yyjson_mut_doc;
|
||||
struct yyjson_mut_val;
|
||||
|
||||
typedef struct FFModuleFormatArg
|
||||
{
|
||||
const char* desc;
|
||||
const char* name;
|
||||
} FFModuleFormatArg;
|
||||
|
||||
typedef struct FFModuleFormatArgList
|
||||
{
|
||||
FFModuleFormatArg* args;
|
||||
uint32_t count;
|
||||
} FFModuleFormatArgList;
|
||||
|
||||
#define FF_FORMAT_ARG_LIST(list) { .args = list, .count = sizeof(list) / sizeof(FFModuleFormatArg) }
|
||||
|
||||
// Must be the first field of FFModuleOptions
|
||||
typedef struct FFModuleBaseInfo
|
||||
{
|
||||
@@ -19,32 +33,10 @@ typedef struct FFModuleBaseInfo
|
||||
void (*parseJsonObject)(void* options, struct yyjson_val *module);
|
||||
void (*printModule)(void* options);
|
||||
void (*generateJsonResult)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
|
||||
void (*printHelpFormat)(void);
|
||||
void (*generateJsonConfig)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* obj);
|
||||
FFModuleFormatArgList formatArgs;
|
||||
} FFModuleBaseInfo;
|
||||
|
||||
static inline void ffOptionInitModuleBaseInfo(
|
||||
FFModuleBaseInfo* baseInfo,
|
||||
const char* name,
|
||||
const char* description,
|
||||
void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value)
|
||||
void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module)
|
||||
void* printModule, // void (*const printModule)(void* options)
|
||||
void* generateJsonResult, // void (*const generateJsonResult)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
void (*printHelpFormat)(void),
|
||||
void* generateJsonConfig // void (*const generateJsonConfig)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
)
|
||||
{
|
||||
baseInfo->name = name;
|
||||
baseInfo->description = description;
|
||||
baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions;
|
||||
baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject;
|
||||
baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule;
|
||||
baseInfo->generateJsonResult = (__typeof__(baseInfo->generateJsonResult)) generateJsonResult;
|
||||
baseInfo->printHelpFormat = printHelpFormat;
|
||||
baseInfo->generateJsonConfig = (__typeof__(baseInfo->generateJsonConfig)) generateJsonConfig;
|
||||
}
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFModuleKeyType
|
||||
{
|
||||
FF_MODULE_KEY_TYPE_NONE = 0,
|
||||
|
||||
+1
-16
@@ -50,7 +50,7 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &moduleArgs->key, 2, ((FFformatarg[]){
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &moduleArgs->key, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(moduleIndex, "index"),
|
||||
FF_FORMAT_ARG(moduleArgs->keyIcon, "icon"),
|
||||
}));
|
||||
@@ -148,18 +148,3 @@ void ffPrintCharTimes(char c, uint32_t times)
|
||||
if(remaining > 0)
|
||||
fwrite(str, 1, remaining, stdout);
|
||||
}
|
||||
|
||||
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[])
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateS(name);
|
||||
ffStrbufLowerCase(&buffer);
|
||||
printf("--%s-format:\n", buffer.chars);
|
||||
printf("Sets the format string for %s output.\n", name);
|
||||
puts("To see how a format string is constructed, take a look at \"fastfetch --help format\".");
|
||||
puts("The following values are passed:");
|
||||
|
||||
for(unsigned i = 0; i < numArgs; i++)
|
||||
printf(" {%u}: %s\n", i + 1, args[i]);
|
||||
|
||||
printf("The default is something similar to \"%s\".\n", def);
|
||||
}
|
||||
|
||||
+2
-10
@@ -14,16 +14,8 @@ typedef enum __attribute__((__packed__)) FFPrintType {
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType);
|
||||
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PRINT_FORMAT_CHECKED(moduleName, moduleIndex, moduleArgs, printType, numArgs, arguments) do {\
|
||||
static_assert(sizeof(arguments) / sizeof(*arguments) == (numArgs), "Invalid number of format arguments");\
|
||||
ffPrintFormat((moduleName), (moduleIndex), (moduleArgs), (printType), (numArgs), (arguments));\
|
||||
} while (0)
|
||||
#define FF_PRINT_FORMAT_CHECKED(moduleName, moduleIndex, moduleArgs, printType, arguments) \
|
||||
ffPrintFormat((moduleName), (moduleIndex), (moduleArgs), (printType), (sizeof(arguments) / sizeof(*arguments)), (arguments));
|
||||
FF_C_PRINTF(5, 6) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...);
|
||||
void ffPrintColor(const FFstrbuf* colorValue);
|
||||
void ffPrintCharTimes(char c, uint32_t times);
|
||||
|
||||
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]);
|
||||
#define FF_PRINT_MODULE_FORMAT_HELP_CHECKED(moduleName, def, numArgs, args) do {\
|
||||
static_assert(sizeof(args) / sizeof(*args) == (numArgs), "Invalid number of format arguments");\
|
||||
ffPrintModuleFormatHelp((moduleName), (def), (numArgs), (args));\
|
||||
} while (0)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/time.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
@@ -90,6 +89,16 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
@@ -104,7 +113,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
else if (nRead == 0)
|
||||
{
|
||||
int stat_loc = 0;
|
||||
if (waitpid(childPid, &stat_loc, 0) == childPid)
|
||||
if (childPid > 0 && waitpid(childPid, &stat_loc, 0) == childPid)
|
||||
{
|
||||
if (!WIFEXITED(stat_loc))
|
||||
return "child process exited abnormally";
|
||||
@@ -113,10 +122,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
|
||||
return NULL;
|
||||
}
|
||||
return "waitpid() failed";
|
||||
return NULL;
|
||||
}
|
||||
else if (nRead < 0)
|
||||
break;
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
return NULL;
|
||||
else
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
|
||||
|
||||
@@ -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/"));
|
||||
|
||||
@@ -99,7 +99,7 @@ double ddca_set_default_sleep_multiplier(double multiplier); // ddcutil 1.4
|
||||
DDCA_Status ddca_init(const char *libopts, int syslog_level, int opts);
|
||||
#endif
|
||||
|
||||
static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
|
||||
static const char* detectWithDdcci(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libddcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffStrbufRemoveStrings(&cpu->name, ARRAY_SIZE(removeStrings), removeStrings);
|
||||
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
|
||||
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||
ffStrbufRemoveDupWhitespaces(&cpu->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ typedef struct FFCPUResult
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
|
||||
uint16_t packages;
|
||||
uint16_t coresPhysical;
|
||||
uint16_t coresLogical;
|
||||
uint16_t coresOnline;
|
||||
|
||||
@@ -109,6 +109,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
return "sysctlbyname(machdep.cpu.brand_string) failed";
|
||||
|
||||
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
|
||||
cpu->packages = (uint16_t) ffSysctlGetInt("hw.packages", 1);
|
||||
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple "))
|
||||
ffStrbufAppendS(&cpu->vendor, "Apple");
|
||||
|
||||
|
||||
@@ -168,7 +168,8 @@ static const char* qcomPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x001: return "Oryon";
|
||||
case 0x001: return "Oryon 1";
|
||||
case 0x002: return "Oryon 2";
|
||||
case 0x00f: return "Scorpion";
|
||||
case 0x02d: return "Scorpion";
|
||||
case 0x04d: return "Krait";
|
||||
@@ -262,6 +263,9 @@ static const char* applePartId2name(uint32_t partId)
|
||||
case 0x037: return "Everest-A16";
|
||||
case 0x038: return "Blizzard-M2-Max";
|
||||
case 0x039: return "Avalanche-M2-Max";
|
||||
case 0x046: return "Sawtooth-M11";
|
||||
case 0x048: return "Sawtooth-M3-Max";
|
||||
case 0x049: return "Everest-M3-Max";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+109
-35
@@ -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,46 +191,53 @@ 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
|
||||
|
||||
#if __arm__ || __aarch64__
|
||||
#include "cpu_arm.h"
|
||||
|
||||
static void detectArmName(FILE* cpuinfo, FFCPUResult* cpu, uint32_t implId)
|
||||
static void detectArmName(FFstrbuf* cpuinfo, FFCPUResult* cpu, uint32_t implId)
|
||||
{
|
||||
FF_AUTO_FREE char* line = NULL;
|
||||
rewind(cpuinfo);
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
uint32_t lastPartId = UINT32_MAX;
|
||||
uint32_t num = 0;
|
||||
while(getline(&line, &len, cpuinfo) != -1)
|
||||
while(ffStrbufGetline(&line, &len, cpuinfo))
|
||||
{
|
||||
if (!ffStrStartsWith(line, "CPU part\t: ")) continue;
|
||||
uint32_t partId = (uint32_t) strtoul(line + strlen("CPU part\t: "), NULL, 16);
|
||||
const char* name = NULL;
|
||||
if (partId > 0) // Linux reports 0 for unknown CPUs
|
||||
switch (implId)
|
||||
{
|
||||
switch (implId)
|
||||
{
|
||||
case 0x41: name = armPartId2name(partId); break;
|
||||
case 0x42: name = brcmPartId2name(partId); break;
|
||||
case 0x43: name = caviumPartId2name(partId); break;
|
||||
case 0x44: name = decPartId2name(partId); break;
|
||||
case 0x46: name = fujitsuPartId2name(partId); break;
|
||||
case 0x48: name = hisiPartId2name(partId); break;
|
||||
case 0x4e: name = nvidiaPartId2name(partId); break;
|
||||
case 0x50: name = apmPartId2name(partId); break;
|
||||
case 0x51: name = qcomPartId2name(partId); break;
|
||||
case 0x53: name = samsungPartId2name(partId); break;
|
||||
case 0x56: name = marvellPartId2name(partId); break;
|
||||
case 0x61: name = applePartId2name(partId); break;
|
||||
case 0x66: name = faradayPartId2name(partId); break;
|
||||
case 0x69: name = intelPartId2name(partId); break;
|
||||
case 0x6d: name = msPartId2name(partId); break;
|
||||
case 0x70: name = ftPartId2name(partId); break;
|
||||
case 0xc0: name = amperePartId2name(partId); break;
|
||||
}
|
||||
case 0x41: name = armPartId2name(partId); break;
|
||||
case 0x42: name = brcmPartId2name(partId); break;
|
||||
case 0x43: name = caviumPartId2name(partId); break;
|
||||
case 0x44: name = decPartId2name(partId); break;
|
||||
case 0x46: name = fujitsuPartId2name(partId); break;
|
||||
case 0x48: name = hisiPartId2name(partId); break;
|
||||
case 0x4e: name = nvidiaPartId2name(partId); break;
|
||||
case 0x50: name = apmPartId2name(partId); break;
|
||||
case 0x51: name = qcomPartId2name(partId); break;
|
||||
case 0x53: name = samsungPartId2name(partId); break;
|
||||
case 0x56: name = marvellPartId2name(partId); break;
|
||||
case 0x61:
|
||||
if (partId == 0)
|
||||
{
|
||||
// https://github.com/Dr-Noob/cpufetch/issues/213#issuecomment-1927782105
|
||||
ffStrbufSetStatic(&cpu->name, "Virtualized Apple Silicon");
|
||||
ffStrbufGetlineRestore(&line, &len, cpuinfo);
|
||||
return;
|
||||
}
|
||||
name = applePartId2name(partId);
|
||||
break;
|
||||
case 0x66: name = faradayPartId2name(partId); break;
|
||||
case 0x69: name = intelPartId2name(partId); break;
|
||||
case 0x6d: name = msPartId2name(partId); break;
|
||||
case 0x70: name = ftPartId2name(partId); break;
|
||||
case 0xc0: name = amperePartId2name(partId); break;
|
||||
}
|
||||
if (lastPartId != partId)
|
||||
{
|
||||
@@ -220,18 +265,18 @@ static void detectArmName(FILE* cpuinfo, FFCPUResult* cpu, uint32_t implId)
|
||||
#endif
|
||||
|
||||
static const char* parseCpuInfo(
|
||||
FF_MAYBE_UNUSED FILE* cpuinfo,
|
||||
FF_MAYBE_UNUSED FFCPUResult* cpu,
|
||||
FFstrbuf* cpuinfo,
|
||||
FFCPUResult* cpu,
|
||||
FF_MAYBE_UNUSED FFstrbuf* physicalCoresBuffer,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuMHz,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuIsa,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuUarch,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuImplementer)
|
||||
{
|
||||
FF_AUTO_FREE char* line = NULL;
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while(getline(&line, &len, cpuinfo) != -1)
|
||||
while(ffStrbufGetline(&line, &len, cpuinfo))
|
||||
{
|
||||
//Stop after reasonable information is acquired
|
||||
if((*line == '\0' || *line == '\n')
|
||||
@@ -239,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.
|
||||
@@ -465,11 +513,32 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu)
|
||||
}
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
|
||||
{
|
||||
const char* p = cpuinfo->chars;
|
||||
uint64_t low = 0, high = 0;
|
||||
|
||||
while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), "\nphysical id\t:", strlen("\nphysical id\t:"))))
|
||||
{
|
||||
if (!p) break;
|
||||
p += strlen("\nphysical id\t:");
|
||||
char* pend;
|
||||
unsigned long id = strtoul(p, &pend, 10);
|
||||
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
|
||||
high |= 1 << (id - 64);
|
||||
else
|
||||
low |= 1 << id;
|
||||
p = pend;
|
||||
}
|
||||
|
||||
return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high));
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
FF_AUTO_CLOSE_FILE FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if(cpuinfo == NULL)
|
||||
return "fopen(\"/proc/cpuinfo\", \"r\") failed";
|
||||
FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ);
|
||||
if (!ffReadFileBuffer("/proc/cpuinfo", &cpuinfo) || cpuinfo.length == 0)
|
||||
return "ffReadFileBuffer(\"/proc/cpuinfo\") failed";
|
||||
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -479,12 +548,17 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
FF_STRBUF_AUTO_DESTROY cpuUarch = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuImplementerStr = ffStrbufCreate();
|
||||
|
||||
const char* error = parseCpuInfo(cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr);
|
||||
const char* error = parseCpuInfo(&cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr);
|
||||
if (error) return error;
|
||||
|
||||
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
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
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
@@ -519,7 +593,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
#endif
|
||||
|
||||
if (cpu->name.length == 0)
|
||||
detectArmName(cpuinfo, cpu, cpuImplementer);
|
||||
detectArmName(&cpuinfo, cpu, cpuImplementer);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -100,9 +100,7 @@ static const char* detectNCores(FFCPUResult* cpu)
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
{
|
||||
if (ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if (ptr->Relationship == RelationGroup)
|
||||
if (ptr->Relationship == RelationGroup)
|
||||
{
|
||||
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
|
||||
{
|
||||
@@ -110,6 +108,10 @@ static const char* detectNCores(FFCPUResult* cpu)
|
||||
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
|
||||
}
|
||||
}
|
||||
else if (ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if (ptr->Relationship == RelationProcessorPackage)
|
||||
cpu->packages++;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -7,6 +7,9 @@ FFDisplayResult* ffdsAppendDisplay(
|
||||
double refreshRate,
|
||||
uint32_t scaledWidth,
|
||||
uint32_t scaledHeight,
|
||||
uint32_t preferredWidth,
|
||||
uint32_t preferredHeight,
|
||||
double preferredRefreshRate,
|
||||
uint32_t rotation,
|
||||
FFstrbuf* name,
|
||||
FFDisplayType type,
|
||||
@@ -25,6 +28,9 @@ FFDisplayResult* ffdsAppendDisplay(
|
||||
display->refreshRate = refreshRate;
|
||||
display->scaledWidth = scaledWidth;
|
||||
display->scaledHeight = scaledHeight;
|
||||
display->preferredWidth = preferredWidth;
|
||||
display->preferredHeight = preferredHeight;
|
||||
display->preferredRefreshRate = preferredRefreshRate;
|
||||
display->rotation = rotation;
|
||||
ffStrbufInitMove(&display->name, name);
|
||||
display->type = type;
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
#define FF_WM_PRETTY_ICEWM "IceWM"
|
||||
#define FF_WM_PRETTY_SPECTRWM "spectrwm"
|
||||
#define FF_WM_PRETTY_DTWM "dtwm"
|
||||
|
||||
#define FF_WM_PRETTY_FVWM "fvwm"
|
||||
#define FF_WM_PRETTY_CTWM "ctwm"
|
||||
#define FF_WM_PRETTY_RATPOISON "ratpoison"
|
||||
|
||||
#define FF_WM_PROTOCOL_TTY "TTY"
|
||||
#define FF_WM_PROTOCOL_X11 "X11"
|
||||
@@ -58,17 +60,20 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus
|
||||
|
||||
typedef struct FFDisplayResult
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
double refreshRate;
|
||||
uint32_t scaledWidth;
|
||||
uint32_t scaledHeight;
|
||||
uint32_t width; // in px
|
||||
uint32_t height; // in px
|
||||
double refreshRate; // in Hz
|
||||
uint32_t scaledWidth; // in px
|
||||
uint32_t scaledHeight; // in px
|
||||
uint32_t preferredWidth; // in px
|
||||
uint32_t preferredHeight; // in px
|
||||
double preferredRefreshRate; // in Hz
|
||||
FFstrbuf name;
|
||||
FFDisplayType type;
|
||||
uint32_t rotation;
|
||||
uint64_t id; // platform dependent
|
||||
uint32_t physicalWidth;
|
||||
uint32_t physicalHeight;
|
||||
uint32_t physicalWidth; // in mm
|
||||
uint32_t physicalHeight; // in mm
|
||||
bool primary;
|
||||
const char* platformApi;
|
||||
uint8_t bitDepth;
|
||||
@@ -97,6 +102,9 @@ FFDisplayResult* ffdsAppendDisplay(
|
||||
double refreshRate,
|
||||
uint32_t scaledWidth,
|
||||
uint32_t scaledHeight,
|
||||
uint32_t preferredWidth,
|
||||
uint32_t preferredHeight,
|
||||
double preferredRefreshRate,
|
||||
uint32_t rotation,
|
||||
FFstrbuf* name,
|
||||
FFDisplayType type,
|
||||
|
||||
@@ -61,6 +61,9 @@ static void detectWithDumpsys(FFDisplayServerResult* ds)
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&name,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
@@ -97,6 +100,9 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
|
||||
(uint32_t) (height / scaleFactor + .5),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_BUILTIN,
|
||||
false,
|
||||
0,
|
||||
|
||||
@@ -60,7 +60,11 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t physicalWidth = 0, physicalHeight = 0;
|
||||
uint32_t preferredWidth = 0, preferredHeight = 0;
|
||||
double preferredRefreshRate = 0;
|
||||
|
||||
if(displayInfo)
|
||||
{
|
||||
CFDictionaryRef productNames;
|
||||
@@ -76,9 +80,35 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
if (edidLength >= 128)
|
||||
ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight);
|
||||
}
|
||||
|
||||
if (!physicalWidth || !physicalHeight)
|
||||
{
|
||||
if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayHorizontalImageSize), (int*) &physicalWidth) == NULL)
|
||||
ffCfDictGetInt(displayInfo, CFSTR(kDisplayVerticalImageSize), (int*) &physicalHeight);
|
||||
}
|
||||
|
||||
ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), (int*) &preferredWidth);
|
||||
ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), (int*) &preferredHeight);
|
||||
if (preferredWidth && preferredHeight)
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFArrayRef allModes = CGDisplayCopyAllDisplayModes(screen, NULL);
|
||||
if (allModes)
|
||||
{
|
||||
for (CFIndex i = 0, count = CFArrayGetCount(allModes); i < count; i++)
|
||||
{
|
||||
CGDisplayModeRef modeInfo = (CGDisplayModeRef) CFArrayGetValueAtIndex(allModes, i);
|
||||
if (CGDisplayModeGetPixelWidth(modeInfo) == preferredWidth && CGDisplayModeGetPixelHeight(modeInfo) == preferredHeight)
|
||||
{
|
||||
double rr = CGDisplayModeGetRefreshRate(modeInfo);
|
||||
if (rr > preferredRefreshRate) preferredRefreshRate = rr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!physicalWidth || !physicalHeight)
|
||||
if ((!physicalWidth || !physicalHeight) && CGDisplayPrimaryDisplay(screen) == screen) // #1406
|
||||
{
|
||||
CGSize size = CGDisplayScreenSize(screen);
|
||||
physicalWidth = (uint32_t) (size.width + 0.5);
|
||||
@@ -91,6 +121,9 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
refreshRate,
|
||||
(uint32_t)CGDisplayModeGetWidth(mode),
|
||||
(uint32_t)CGDisplayModeGetHeight(mode),
|
||||
preferredWidth,
|
||||
preferredHeight,
|
||||
preferredRefreshRate,
|
||||
(uint32_t)CGDisplayRotation(screen),
|
||||
&buffer,
|
||||
CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL,
|
||||
@@ -117,7 +150,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display->type == FF_DISPLAY_TYPE_BUILTIN)
|
||||
if (display->type == FF_DISPLAY_TYPE_BUILTIN && displayInfo)
|
||||
display->hdrStatus = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance"))
|
||||
? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
@@ -135,11 +168,15 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
#endif
|
||||
|
||||
display->serial = CGDisplaySerialNumber(screen);
|
||||
int value;
|
||||
if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayYearOfManufacture), &value) == NULL)
|
||||
display->manufactureYear = (uint16_t) value;
|
||||
if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayWeekOfManufacture), &value) == NULL)
|
||||
display->manufactureWeek = (uint16_t) value;
|
||||
|
||||
if (displayInfo)
|
||||
{
|
||||
int value;
|
||||
if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayYearOfManufacture), &value) == NULL)
|
||||
display->manufactureYear = (uint16_t) value;
|
||||
if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayWeekOfManufacture), &value) == NULL)
|
||||
display->manufactureWeek = (uint16_t) value;
|
||||
}
|
||||
}
|
||||
CGDisplayModeRelease(mode);
|
||||
}
|
||||
|
||||
@@ -149,12 +149,30 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
default: rotation = 0; break;
|
||||
}
|
||||
|
||||
DISPLAYCONFIG_TARGET_PREFERRED_MODE preferredMode = {
|
||||
.header = {
|
||||
.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE,
|
||||
.size = sizeof(preferredMode),
|
||||
.adapterId = path->targetInfo.adapterId,
|
||||
.id = path->targetInfo.id,
|
||||
}
|
||||
};
|
||||
double preferredRefreshRate = 0;
|
||||
if (DisplayConfigGetDeviceInfo(&preferredMode.header) == ERROR_SUCCESS)
|
||||
{
|
||||
DISPLAYCONFIG_RATIONAL freq = preferredMode.targetMode.targetVideoSignalInfo.vSyncFreq;
|
||||
preferredRefreshRate = freq.Numerator / (double) freq.Denominator;
|
||||
}
|
||||
|
||||
FFDisplayResult* display = ffdsAppendDisplay(ds,
|
||||
width,
|
||||
height,
|
||||
path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator,
|
||||
(uint32_t) (monitorInfo->info.rcMonitor.right - monitorInfo->info.rcMonitor.left),
|
||||
(uint32_t) (monitorInfo->info.rcMonitor.bottom - monitorInfo->info.rcMonitor.top),
|
||||
preferredMode.width,
|
||||
preferredMode.height,
|
||||
preferredRefreshRate,
|
||||
rotation,
|
||||
&name,
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER ? FF_DISPLAY_TYPE_UNKNOWN :
|
||||
@@ -218,19 +236,24 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
|
||||
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
|
||||
const FFOSResult* os = ffDetectOS();
|
||||
if(
|
||||
ffStrbufEqualS(&os->version, "11") ||
|
||||
ffStrbufEqualS(&os->version, "10") ||
|
||||
ffStrbufEqualS(&os->version, "2022") ||
|
||||
ffStrbufEqualS(&os->version, "2019") ||
|
||||
ffStrbufEqualS(&os->version, "2016")
|
||||
) ffStrbufSetStatic(&ds->dePrettyName, "Fluent");
|
||||
else if(
|
||||
ffStrbufEqualS(&os->version, "8") ||
|
||||
ffStrbufEqualS(&os->version, "8.1") ||
|
||||
ffStrbufEqualS(&os->version, "2012 R2") ||
|
||||
ffStrbufEqualS(&os->version, "2012")
|
||||
) ffStrbufSetStatic(&ds->dePrettyName, "Metro");
|
||||
uint32_t ver = (uint32_t) ffStrbufToUInt(&os->version, 0);
|
||||
if (ver > 1000)
|
||||
{
|
||||
// Windows Server
|
||||
if (ver >= 2016)
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Fluent");
|
||||
else if (ver >= 2012)
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Metro");
|
||||
else
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Aero");
|
||||
}
|
||||
else
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Aero");
|
||||
{
|
||||
if (ver >= 10)
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Fluent");
|
||||
else if (ver >= 8)
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Metro");
|
||||
else
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Aero");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,18 +54,11 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
//Try the x11 libs, from most feature rich to least.
|
||||
//We use the display list to detect if a connection is needed.
|
||||
//They respect wmProtocolName, and only detect display if it is set.
|
||||
|
||||
if(ds->displays.length == 0)
|
||||
ffdsConnectXcbRandr(ds);
|
||||
|
||||
if(ds->displays.length == 0)
|
||||
ffdsConnectXrandr(ds);
|
||||
|
||||
if(ds->displays.length == 0)
|
||||
ffdsConnectXcb(ds);
|
||||
|
||||
if(ds->displays.length == 0)
|
||||
ffdsConnectXlib(ds);
|
||||
}
|
||||
|
||||
//This display detection method is display server independent.
|
||||
@@ -86,7 +79,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
if (ffSettingsGetFreeBSDKenv("screen.height", &buf))
|
||||
{
|
||||
uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0);
|
||||
ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0, "kenv");
|
||||
ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0, "kenv");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
const char* ffdsConnectWayland(FFDisplayServerResult* result);
|
||||
|
||||
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result);
|
||||
const char* ffdsConnectXcb(FFDisplayServerResult* result);
|
||||
|
||||
const char* ffdsConnectXrandr(FFDisplayServerResult* result);
|
||||
const char* ffdsConnectXlib(FFDisplayServerResult* result);
|
||||
|
||||
const char* ffdsConnectDrm(FFDisplayServerResult* result);
|
||||
|
||||
void ffdsDetectWMDE(FFDisplayServerResult* result);
|
||||
|
||||
@@ -84,6 +84,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
|
||||
width, height,
|
||||
refreshRate,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0,
|
||||
0,
|
||||
&name,
|
||||
ffdsGetDisplayType(plainName),
|
||||
@@ -218,12 +220,14 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetConnectorCurrent)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetCrtc)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetEncoder)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetFB)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetProperty)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetPropertyBlob)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeResources)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeCrtc)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeEncoder)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeConnector)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeEncoder)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeFB)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeProperty)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreePropertyBlob)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
|
||||
@@ -252,28 +256,29 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
FF_AUTO_CLOSE_FD int primaryFd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (primaryFd < 0)
|
||||
continue;
|
||||
|
||||
drmModeRes* res = ffdrmModeGetResources(fd);
|
||||
drmModeRes* res = ffdrmModeGetResources(primaryFd);
|
||||
if (!res)
|
||||
continue;
|
||||
|
||||
for (int iConn = 0; iConn < res->count_connectors; ++iConn)
|
||||
{
|
||||
drmModeConnector* conn = ffdrmModeGetConnectorCurrent(fd, res->connectors[iConn]);
|
||||
drmModeConnector* conn = ffdrmModeGetConnectorCurrent(primaryFd, res->connectors[iConn]);
|
||||
if (!conn)
|
||||
continue;
|
||||
|
||||
if (conn->connection != DRM_MODE_DISCONNECTED)
|
||||
{
|
||||
drmModeEncoder* encoder = ffdrmModeGetEncoder(fd, conn->encoder_id);
|
||||
drmModeEncoder* encoder = ffdrmModeGetEncoder(primaryFd, conn->encoder_id);
|
||||
uint32_t width = 0, height = 0, refreshRate = 0;
|
||||
uint8_t bitDepth = 0;
|
||||
|
||||
if (encoder)
|
||||
{
|
||||
drmModeCrtc* crtc = ffdrmModeGetCrtc(fd, encoder->crtc_id);
|
||||
drmModeCrtc* crtc = ffdrmModeGetCrtc(primaryFd, encoder->crtc_id);
|
||||
if (crtc)
|
||||
{
|
||||
width = crtc->mode.hdisplay;
|
||||
@@ -292,28 +297,42 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFBPtr fb = ffdrmModeGetFB(primaryFd, crtc->buffer_id);
|
||||
if (fb)
|
||||
{
|
||||
bitDepth = (uint8_t) (fb->depth / 3);
|
||||
ffdrmModeFreeFB(fb);
|
||||
}
|
||||
|
||||
ffdrmModeFreeCrtc(crtc);
|
||||
}
|
||||
|
||||
ffdrmModeFreeEncoder(encoder);
|
||||
}
|
||||
|
||||
uint32_t preferredWidth = 0, preferredHeight = 0, preferredRefreshRate = 0;
|
||||
|
||||
for (int iMode = 0; iMode < conn->count_modes; ++iMode)
|
||||
{
|
||||
drmModeModeInfo* mode = &conn->modes[iMode];
|
||||
|
||||
if (mode->type & DRM_MODE_TYPE_PREFERRED)
|
||||
{
|
||||
preferredWidth = mode->hdisplay;
|
||||
preferredHeight = mode->vdisplay;
|
||||
preferredRefreshRate = mode->vrefresh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// NVIDIA DRM driver seems incomplete and conn->encoder_id == 0
|
||||
// Assume preferred resolution is used as what we do in drmParseSys
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
// NVIDIA DRM driver seems incomplete and conn->encoder_id == 0
|
||||
// Assume preferred resolution is used as what we do in drmParseSys
|
||||
for (int iMode = 0; iMode < conn->count_modes; ++iMode)
|
||||
{
|
||||
drmModeModeInfo* mode = &conn->modes[iMode];
|
||||
|
||||
if (mode->type & DRM_MODE_TYPE_PREFERRED)
|
||||
{
|
||||
width = mode->hdisplay;
|
||||
height = mode->vdisplay;
|
||||
refreshRate = mode->vrefresh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
width = preferredWidth;
|
||||
height = preferredHeight;
|
||||
refreshRate = preferredRefreshRate;
|
||||
}
|
||||
|
||||
|
||||
@@ -324,7 +343,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
|
||||
for (int iProp = 0; iProp < conn->count_props; ++iProp)
|
||||
{
|
||||
drmModePropertyRes *prop = ffdrmModeGetProperty(fd, conn->props[iProp]);
|
||||
drmModePropertyRes *prop = ffdrmModeGetProperty(primaryFd, conn->props[iProp]);
|
||||
if (!prop)
|
||||
continue;
|
||||
|
||||
@@ -334,9 +353,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
drmModePropertyBlobPtr blob = NULL;
|
||||
|
||||
if (prop->count_blobs > 0 && prop->blob_ids != NULL)
|
||||
blob = ffdrmModeGetPropertyBlob(fd, prop->blob_ids[0]);
|
||||
blob = ffdrmModeGetPropertyBlob(primaryFd, prop->blob_ids[0]);
|
||||
else
|
||||
blob = ffdrmModeGetPropertyBlob(fd, (uint32_t) conn->prop_values[iProp]);
|
||||
blob = ffdrmModeGetPropertyBlob(primaryFd, (uint32_t) conn->prop_values[iProp]);
|
||||
|
||||
if (blob)
|
||||
{
|
||||
@@ -382,6 +401,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
refreshRate,
|
||||
0,
|
||||
0,
|
||||
preferredWidth,
|
||||
preferredHeight,
|
||||
preferredRefreshRate,
|
||||
0,
|
||||
&name,
|
||||
conn->connector_type == DRM_MODE_CONNECTOR_eDP || conn->connector_type == DRM_MODE_CONNECTOR_LVDS
|
||||
@@ -401,6 +423,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
item->serial = serial;
|
||||
item->manufactureYear = myear;
|
||||
item->manufactureWeek = mweak;
|
||||
item->bitDepth = bitDepth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,20 @@
|
||||
|
||||
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||
return;
|
||||
|
||||
WaylandDisplay* display = data;
|
||||
display->width = width;
|
||||
display->height = height;
|
||||
display->refreshRate = refreshRate;
|
||||
|
||||
if (flags & WL_OUTPUT_MODE_CURRENT)
|
||||
{
|
||||
display->width = width;
|
||||
display->height = height;
|
||||
display->refreshRate = refreshRate;
|
||||
}
|
||||
if (flags & WL_OUTPUT_MODE_PREFERRED)
|
||||
{
|
||||
display->preferredWidth = width;
|
||||
display->preferredHeight = height;
|
||||
display->preferredRefreshRate = refreshRate;
|
||||
}
|
||||
}
|
||||
|
||||
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
|
||||
@@ -79,9 +86,6 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
|
||||
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
@@ -118,6 +122,9 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
(uint32_t) display.preferredWidth,
|
||||
(uint32_t) display.preferredHeight,
|
||||
display.preferredRefreshRate / 1000.0,
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
|
||||
@@ -11,26 +11,33 @@ typedef struct WaylandKdeMode
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
bool preferred;
|
||||
struct kde_output_device_mode_v2* pMode;
|
||||
} WaylandKdeMode;
|
||||
|
||||
static void waylandKdeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height)
|
||||
static void waylandKdeModeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height)
|
||||
{
|
||||
WaylandKdeMode* mode = (WaylandKdeMode*) data;
|
||||
mode->width = width;
|
||||
mode->height = height;
|
||||
}
|
||||
|
||||
static void waylandKdeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate)
|
||||
static void waylandKdeModeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate)
|
||||
{
|
||||
WaylandKdeMode* mode = (WaylandKdeMode*) data;
|
||||
mode->refreshRate = rate;
|
||||
}
|
||||
|
||||
static void waylandKdeModePreferredListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_)
|
||||
{
|
||||
WaylandKdeMode* mode = (WaylandKdeMode*) data;
|
||||
mode->preferred = true;
|
||||
}
|
||||
|
||||
static const struct kde_output_device_mode_v2_listener modeListener = {
|
||||
.size = waylandKdeSizeListener,
|
||||
.refresh = waylandKdeRefreshListener,
|
||||
.preferred = (void*) stubListener,
|
||||
.size = waylandKdeModeSizeListener,
|
||||
.refresh = waylandKdeModeRefreshListener,
|
||||
.preferred = waylandKdeModePreferredListener,
|
||||
.removed = (void*) stubListener,
|
||||
};
|
||||
|
||||
@@ -40,7 +47,7 @@ static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output
|
||||
if (!wldata->internal) return;
|
||||
|
||||
WaylandKdeMode* newMode = ffListAdd((FFlist*) wldata->internal);
|
||||
newMode->pMode = mode;
|
||||
*newMode = (WaylandKdeMode) { .pMode = mode };
|
||||
|
||||
// Strangely, the listener is called only in this function, but not in `waylandKdeCurrentModeListener`
|
||||
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
|
||||
@@ -52,18 +59,24 @@ static void waylandKdeCurrentModeListener(void* data, FF_MAYBE_UNUSED struct kde
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
if (!wldata->internal) return;
|
||||
|
||||
WaylandKdeMode* current = NULL;
|
||||
int set = 0;
|
||||
FF_LIST_FOR_EACH(WaylandKdeMode, m, *(FFlist*) wldata->internal)
|
||||
{
|
||||
if (m->pMode == mode)
|
||||
{
|
||||
current = m;
|
||||
break;
|
||||
wldata->width = m->width;
|
||||
wldata->height = m->height;
|
||||
wldata->refreshRate = m->refreshRate;
|
||||
if (++set == 2) break;
|
||||
}
|
||||
if (m->preferred)
|
||||
{
|
||||
wldata->preferredWidth = m->width;
|
||||
wldata->preferredHeight = m->height;
|
||||
wldata->preferredRefreshRate = m->refreshRate;
|
||||
if (++set == 2) break;
|
||||
}
|
||||
}
|
||||
wldata->width = current->width;
|
||||
wldata->height = current->height;
|
||||
wldata->refreshRate = current->refreshRate;
|
||||
}
|
||||
|
||||
static void waylandKdeScaleListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, wl_fixed_t scale)
|
||||
@@ -113,10 +126,7 @@ static void waylandKdeNameListener(void* data, FF_MAYBE_UNUSED struct kde_output
|
||||
WaylandDisplay* display = data;
|
||||
display->type = ffdsGetDisplayType(name);
|
||||
// As display->id is used as an internal identifier, we don't need it to be NUL terminated
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
strncpy((char*) &display->id, name, sizeof(display->id));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
ffStrbufAppendS(&display->name, name);
|
||||
}
|
||||
@@ -164,9 +174,6 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry,
|
||||
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandKdeMode));
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
@@ -191,6 +198,9 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
(uint32_t) display.preferredWidth,
|
||||
(uint32_t) display.preferredHeight,
|
||||
display.preferredRefreshRate / 1000.0,
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
|
||||
@@ -18,10 +18,18 @@
|
||||
#include "kde-output-order-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#if __FreeBSD__
|
||||
#include <sys/un.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
struct ucred ucred;
|
||||
#if __linux__ || (__FreeBSD__ && !__DragonFly__)
|
||||
|
||||
#if __linux
|
||||
struct ucred ucred = {};
|
||||
socklen_t len = sizeof(ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1 || ucred.pid <= 0)
|
||||
return false;
|
||||
@@ -30,6 +38,19 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
|
||||
if (!ffReadFileBuffer(procPath.chars, &result->wmProcessName))
|
||||
return false;
|
||||
#else
|
||||
struct xucred ucred = {};
|
||||
socklen_t len = sizeof(ucred);
|
||||
if (getsockopt(fd, AF_UNSPEC, LOCAL_PEERCRED, &ucred, &len) == -1 || ucred.cr_pid <= 0)
|
||||
return false;
|
||||
|
||||
size_t size = 4096;
|
||||
ffStrbufEnsureFixedLengthFree(&result->wmProcessName, (uint32_t) size);
|
||||
|
||||
if(sysctl((int[]){CTL_KERN, KERN_PROC, KERN_PROC_ARGS, ucred.cr_pid}, 4, result->wmProcessName.chars, &size, NULL, 0 ) != 0)
|
||||
return false;
|
||||
result->wmProcessName.length = (uint32_t) size - 1;
|
||||
#endif
|
||||
|
||||
// #1135: wl-restart is a special case
|
||||
const char* filename = strrchr(result->wmProcessName.chars, '/');
|
||||
@@ -39,20 +60,18 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
filename = result->wmProcessName.chars;
|
||||
|
||||
if (ffStrEquals(filename, "wl-restart"))
|
||||
ffStrbufSubstrAfterFirstC(&result->wmProcessName, '\0');
|
||||
ffStrbufSubstrAfterLastC(&result->wmProcessName, '\0');
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
|
||||
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_UNUSED(fd, result);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
{
|
||||
@@ -83,7 +102,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchDrmConnector(const char* connName, WaylandDisplay* wldata)
|
||||
static FF_MAYBE_UNUSED bool matchDrmConnector(const char* connName, WaylandDisplay* wldata)
|
||||
{
|
||||
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name
|
||||
// The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc."
|
||||
@@ -129,8 +148,10 @@ void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const
|
||||
if (display->id) return;
|
||||
|
||||
display->type = ffdsGetDisplayType(name);
|
||||
#if __linux__
|
||||
if (!display->edidName.length)
|
||||
matchDrmConnector(name, display);
|
||||
#endif
|
||||
display->id = ffWaylandGenerateIdFromName(name);
|
||||
ffStrbufAppendS(&display->name, name);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,12 @@ typedef struct WaylandDisplay
|
||||
WaylandData* parent;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
int32_t preferredWidth;
|
||||
int32_t preferredHeight;
|
||||
int32_t preferredRefreshRate;
|
||||
int32_t physicalWidth;
|
||||
int32_t physicalHeight;
|
||||
int32_t refreshRate;
|
||||
double scale;
|
||||
enum wl_output_transform transform;
|
||||
FFDisplayType type;
|
||||
|
||||
@@ -20,34 +20,43 @@ typedef struct WaylandZwlrMode
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
bool preferred;
|
||||
struct zwlr_output_mode_v1* pMode;
|
||||
} WaylandZwlrMode;
|
||||
|
||||
static void waylandZwlrSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t width, int32_t height)
|
||||
static void waylandZwlrModeSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t width, int32_t height)
|
||||
{
|
||||
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
|
||||
mode->width = width;
|
||||
mode->height = height;
|
||||
}
|
||||
|
||||
static void waylandZwlrRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t rate)
|
||||
static void waylandZwlrModeRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t rate)
|
||||
{
|
||||
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
|
||||
mode->refreshRate = rate;
|
||||
}
|
||||
|
||||
static void waylandZwlrModePreferredListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1)
|
||||
{
|
||||
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
|
||||
mode->preferred = true;
|
||||
}
|
||||
|
||||
static const struct zwlr_output_mode_v1_listener modeListener = {
|
||||
.size = waylandZwlrSizeListener,
|
||||
.refresh = waylandZwlrRefreshListener,
|
||||
.preferred = (void*) stubListener,
|
||||
.size = waylandZwlrModeSizeListener,
|
||||
.refresh = waylandZwlrModeRefreshListener,
|
||||
.preferred = waylandZwlrModePreferredListener,
|
||||
.finished = (void*) stubListener,
|
||||
};
|
||||
|
||||
static void waylandZwlrModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, struct zwlr_output_mode_v1 *mode)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
if (!wldata->internal) return;
|
||||
|
||||
WaylandZwlrMode* newMode = ffListAdd((FFlist*) wldata->internal);
|
||||
newMode->pMode = mode;
|
||||
*newMode = (WaylandZwlrMode) { .pMode = mode };
|
||||
|
||||
// Strangely, the listener is called only in this function, but not in `waylandZwlrCurrentModeListener`
|
||||
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
|
||||
@@ -57,18 +66,26 @@ static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zw
|
||||
{
|
||||
// waylandZwlrModeListener is always run before this
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
WaylandZwlrMode* current = NULL;
|
||||
if (!wldata->internal) return;
|
||||
|
||||
int set = 0;
|
||||
FF_LIST_FOR_EACH(WaylandZwlrMode, m, *(FFlist*) wldata->internal)
|
||||
{
|
||||
if (m->pMode == mode)
|
||||
{
|
||||
current = m;
|
||||
break;
|
||||
wldata->width = m->width;
|
||||
wldata->height = m->height;
|
||||
wldata->refreshRate = m->refreshRate;
|
||||
if (++set == 2) break;
|
||||
}
|
||||
if (m->preferred)
|
||||
{
|
||||
wldata->preferredWidth = m->width;
|
||||
wldata->preferredHeight = m->height;
|
||||
wldata->preferredRefreshRate = m->refreshRate;
|
||||
if (++set == 2) break;
|
||||
}
|
||||
}
|
||||
wldata->width = current->width;
|
||||
wldata->height = current->height;
|
||||
wldata->refreshRate = current->refreshRate;
|
||||
}
|
||||
|
||||
static void waylandZwlrPhysicalSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, int32_t width, int32_t height)
|
||||
@@ -78,12 +95,18 @@ static void waylandZwlrPhysicalSizeListener(void* data, FF_MAYBE_UNUSED struct z
|
||||
wldata->physicalHeight = height;
|
||||
}
|
||||
|
||||
static void waylandZwlrEnabledListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, bool enabled)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
if (!enabled) wldata->internal = NULL;
|
||||
}
|
||||
|
||||
static const struct zwlr_output_head_v1_listener headListener = {
|
||||
.name = (void*) ffWaylandOutputNameListener,
|
||||
.description = (void*) ffWaylandOutputDescriptionListener,
|
||||
.physical_size = waylandZwlrPhysicalSizeListener,
|
||||
.mode = waylandZwlrModeListener,
|
||||
.enabled = (void*) stubListener,
|
||||
.enabled = (void*) waylandZwlrEnabledListener,
|
||||
.current_mode = waylandZwlrCurrentModeListener,
|
||||
.position = (void*) stubListener,
|
||||
.transform = waylandZwlrTransformListener,
|
||||
@@ -102,9 +125,6 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
|
||||
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandZwlrMode));
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
@@ -117,7 +137,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
|
||||
wldata->ffwl_proxy_add_listener((struct wl_proxy*) head, (void(**)(void)) &headListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
if(display.width <= 0 || display.height <= 0 || !display.internal)
|
||||
return;
|
||||
|
||||
uint32_t rotation = ffWaylandHandleRotation(&display);
|
||||
@@ -128,6 +148,9 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale + 0.5),
|
||||
(uint32_t) (display.height / display.scale + 0.5),
|
||||
(uint32_t) display.preferredWidth,
|
||||
(uint32_t) display.preferredHeight,
|
||||
display.preferredRefreshRate / 1000.0,
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
|
||||
@@ -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 &&
|
||||
@@ -126,8 +129,14 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name)
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_ICEWM);
|
||||
else if(ffStrEqualsIgnCase(name, "dtwm"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DTWM);
|
||||
else if(ffStrEqualsIgnCase(name, "fvwm"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_FVWM);
|
||||
else if(ffStrEqualsIgnCase(name, "ctwm"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_CTWM);
|
||||
else if(ffStrEqualsIgnCase(name, "hyprland"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_HYPRLAND);
|
||||
else if(ffStrEqualsIgnCase(name, "ratpoison"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_RATPOISON);
|
||||
}
|
||||
|
||||
static void applyNameIfWM(FFDisplayServerResult* result, const char* processName)
|
||||
@@ -296,10 +305,10 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if(result->dePrettyName.length == 0)
|
||||
applyPrettyNameIfDE(result, proc->p_comm);
|
||||
applyPrettyNameIfDE(result, proc[i].p_comm);
|
||||
|
||||
if(result->wmPrettyName.length == 0)
|
||||
applyNameIfWM(result, proc->p_comm);
|
||||
applyNameIfWM(result, proc[i].p_comm);
|
||||
|
||||
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
|
||||
break;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#ifdef FF_HAVE_XCB
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/time.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
typedef struct XcbPropertyData
|
||||
@@ -82,72 +86,6 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect
|
||||
ffStrbufSetS(&result->wmProcessName, wmName);
|
||||
}
|
||||
|
||||
const char* ffdsConnectXcb(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xcb, "dlopen lbxcb failed", "libxcb" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcb, xcb_connect)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcb, xcb_get_setup)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcb, xcb_setup_roots_iterator)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcb, xcb_screen_next)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcb, xcb_disconnect)
|
||||
|
||||
XcbPropertyData propertyData;
|
||||
bool propertyDataInitialized = xcbInitPropertyData(xcb, &propertyData);
|
||||
|
||||
xcb_connection_t* connection = ffxcb_connect(NULL, NULL);
|
||||
if(connection == NULL)
|
||||
return "xcb_connect failed";
|
||||
|
||||
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(connection));
|
||||
|
||||
if(iterator.rem > 0 && propertyDataInitialized)
|
||||
xcbDetectWMfromEWMH(&propertyData, connection, iterator.data->root, result);
|
||||
|
||||
while(iterator.rem > 0)
|
||||
{
|
||||
xcb_screen_t* screen = iterator.data;
|
||||
ffdsAppendDisplay(result,
|
||||
(uint32_t) screen->width_in_pixels,
|
||||
(uint32_t) screen->height_in_pixels,
|
||||
0,
|
||||
(uint32_t) screen->width_in_pixels,
|
||||
(uint32_t) screen->height_in_pixels,
|
||||
0,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
0,
|
||||
(uint32_t) screen->width_in_millimeters,
|
||||
(uint32_t) screen->height_in_millimeters,
|
||||
"xcb"
|
||||
);
|
||||
ffxcb_screen_next(&iterator);
|
||||
}
|
||||
|
||||
ffxcb_disconnect(connection);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffdsConnectXcb(FFDisplayServerResult* result)
|
||||
{
|
||||
//Do nothing. There are other implementations coming
|
||||
FF_UNUSED(result)
|
||||
return "Fastfetch was compiled without XCB support";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
#include "util/edidHelper.h"
|
||||
#include <xcb/randr.h>
|
||||
|
||||
typedef struct XcbRandrData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_current)
|
||||
@@ -181,28 +119,6 @@ typedef struct XcbRandrData
|
||||
xcb_randr_get_screen_resources_current_reply_t* screenResources;
|
||||
} XcbRandrData;
|
||||
|
||||
static double xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode)
|
||||
{
|
||||
//We do the check here, because we want the best fallback display if this call failed
|
||||
if(data->screenResources == NULL)
|
||||
return 0;
|
||||
|
||||
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources);
|
||||
|
||||
while(modesIterator.rem > 0)
|
||||
{
|
||||
if(modesIterator.data->id == mode)
|
||||
{
|
||||
xcb_randr_mode_info_t* modeInfo = modesIterator.data;
|
||||
return (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal);
|
||||
}
|
||||
|
||||
data->ffxcb_randr_mode_info_next(&modesIterator);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength)
|
||||
{
|
||||
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME);
|
||||
@@ -227,13 +143,38 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
|
||||
break;
|
||||
}
|
||||
|
||||
xcb_randr_mode_info_t* currentMode = NULL;
|
||||
xcb_randr_mode_info_t* preferredMode = NULL;
|
||||
|
||||
if(data->screenResources)
|
||||
{
|
||||
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources);
|
||||
|
||||
if (output->num_preferred > 0)
|
||||
preferredMode = modesIterator.data;
|
||||
|
||||
while (modesIterator.rem > 0)
|
||||
{
|
||||
if (modesIterator.data->id == crtcInfoReply->mode)
|
||||
{
|
||||
currentMode = modesIterator.data;
|
||||
break;
|
||||
}
|
||||
|
||||
data->ffxcb_randr_mode_info_next(&modesIterator);
|
||||
}
|
||||
}
|
||||
|
||||
FFDisplayResult* item = ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
xcbRandrHandleMode(data, crtcInfoReply->mode),
|
||||
currentMode ? (double) currentMode->dot_clock / (double) ((uint32_t) currentMode->htotal * currentMode->vtotal) : 0,
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
preferredMode ? (uint32_t) preferredMode->width : 0,
|
||||
preferredMode ? (uint32_t) preferredMode->height : 0,
|
||||
preferredMode ? (double) preferredMode->dot_clock / (double) ((uint32_t) preferredMode->htotal * preferredMode->vtotal) : 0,
|
||||
rotation,
|
||||
name,
|
||||
displayType,
|
||||
@@ -247,7 +188,6 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
|
||||
{
|
||||
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
|
||||
ffEdidGetPhysicalSize(edidData, &item->physicalWidth, &item->physicalHeight);
|
||||
}
|
||||
|
||||
return !!item;
|
||||
@@ -323,6 +263,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
|
||||
0,
|
||||
(uint32_t) monitor->width,
|
||||
(uint32_t) monitor->height,
|
||||
0, 0, 0,
|
||||
0,
|
||||
&name,
|
||||
displayType,
|
||||
@@ -378,6 +319,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
|
||||
0,
|
||||
(uint32_t) screen->width_in_pixels,
|
||||
(uint32_t) screen->height_in_pixels,
|
||||
0, 0, 0,
|
||||
0,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include "displayserver_linux.h"
|
||||
|
||||
#ifdef FF_HAVE_X11
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
typedef struct X11PropertyData
|
||||
@@ -58,66 +62,6 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl
|
||||
data->ffXFree(wmWindow);
|
||||
}
|
||||
|
||||
const char* ffdsConnectXlib(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(x11, "dlopen libX11 failed", "libX11" FF_LIBRARY_EXTENSION, 7, "libX11-xcb" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(x11, XOpenDisplay)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(x11, XCloseDisplay)
|
||||
|
||||
X11PropertyData propertyData;
|
||||
bool propertyDataInitialized = x11InitPropertyData(x11, &propertyData);
|
||||
|
||||
Display* display = ffXOpenDisplay(x11);
|
||||
if(display == NULL)
|
||||
return "XOpenDisplay failed";
|
||||
|
||||
if(propertyDataInitialized && ScreenCount(display) > 0)
|
||||
x11DetectWMFromEWMH(&propertyData, display, result);
|
||||
|
||||
for(int i = 0; i < ScreenCount(display); i++)
|
||||
{
|
||||
Screen* screen = ScreenOfDisplay(display, i);
|
||||
ffdsAppendDisplay(result,
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
0,
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
0,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
0,
|
||||
(uint32_t) WidthMMOfScreen(screen),
|
||||
(uint32_t) HeightMMOfScreen(screen),
|
||||
"xlib"
|
||||
);
|
||||
}
|
||||
|
||||
ffXCloseDisplay(display);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffdsConnectXlib(FFDisplayServerResult* result)
|
||||
{
|
||||
//Do nothing. WM / DE detection will use environment vars to detect as much as possible.
|
||||
FF_UNUSED(result);
|
||||
return "Fastfetch was compiled without libX11 support";
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_X11
|
||||
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
#include "util/edidHelper.h"
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
typedef struct XrandrData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(XInternAtom)
|
||||
@@ -141,19 +85,6 @@ typedef struct XrandrData
|
||||
XRRScreenResources* screenResources;
|
||||
} XrandrData;
|
||||
|
||||
static double xrandrHandleMode(XrandrData* data, RRMode mode)
|
||||
{
|
||||
for(int i = 0; i < data->screenResources->nmode; i++)
|
||||
{
|
||||
if(data->screenResources->modes[i].id == mode)
|
||||
{
|
||||
XRRModeInfo* modeInfo = &data->screenResources->modes[i];
|
||||
return (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength)
|
||||
{
|
||||
//We do the check here, because we want the best fallback display if this call failed
|
||||
@@ -181,13 +112,31 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
|
||||
break;
|
||||
}
|
||||
|
||||
XRRModeInfo* currentMode = NULL;
|
||||
if (data->screenResources)
|
||||
{
|
||||
for(int i = 0; i < data->screenResources->nmode; i++)
|
||||
{
|
||||
if(data->screenResources->modes[i].id == crtcInfo->mode)
|
||||
{
|
||||
currentMode = &data->screenResources->modes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XRRModeInfo* preferredMode = data->screenResources && output->npreferred > 0 ? &data->screenResources->modes[0] : NULL;
|
||||
|
||||
FFDisplayResult* item = ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) crtcInfo->width,
|
||||
(uint32_t) crtcInfo->height,
|
||||
xrandrHandleMode(data, crtcInfo->mode),
|
||||
currentMode ? (double) currentMode->dotClock / (double) ((uint32_t) currentMode->hTotal * currentMode->vTotal) : 0,
|
||||
(uint32_t) crtcInfo->width,
|
||||
(uint32_t) crtcInfo->height,
|
||||
preferredMode ? (uint32_t) preferredMode->width : 0,
|
||||
preferredMode ? (uint32_t) preferredMode->height : 0,
|
||||
preferredMode ? (double) preferredMode->dotClock / (double) ((uint32_t) preferredMode->hTotal * preferredMode->vTotal) : 0,
|
||||
rotation,
|
||||
name,
|
||||
displayType,
|
||||
@@ -202,7 +151,6 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
|
||||
{
|
||||
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
|
||||
ffEdidGetPhysicalSize(edidData, &item->physicalWidth, &item->physicalHeight);
|
||||
}
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
@@ -264,6 +212,7 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
0,
|
||||
(uint32_t) monitorInfo->width,
|
||||
(uint32_t) monitorInfo->height,
|
||||
0, 0, 0,
|
||||
0,
|
||||
&name,
|
||||
displayType,
|
||||
@@ -315,6 +264,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
0,
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
0, 0, 0,
|
||||
0,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
|
||||
@@ -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);
|
||||
@@ -536,27 +536,27 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
.name = &gpu->name,
|
||||
}, soName);
|
||||
}
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <paths.h>
|
||||
#include <paths.h>
|
||||
#ifndef _PATH_LOCALBASE
|
||||
#define _PATH_LOCALBASE "/usr/local"
|
||||
#endif
|
||||
#elif __OpenBSD__
|
||||
#define _PATH_LOCALBASE "/usr/local"
|
||||
#elif __NetBSD__
|
||||
#define _PATH_LOCALBASE "/usr/pkg"
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_EMBEDDED_PCIIDS
|
||||
@@ -37,17 +41,10 @@ static const FFstrbuf* loadPciIds()
|
||||
if (pciids.length == 0)
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids);
|
||||
}
|
||||
#elif __FreeBSD__
|
||||
// https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h
|
||||
#elif __FreeBSD__ || __OpenBSD__ || __NetBSD__
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids);
|
||||
if (pciids.length == 0)
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", &pciids);
|
||||
#elif __sun
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
|
||||
#elif __OpenBSD__
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/local/share/pci.ids", &pciids);
|
||||
#elif __NetBSD__
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/pkg/share/pciutils/pci.ids", &pciids);
|
||||
#endif
|
||||
|
||||
#endif // FF_CUSTOM_PCI_IDS_PATH
|
||||
|
||||
@@ -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))
|
||||
|
||||
+20
-26
@@ -4,10 +4,8 @@
|
||||
// THIS FILE IS CREATED FROM SCRATCH, BY READING THE OFFICIAL MTML API
|
||||
// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT.
|
||||
|
||||
#define MTML_API __attribute__((visibility("default")))
|
||||
#define MTML_DEVICE_PCI_SBDF_BUFFER_SIZE 32
|
||||
#define MTML_DEVICE_NAME_BUFFER_SIZE 32
|
||||
#define MTML_DEVICE_UUID_BUFFER_SIZE 48
|
||||
|
||||
/**
|
||||
* Return values for MTML API calls.
|
||||
@@ -23,10 +21,6 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
MTML_BRAND_MTT = 0, //!< MTT series.
|
||||
MTML_BRAND_UNKNOWN, //!< An unknown brand.
|
||||
|
||||
// Keep this on the last line.
|
||||
MTML_BRAND_COUNT //!< The number of brands.
|
||||
} MtmlBrandType;
|
||||
|
||||
typedef struct MtmlLibrary MtmlLibrary;
|
||||
@@ -57,62 +51,62 @@ typedef struct
|
||||
} MtmlPciInfo;
|
||||
|
||||
// Retrieves the number of cores of a device.
|
||||
MtmlReturn MTML_API mtmlDeviceCountGpuCores(const MtmlDevice* device, unsigned int* numCores);
|
||||
MtmlReturn mtmlDeviceCountGpuCores(const MtmlDevice* device, unsigned int* numCores);
|
||||
// Retrieves the brand of a device.
|
||||
MtmlReturn MTML_API mtmlDeviceGetBrand(const MtmlDevice *dev, MtmlBrandType *type);
|
||||
MtmlReturn mtmlDeviceGetBrand(const MtmlDevice *dev, MtmlBrandType *type);
|
||||
// Retrieves the index associated with the specified device.
|
||||
MtmlReturn MTML_API mtmlDeviceGetIndex(const MtmlDevice *dev, unsigned int *index);
|
||||
MtmlReturn mtmlDeviceGetIndex(const MtmlDevice *dev, unsigned int *index);
|
||||
// Retrieves the name of a device.
|
||||
MtmlReturn MTML_API mtmlDeviceGetName(const MtmlDevice *dev, char *name, unsigned int length);
|
||||
MtmlReturn mtmlDeviceGetName(const MtmlDevice *dev, char *name, unsigned int length);
|
||||
// Retrieves the PCI attributes of a device.
|
||||
MtmlReturn MTML_API mtmlDeviceGetPciInfo(const MtmlDevice *dev, MtmlPciInfo *pci);
|
||||
MtmlReturn mtmlDeviceGetPciInfo(const MtmlDevice *dev, MtmlPciInfo *pci);
|
||||
/**
|
||||
* Retrieves the UUID of a specified device. The UUID is a hexadecimal string in the
|
||||
* form of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where each 'x' is an ASCII character that represents a hexadecimal
|
||||
* digit. The UUID is globally unique for every single device thus can be used to identify different devices
|
||||
* physically.
|
||||
*/
|
||||
MtmlReturn MTML_API mtmlDeviceGetUUID(const MtmlDevice *dev, char *uuid, unsigned int length);
|
||||
MtmlReturn mtmlDeviceGetUUID(const MtmlDevice *dev, char *uuid, unsigned int length);
|
||||
// Initializes a GPU opaque object to represent a specific graphic core on the target device that is designated by its index.
|
||||
MtmlReturn MTML_API mtmlDeviceInitGpu(const MtmlDevice *dev, MtmlGpu **gpu);
|
||||
MtmlReturn mtmlDeviceInitGpu(const MtmlDevice *dev, MtmlGpu **gpu);
|
||||
// Initializes a memory opaque object to represent the memory on the target device.
|
||||
MtmlReturn MTML_API mtmlDeviceInitMemory(const MtmlDevice *dev, MtmlMemory **mem);
|
||||
MtmlReturn mtmlDeviceInitMemory(const MtmlDevice *dev, MtmlMemory **mem);
|
||||
|
||||
// Retrieves the maximum supported clock speed for the device's graphic core.
|
||||
MtmlReturn MTML_API mtmlGpuGetMaxClock(const MtmlGpu *gpu, unsigned int *clockMhz);
|
||||
MtmlReturn mtmlGpuGetMaxClock(const MtmlGpu *gpu, unsigned int *clockMhz);
|
||||
// Retrieves the current temperature readings for the device's graphic core, in degrees Celsius.
|
||||
MtmlReturn MTML_API mtmlGpuGetTemperature(const MtmlGpu *gpu, unsigned int *temp);
|
||||
MtmlReturn mtmlGpuGetTemperature(const MtmlGpu *gpu, unsigned int *temp);
|
||||
// Retrieves the current utilization rate for the device's graphic core.
|
||||
MtmlReturn MTML_API mtmlGpuGetUtilization(const MtmlGpu *gpu, unsigned int *utilization);
|
||||
MtmlReturn mtmlGpuGetUtilization(const MtmlGpu *gpu, unsigned int *utilization);
|
||||
|
||||
// Retrieves the number of devices that can be accessed by the library opaque object.
|
||||
MtmlReturn MTML_API mtmlLibraryCountDevice(const MtmlLibrary *lib, unsigned int *count);
|
||||
MtmlReturn mtmlLibraryCountDevice(const MtmlLibrary *lib, unsigned int *count);
|
||||
/**
|
||||
* Initializes a device opaque object to represent a device that is designated by its index.
|
||||
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
|
||||
*/
|
||||
MtmlReturn MTML_API mtmlLibraryInit(MtmlLibrary **lib);
|
||||
MtmlReturn mtmlLibraryInit(MtmlLibrary **lib);
|
||||
/**
|
||||
* Initializes a device opaque object to represent a device that is designated by its index.
|
||||
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
|
||||
*/
|
||||
MtmlReturn MTML_API mtmlLibraryInitDeviceByIndex(const MtmlLibrary *lib, unsigned int index, MtmlDevice **dev);
|
||||
MtmlReturn mtmlLibraryInitDeviceByIndex(const MtmlLibrary *lib, unsigned int index, MtmlDevice **dev);
|
||||
/**
|
||||
* Initializes a device opaque object to represent a device that is designated by its PCI Sbdf.
|
||||
* The PCI Sbdf format like 00000000:3a:00.0 refer to \ref MtmlPciInfo::sbdf.
|
||||
*/
|
||||
MtmlReturn MTML_API mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary *lib, const char *pciSbdf, MtmlDevice **dev);
|
||||
MtmlReturn mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary *lib, const char *pciSbdf, MtmlDevice **dev);
|
||||
// Initializes a MtmlSystem opaque pointer that is bound to a library opaque object.
|
||||
MtmlReturn MTML_API mtmlLibraryInitSystem(const MtmlLibrary *lib, MtmlSystem **sys);
|
||||
MtmlReturn mtmlLibraryInitSystem(const MtmlLibrary *lib, MtmlSystem **sys);
|
||||
/**
|
||||
* Shuts down the library opaque object that is previously initialized by \ref mtmlLibraryInit() and releases its resources.
|
||||
* The \a lib pointer cannot be used anymore after this function returns.
|
||||
*/
|
||||
MtmlReturn MTML_API mtmlLibraryShutDown(MtmlLibrary *lib);
|
||||
MtmlReturn mtmlLibraryShutDown(MtmlLibrary *lib);
|
||||
|
||||
// Retrieves the amount of total memory available on the device, in bytes.
|
||||
MtmlReturn MTML_API mtmlMemoryGetTotal(const MtmlMemory *mem, unsigned long long *total);
|
||||
MtmlReturn mtmlMemoryGetTotal(const MtmlMemory *mem, unsigned long long *total);
|
||||
// Retrieves the amount of used memory on the device, in bytes.
|
||||
MtmlReturn MTML_API mtmlMemoryGetUsed(const MtmlMemory *mem, unsigned long long *used);
|
||||
MtmlReturn mtmlMemoryGetUsed(const MtmlMemory *mem, unsigned long long *used);
|
||||
// Retrieves the current memory utilization rate for the device.
|
||||
MtmlReturn MTML_API mtmlMemoryGetUtilization(const MtmlMemory *mem, unsigned int *utilization);
|
||||
MtmlReturn mtmlMemoryGetUtilization(const MtmlMemory *mem, unsigned int *utilization);
|
||||
|
||||
@@ -13,4 +13,8 @@ typedef struct FFHostResult
|
||||
FFstrbuf vendor;
|
||||
} FFHostResult;
|
||||
|
||||
const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel);
|
||||
#ifdef __x86_64__
|
||||
bool ffHostDetectMac(FFHostResult* host);
|
||||
#endif
|
||||
const char* ffDetectHost(FFHostResult* host);
|
||||
|
||||
@@ -5,179 +5,6 @@
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static const char* getProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
{
|
||||
// Macbook Pro: https://support.apple.com/en-us/HT201300
|
||||
// Macbook Air: https://support.apple.com/en-us/HT201862
|
||||
// Mac mini: https://support.apple.com/en-us/HT201894
|
||||
// iMac: https://support.apple.com/en-us/HT201634
|
||||
// Mac Pro: https://support.apple.com/en-us/HT202888
|
||||
// Mac Studio: https://support.apple.com/en-us/HT213073
|
||||
|
||||
if(ffStrbufStartsWithS(hwModel, "MacBookPro"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBookPro");
|
||||
if(ffStrEquals(version, "18,3") ||
|
||||
ffStrEquals(version, "18,4")) return "MacBook Pro (14-inch, 2021)";
|
||||
if(ffStrEquals(version, "18,1") ||
|
||||
ffStrEquals(version, "18,2")) return "MacBook Pro (16-inch, 2021)";
|
||||
if(ffStrEquals(version, "17,1")) return "MacBook Pro (13-inch, M1, 2020)";
|
||||
if(ffStrEquals(version, "16,3")) return "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "16,2")) return "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "16,4") ||
|
||||
ffStrEquals(version, "16,1")) return "MacBook Pro (16-inch, 2019)";
|
||||
if(ffStrEquals(version, "15,4")) return "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (15-inch, 2019)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "15,1")) return "MacBook Pro (15-inch, 2018/2019)";
|
||||
if(ffStrEquals(version, "14,3")) return "MacBook Pro (15-inch, 2017)";
|
||||
if(ffStrEquals(version, "14,2")) return "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "14,1")) return "MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "13,3")) return "MacBook Pro (15-inch, 2016)";
|
||||
if(ffStrEquals(version, "13,2")) return "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "13,1")) return "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "12,1")) return "MacBook Pro (Retina, 13-inch, Early 2015)";
|
||||
if(ffStrEquals(version, "11,4") ||
|
||||
ffStrEquals(version, "11,5")) return "MacBook Pro (Retina, 15-inch, Mid 2015)";
|
||||
if(ffStrEquals(version, "11,2") ||
|
||||
ffStrEquals(version, "11,3")) return "MacBook Pro (Retina, 15-inch, Late 2013/Mid 2014)";
|
||||
if(ffStrEquals(version, "11,1")) return "MacBook Pro (Retina, 13-inch, Late 2013/Mid 2014)";
|
||||
if(ffStrEquals(version, "10,2")) return "MacBook Pro (Retina, 13-inch, Late 2012/Early 2013)";
|
||||
if(ffStrEquals(version, "10,1")) return "MacBook Pro (Retina, 15-inch, Mid 2012/Early 2013)";
|
||||
if(ffStrEquals(version, "9,2")) return "MacBook Pro (13-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "9,1")) return "MacBook Pro (15-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "8,3")) return "MacBook Pro (17-inch, 2011)";
|
||||
if(ffStrEquals(version, "8,2")) return "MacBook Pro (15-inch, 2011)";
|
||||
if(ffStrEquals(version, "8,1")) return "MacBook Pro (13-inch, 2011)";
|
||||
if(ffStrEquals(version, "7,1")) return "MacBook Pro (13-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "6,2")) return "MacBook Pro (15-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "6,1")) return "MacBook Pro (17-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "5,5")) return "MacBook Pro (13-inch, Mid 2009)";
|
||||
if(ffStrEquals(version, "5,3")) return "MacBook Pro (15-inch, Mid 2009)";
|
||||
if(ffStrEquals(version, "5,2")) return "MacBook Pro (17-inch, Mid/Early 2009)";
|
||||
if(ffStrEquals(version, "5,1")) return "MacBook Pro (15-inch, Late 2008)";
|
||||
if(ffStrEquals(version, "4,1")) return "MacBook Pro (17/15-inch, Early 2008)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "MacBookAir"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBookAir");
|
||||
if(ffStrEquals(version, "10,1")) return "MacBook Air (M1, 2020)";
|
||||
if(ffStrEquals(version, "9,1")) return "MacBook Air (Retina, 13-inch, 2020)";
|
||||
if(ffStrEquals(version, "8,2")) return "MacBook Air (Retina, 13-inch, 2019)";
|
||||
if(ffStrEquals(version, "8,1")) return "MacBook Air (Retina, 13-inch, 2018)";
|
||||
if(ffStrEquals(version, "7,2")) return "MacBook Air (13-inch, Early 2015/2017)";
|
||||
if(ffStrEquals(version, "7,1")) return "MacBook Air (11-inch, Early 2015)";
|
||||
if(ffStrEquals(version, "6,2")) return "MacBook Air (13-inch, Mid 2013/Early 2014)";
|
||||
if(ffStrEquals(version, "6,1")) return "MacBook Air (11-inch, Mid 2013/Early 2014)";
|
||||
if(ffStrEquals(version, "5,2")) return "MacBook Air (13-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "5,1")) return "MacBook Air (11-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "4,2")) return "MacBook Air (13-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "4,1")) return "MacBook Air (11-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "3,2")) return "MacBook Air (13-inch, Late 2010)";
|
||||
if(ffStrEquals(version, "3,1")) return "MacBook Air (11-inch, Late 2010)";
|
||||
if(ffStrEquals(version, "2,1")) return "MacBook Air (Mid 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "Macmini"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Macmini");
|
||||
if(ffStrEquals(version, "9,1")) return "Mac mini (M1, 2020)";
|
||||
if(ffStrEquals(version, "8,1")) return "Mac mini (2018)";
|
||||
if(ffStrEquals(version, "7,1")) return "Mac mini (Mid 2014)";
|
||||
if(ffStrEquals(version, "6,1") ||
|
||||
ffStrEquals(version, "6,2")) return "Mac mini (Late 2012)";
|
||||
if(ffStrEquals(version, "5,1") ||
|
||||
ffStrEquals(version, "5,2")) return "Mac mini (Mid 2011)";
|
||||
if(ffStrEquals(version, "4,1")) return "Mac mini (Mid 2010)";
|
||||
if(ffStrEquals(version, "3,1")) return "Mac mini (Early/Late 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "MacBook"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBook");
|
||||
if(ffStrEquals(version, "10,1")) return "MacBook (Retina, 12-inch, 2017)";
|
||||
if(ffStrEquals(version, "9,1")) return "MacBook (Retina, 12-inch, Early 2016)";
|
||||
if(ffStrEquals(version, "8,1")) return "MacBook (Retina, 12-inch, Early 2015)";
|
||||
if(ffStrEquals(version, "7,1")) return "MacBook (13-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "6,1")) return "MacBook (13-inch, Late 2009)";
|
||||
if(ffStrEquals(version, "5,2")) return "MacBook (13-inch, Early/Mid 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "MacPro"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacPro");
|
||||
if(ffStrEquals(version, "7,1")) return "Mac Pro (2019)";
|
||||
if(ffStrEquals(version, "6,1")) return "Mac Pro (Late 2013)";
|
||||
if(ffStrEquals(version, "5,1")) return "Mac Pro (Mid 2010 - Mid 2012)";
|
||||
if(ffStrEquals(version, "4,1")) return "Mac Pro (Early 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
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,7") ||
|
||||
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 4 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)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,4")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,5")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(ffStrEquals(version, "15,6") ||
|
||||
ffStrEquals(version, "15,8") ||
|
||||
ffStrEquals(version, "15,10")) return "MacBook Pro (14-inch, Nov 2023, Three Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "15,7") ||
|
||||
ffStrEquals(version, "15,9") ||
|
||||
ffStrEquals(version, "15,11")) return "MacBook Pro (16-inch, Nov 2023, Three Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,15")) return "MacBook Air (15-inch, M2, 2023)";
|
||||
if(ffStrEquals(version, "14,14")) return "Mac Studio (M2 Ultra, 2023, Two Thunderbolt 4 front ports)";
|
||||
if(ffStrEquals(version, "14,13")) return "Mac Studio (M2 Max, 2023, Two USB-C front ports)";
|
||||
if(ffStrEquals(version, "14,8")) return "Mac Pro (2023)";
|
||||
if(ffStrEquals(version, "14,6") ||
|
||||
ffStrEquals(version, "14,10")) return "MacBook Pro (16-inch, 2023)";
|
||||
if(ffStrEquals(version, "14,5") ||
|
||||
ffStrEquals(version, "14,9")) return "MacBook Pro (14-inch, 2023)";
|
||||
if(ffStrEquals(version, "14,3")) return "Mac mini (M2, 2023, Two Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,12")) return "Mac mini (M2, 2023, Four Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,7")) return "MacBook Pro (13-inch, M2, 2022)";
|
||||
if(ffStrEquals(version, "14,2")) return "MacBook Air (M2, 2022)";
|
||||
if(ffStrEquals(version, "13,1")) return "Mac Studio (M1 Max, 2022, Two USB-C front ports)";
|
||||
if(ffStrEquals(version, "13,2")) return "Mac Studio (M1 Ultra, 2022, Two Thunderbolt 4 front ports)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "iMac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("iMac");
|
||||
if(ffStrEquals(version, "21,1")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(ffStrEquals(version, "21,2")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "20,1") ||
|
||||
ffStrEquals(version, "20,2")) return "iMac (Retina 5K, 27-inch, 2020)";
|
||||
if(ffStrEquals(version, "19,1")) return "iMac (Retina 5K, 27-inch, 2019)";
|
||||
if(ffStrEquals(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(ffStrEquals(version, "Pro1,1")) return "iMac Pro (2017)";
|
||||
if(ffStrEquals(version, "18,3")) return "iMac (Retina 5K, 27-inch, 2017)";
|
||||
if(ffStrEquals(version, "18,2")) return "iMac (Retina 4K, 21.5-inch, 2017)";
|
||||
if(ffStrEquals(version, "18,1")) return "iMac (21.5-inch, 2017)";
|
||||
if(ffStrEquals(version, "17,1")) return "iMac (Retina 5K, 27-inch, Late 2015)";
|
||||
if(ffStrEquals(version, "16,2")) return "iMac (Retina 4K, 21.5-inch, Late 2015)";
|
||||
if(ffStrEquals(version, "16,1")) return "iMac (21.5-inch, Late 2015)";
|
||||
if(ffStrEquals(version, "15,1")) return "iMac (Retina 5K, 27-inch, Late 2014 - Mid 2015)";
|
||||
if(ffStrEquals(version, "14,4")) return "iMac (21.5-inch, Mid 2014)";
|
||||
if(ffStrEquals(version, "14,2")) return "iMac (27-inch, Late 2013)";
|
||||
if(ffStrEquals(version, "14,1")) return "iMac (21.5-inch, Late 2013)";
|
||||
if(ffStrEquals(version, "13,2")) return "iMac (27-inch, Late 2012)";
|
||||
if(ffStrEquals(version, "13,1")) return "iMac (21.5-inch, Late 2012)";
|
||||
if(ffStrEquals(version, "12,2")) return "iMac (27-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "12,1")) return "iMac (21.5-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "11,3")) return "iMac (27-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "11,2")) return "iMac (21.5-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "10,1")) return "iMac (27/21.5-inch, Late 2009)";
|
||||
if(ffStrEquals(version, "9,1")) return "iMac (24/20-inch, Early 2009)";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* getProductNameWithIokit(FFstrbuf* result)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("product"));
|
||||
@@ -217,7 +44,7 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
const char* error = ffSysctlGetString("hw.model", &host->family);
|
||||
if (error) return error;
|
||||
|
||||
ffStrbufSetStatic(&host->name, getProductNameWithHwModel(&host->family));
|
||||
ffStrbufSetStatic(&host->name, ffHostGetMacProductNameWithHwModel(&host->family));
|
||||
if (host->name.length == 0)
|
||||
getProductNameWithIokit(&host->name);
|
||||
if (host->name.length == 0)
|
||||
|
||||
@@ -19,5 +19,9 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.maker", &host->vendor);
|
||||
ffCleanUpSmbiosValue(&host->vendor);
|
||||
|
||||
#ifdef __x86_64__
|
||||
ffHostDetectMac(host);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
ffStrbufSetStatic(&host->vendor, "Apple Inc.");
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
ffHostDetectMac(host);
|
||||
#endif
|
||||
|
||||
//KVM/Qemu virtual machine
|
||||
if(ffStrbufStartsWithS(&host->name, "Standard PC"))
|
||||
ffStrbufPrependS(&host->name, "KVM/QEMU ");
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
#include "host.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
{
|
||||
// Macbook Pro: https://support.apple.com/en-us/HT201300
|
||||
// Macbook Air: https://support.apple.com/en-us/HT201862
|
||||
// Mac mini: https://support.apple.com/en-us/HT201894
|
||||
// iMac: https://support.apple.com/en-us/HT201634
|
||||
// Mac Pro: https://support.apple.com/en-us/HT202888
|
||||
// Mac Studio: https://support.apple.com/en-us/HT213073
|
||||
|
||||
if(ffStrbufStartsWithS(hwModel, "MacBookPro"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBookPro");
|
||||
if(ffStrEquals(version, "18,3") ||
|
||||
ffStrEquals(version, "18,4")) return "MacBook Pro (14-inch, 2021)";
|
||||
if(ffStrEquals(version, "18,1") ||
|
||||
ffStrEquals(version, "18,2")) return "MacBook Pro (16-inch, 2021)";
|
||||
if(ffStrEquals(version, "17,1")) return "MacBook Pro (13-inch, M1, 2020)";
|
||||
if(ffStrEquals(version, "16,3")) return "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "16,2")) return "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "16,4") ||
|
||||
ffStrEquals(version, "16,1")) return "MacBook Pro (16-inch, 2019)";
|
||||
if(ffStrEquals(version, "15,4")) return "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (15-inch, 2019)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "15,1")) return "MacBook Pro (15-inch, 2018/2019)";
|
||||
if(ffStrEquals(version, "14,3")) return "MacBook Pro (15-inch, 2017)";
|
||||
if(ffStrEquals(version, "14,2")) return "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "14,1")) return "MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "13,3")) return "MacBook Pro (15-inch, 2016)";
|
||||
if(ffStrEquals(version, "13,2")) return "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "13,1")) return "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)";
|
||||
if(ffStrEquals(version, "12,1")) return "MacBook Pro (Retina, 13-inch, Early 2015)";
|
||||
if(ffStrEquals(version, "11,4") ||
|
||||
ffStrEquals(version, "11,5")) return "MacBook Pro (Retina, 15-inch, Mid 2015)";
|
||||
if(ffStrEquals(version, "11,2") ||
|
||||
ffStrEquals(version, "11,3")) return "MacBook Pro (Retina, 15-inch, Late 2013/Mid 2014)";
|
||||
if(ffStrEquals(version, "11,1")) return "MacBook Pro (Retina, 13-inch, Late 2013/Mid 2014)";
|
||||
if(ffStrEquals(version, "10,2")) return "MacBook Pro (Retina, 13-inch, Late 2012/Early 2013)";
|
||||
if(ffStrEquals(version, "10,1")) return "MacBook Pro (Retina, 15-inch, Mid 2012/Early 2013)";
|
||||
if(ffStrEquals(version, "9,2")) return "MacBook Pro (13-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "9,1")) return "MacBook Pro (15-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "8,3")) return "MacBook Pro (17-inch, 2011)";
|
||||
if(ffStrEquals(version, "8,2")) return "MacBook Pro (15-inch, 2011)";
|
||||
if(ffStrEquals(version, "8,1")) return "MacBook Pro (13-inch, 2011)";
|
||||
if(ffStrEquals(version, "7,1")) return "MacBook Pro (13-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "6,2")) return "MacBook Pro (15-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "6,1")) return "MacBook Pro (17-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "5,5")) return "MacBook Pro (13-inch, Mid 2009)";
|
||||
if(ffStrEquals(version, "5,3")) return "MacBook Pro (15-inch, Mid 2009)";
|
||||
if(ffStrEquals(version, "5,2")) return "MacBook Pro (17-inch, Mid/Early 2009)";
|
||||
if(ffStrEquals(version, "5,1")) return "MacBook Pro (15-inch, Late 2008)";
|
||||
if(ffStrEquals(version, "4,1")) return "MacBook Pro (17/15-inch, Early 2008)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "MacBookAir"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBookAir");
|
||||
if(ffStrEquals(version, "10,1")) return "MacBook Air (M1, 2020)";
|
||||
if(ffStrEquals(version, "9,1")) return "MacBook Air (Retina, 13-inch, 2020)";
|
||||
if(ffStrEquals(version, "8,2")) return "MacBook Air (Retina, 13-inch, 2019)";
|
||||
if(ffStrEquals(version, "8,1")) return "MacBook Air (Retina, 13-inch, 2018)";
|
||||
if(ffStrEquals(version, "7,2")) return "MacBook Air (13-inch, Early 2015/2017)";
|
||||
if(ffStrEquals(version, "7,1")) return "MacBook Air (11-inch, Early 2015)";
|
||||
if(ffStrEquals(version, "6,2")) return "MacBook Air (13-inch, Mid 2013/Early 2014)";
|
||||
if(ffStrEquals(version, "6,1")) return "MacBook Air (11-inch, Mid 2013/Early 2014)";
|
||||
if(ffStrEquals(version, "5,2")) return "MacBook Air (13-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "5,1")) return "MacBook Air (11-inch, Mid 2012)";
|
||||
if(ffStrEquals(version, "4,2")) return "MacBook Air (13-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "4,1")) return "MacBook Air (11-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "3,2")) return "MacBook Air (13-inch, Late 2010)";
|
||||
if(ffStrEquals(version, "3,1")) return "MacBook Air (11-inch, Late 2010)";
|
||||
if(ffStrEquals(version, "2,1")) return "MacBook Air (Mid 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "Macmini"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Macmini");
|
||||
if(ffStrEquals(version, "9,1")) return "Mac mini (M1, 2020)";
|
||||
if(ffStrEquals(version, "8,1")) return "Mac mini (2018)";
|
||||
if(ffStrEquals(version, "7,1")) return "Mac mini (Mid 2014)";
|
||||
if(ffStrEquals(version, "6,1") ||
|
||||
ffStrEquals(version, "6,2")) return "Mac mini (Late 2012)";
|
||||
if(ffStrEquals(version, "5,1") ||
|
||||
ffStrEquals(version, "5,2")) return "Mac mini (Mid 2011)";
|
||||
if(ffStrEquals(version, "4,1")) return "Mac mini (Mid 2010)";
|
||||
if(ffStrEquals(version, "3,1")) return "Mac mini (Early/Late 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "MacBook"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBook");
|
||||
if(ffStrEquals(version, "10,1")) return "MacBook (Retina, 12-inch, 2017)";
|
||||
if(ffStrEquals(version, "9,1")) return "MacBook (Retina, 12-inch, Early 2016)";
|
||||
if(ffStrEquals(version, "8,1")) return "MacBook (Retina, 12-inch, Early 2015)";
|
||||
if(ffStrEquals(version, "7,1")) return "MacBook (13-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "6,1")) return "MacBook (13-inch, Late 2009)";
|
||||
if(ffStrEquals(version, "5,2")) return "MacBook (13-inch, Early/Mid 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "MacPro"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacPro");
|
||||
if(ffStrEquals(version, "7,1")) return "Mac Pro (2019)";
|
||||
if(ffStrEquals(version, "6,1")) return "Mac Pro (Late 2013)";
|
||||
if(ffStrEquals(version, "5,1")) return "Mac Pro (Mid 2010 - Mid 2012)";
|
||||
if(ffStrEquals(version, "4,1")) return "Mac Pro (Early 2009)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
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")) 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 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)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,4")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,5")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(ffStrEquals(version, "15,6") ||
|
||||
ffStrEquals(version, "15,8") ||
|
||||
ffStrEquals(version, "15,10")) return "MacBook Pro (14-inch, Nov 2023, Three Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "15,7") ||
|
||||
ffStrEquals(version, "15,9") ||
|
||||
ffStrEquals(version, "15,11")) return "MacBook Pro (16-inch, Nov 2023, Three Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,15")) return "MacBook Air (15-inch, M2, 2023)";
|
||||
if(ffStrEquals(version, "14,14")) return "Mac Studio (M2 Ultra, 2023, Two Thunderbolt 4 front ports)";
|
||||
if(ffStrEquals(version, "14,13")) return "Mac Studio (M2 Max, 2023, Two USB-C front ports)";
|
||||
if(ffStrEquals(version, "14,8")) return "Mac Pro (2023)";
|
||||
if(ffStrEquals(version, "14,6") ||
|
||||
ffStrEquals(version, "14,10")) return "MacBook Pro (16-inch, 2023)";
|
||||
if(ffStrEquals(version, "14,5") ||
|
||||
ffStrEquals(version, "14,9")) return "MacBook Pro (14-inch, 2023)";
|
||||
if(ffStrEquals(version, "14,3")) return "Mac mini (M2, 2023, Two Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,12")) return "Mac mini (M2, 2023, Four Thunderbolt 4 ports)";
|
||||
if(ffStrEquals(version, "14,7")) return "MacBook Pro (13-inch, M2, 2022)";
|
||||
if(ffStrEquals(version, "14,2")) return "MacBook Air (M2, 2022)";
|
||||
if(ffStrEquals(version, "13,1")) return "Mac Studio (M1 Max, 2022, Two USB-C front ports)";
|
||||
if(ffStrEquals(version, "13,2")) return "Mac Studio (M1 Ultra, 2022, Two Thunderbolt 4 front ports)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "iMac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("iMac");
|
||||
if(ffStrEquals(version, "21,1")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(ffStrEquals(version, "21,2")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "20,1") ||
|
||||
ffStrEquals(version, "20,2")) return "iMac (Retina 5K, 27-inch, 2020)";
|
||||
if(ffStrEquals(version, "19,1")) return "iMac (Retina 5K, 27-inch, 2019)";
|
||||
if(ffStrEquals(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(ffStrEquals(version, "Pro1,1")) return "iMac Pro (2017)";
|
||||
if(ffStrEquals(version, "18,3")) return "iMac (Retina 5K, 27-inch, 2017)";
|
||||
if(ffStrEquals(version, "18,2")) return "iMac (Retina 4K, 21.5-inch, 2017)";
|
||||
if(ffStrEquals(version, "18,1")) return "iMac (21.5-inch, 2017)";
|
||||
if(ffStrEquals(version, "17,1")) return "iMac (Retina 5K, 27-inch, Late 2015)";
|
||||
if(ffStrEquals(version, "16,2")) return "iMac (Retina 4K, 21.5-inch, Late 2015)";
|
||||
if(ffStrEquals(version, "16,1")) return "iMac (21.5-inch, Late 2015)";
|
||||
if(ffStrEquals(version, "15,1")) return "iMac (Retina 5K, 27-inch, Late 2014 - Mid 2015)";
|
||||
if(ffStrEquals(version, "14,4")) return "iMac (21.5-inch, Mid 2014)";
|
||||
if(ffStrEquals(version, "14,2")) return "iMac (27-inch, Late 2013)";
|
||||
if(ffStrEquals(version, "14,1")) return "iMac (21.5-inch, Late 2013)";
|
||||
if(ffStrEquals(version, "13,2")) return "iMac (27-inch, Late 2012)";
|
||||
if(ffStrEquals(version, "13,1")) return "iMac (21.5-inch, Late 2012)";
|
||||
if(ffStrEquals(version, "12,2")) return "iMac (27-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "12,1")) return "iMac (21.5-inch, Mid 2011)";
|
||||
if(ffStrEquals(version, "11,3")) return "iMac (27-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "11,2")) return "iMac (21.5-inch, Mid 2010)";
|
||||
if(ffStrEquals(version, "10,1")) return "iMac (27/21.5-inch, Late 2009)";
|
||||
if(ffStrEquals(version, "9,1")) return "iMac (24/20-inch, Early 2009)";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
bool ffHostDetectMac(FFHostResult* host)
|
||||
{
|
||||
if (ffStrbufEqualS(&host->family, "Mac") && ffStrbufEqualS(&host->vendor, "Apple Inc."))
|
||||
{
|
||||
const char* productName = ffHostGetMacProductNameWithHwModel(&host->name);
|
||||
if (productName)
|
||||
{
|
||||
ffStrbufDestroy(&host->family);
|
||||
ffStrbufInitMove(&host->family, &host->name);
|
||||
ffStrbufSetStatic(&host->name, productName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -72,5 +72,9 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
ffCleanUpSmbiosValue(&host->family);
|
||||
}
|
||||
|
||||
#if _WIN32 && __x86_64__
|
||||
ffHostDetectMac(host);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -17,35 +17,22 @@
|
||||
continue; \
|
||||
}
|
||||
|
||||
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
|
||||
static bool parseMprisMetadata(FFDBusData* data, DBusMessageIter* rootIterator, FFMediaResult* result)
|
||||
{
|
||||
DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata");
|
||||
if(reply == NULL)
|
||||
return false;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator))
|
||||
{
|
||||
data->lib->ffdbus_message_unref(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
|
||||
{
|
||||
data->lib->ffdbus_message_unref(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
DBusMessageIter variantIterator;
|
||||
data->lib->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
|
||||
if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
|
||||
{
|
||||
data->lib->ffdbus_message_unref(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
DBusMessageIter arrayIterator;
|
||||
data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
|
||||
|
||||
if (data->lib->ffdbus_message_iter_get_arg_type(rootIterator) == DBUS_TYPE_VARIANT)
|
||||
{
|
||||
DBusMessageIter variantIterator;
|
||||
data->lib->ffdbus_message_iter_recurse(rootIterator, &variantIterator);
|
||||
if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
|
||||
return false;
|
||||
data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
|
||||
}
|
||||
else
|
||||
{
|
||||
data->lib->ffdbus_message_iter_recurse(rootIterator, &arrayIterator);
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
@@ -66,13 +53,17 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
|
||||
|
||||
data->lib->ffdbus_message_iter_next(&dictIterator);
|
||||
|
||||
if(ffStrEquals(key, "xesam:title"))
|
||||
if(!ffStrStartsWith(key, "xesam:"))
|
||||
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
|
||||
|
||||
key += strlen("xesam:");
|
||||
if(ffStrEquals(key, "title"))
|
||||
ffDBusGetString(data, &dictIterator, &result->song);
|
||||
else if(ffStrEquals(key, "xesam:album"))
|
||||
else if(ffStrEquals(key, "album"))
|
||||
ffDBusGetString(data, &dictIterator, &result->album);
|
||||
else if(ffStrEquals(key, "xesam:artist"))
|
||||
else if(ffStrEquals(key, "artist"))
|
||||
ffDBusGetString(data, &dictIterator, &result->artist);
|
||||
else if(ffStrEquals(key, "xesam:url"))
|
||||
else if(ffStrEquals(key, "url"))
|
||||
ffDBusGetString(data, &dictIterator, &result->url);
|
||||
|
||||
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0)
|
||||
@@ -81,7 +72,47 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
|
||||
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
|
||||
}
|
||||
|
||||
data->lib->ffdbus_message_unref(reply);
|
||||
return true;
|
||||
}
|
||||
|
||||
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", "org.mpris.MediaPlayer2.Player");
|
||||
if(reply == NULL)
|
||||
return false;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator) &&
|
||||
data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
|
||||
{
|
||||
data->lib->ffdbus_message_unref(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
DBusMessageIter arrayIterator;
|
||||
data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
|
||||
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
|
||||
|
||||
DBusMessageIter dictIterator;
|
||||
data->lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
|
||||
|
||||
const char* key;
|
||||
data->lib->ffdbus_message_iter_get_basic(&dictIterator, &key);
|
||||
|
||||
data->lib->ffdbus_message_iter_next(&dictIterator);
|
||||
|
||||
if(ffStrEquals(key, "Metadata"))
|
||||
parseMprisMetadata(data, &dictIterator, result);
|
||||
else if(ffStrEquals(key, "PlaybackStatus"))
|
||||
ffDBusGetString(data, &dictIterator, &result->status);
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
|
||||
}
|
||||
|
||||
if(result->song.length == 0)
|
||||
{
|
||||
@@ -91,17 +122,25 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
|
||||
return false;
|
||||
}
|
||||
|
||||
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "PlaybackStatus", &result->status);
|
||||
|
||||
//Set short bus name
|
||||
ffStrbufAppendS(&result->playerId, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
|
||||
|
||||
//We found a song, get the player name
|
||||
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);
|
||||
if (ffStrbufStartsWithS(&result->playerId, "musikcube.instance"))
|
||||
{
|
||||
// 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);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -122,9 +161,9 @@ static void getCustomBus(FFDBusData* data, const FFstrbuf* playerName, FFMediaRe
|
||||
static void getBestBus(FFDBusData* data, FFMediaResult* result)
|
||||
{
|
||||
if(
|
||||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"spotify", result) ||
|
||||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"vlc", result) ||
|
||||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result)
|
||||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX "spotify", result) ||
|
||||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX "vlc", result) ||
|
||||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX "plasma-browser-integration", result)
|
||||
) return;
|
||||
|
||||
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
#include "fastfetch.h"
|
||||
#include "opengl.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#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
|
||||
|
||||
@@ -140,6 +148,8 @@ static const char* detectByGlx(FFOpenGLResult* result)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCloseDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFree);
|
||||
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
return glxHandleData(result, &data);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -27,7 +27,10 @@ void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglG
|
||||
#if defined(FF_HAVE_EGL) || __has_include(<EGL/egl.h>)
|
||||
#include "common/io/io.h"
|
||||
|
||||
#define EGL_EGL_PROTOTYPES 1
|
||||
#define EGL_EGLEXT_PROTOTYPES 1
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
typedef struct EGLData
|
||||
{
|
||||
@@ -61,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";
|
||||
|
||||
@@ -75,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";
|
||||
|
||||
@@ -91,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;
|
||||
}
|
||||
@@ -102,9 +111,20 @@ static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
|
||||
if(!data->ffglGetString)
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(data->display == EGL_NO_DISPLAY)
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
#if EGL_VERSION_1_5
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC ffeglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC) data->ffeglGetProcAddress("eglGetPlatformDisplay");
|
||||
if (ffeglGetPlatformDisplay)
|
||||
data->display = ffeglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, NULL, NULL);
|
||||
|
||||
if(!ffeglGetPlatformDisplay || data->display == EGL_NO_DISPLAY)
|
||||
#endif
|
||||
|
||||
{
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(data->display == EGL_NO_DISPLAY)
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
}
|
||||
|
||||
|
||||
EGLint major, minor;
|
||||
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
|
||||
@@ -134,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))
|
||||
|
||||
+47
-11
@@ -46,12 +46,49 @@ 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 (detectArmbianVersion(result))
|
||||
return;
|
||||
else if(ffStrbufStartsWithS(&result->prettyName, "Linux Lite "))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Linux Lite");
|
||||
ffStrbufSetS(&result->id, "linuxlite");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
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"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Kubuntu");
|
||||
@@ -70,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");
|
||||
@@ -155,17 +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->name, "Loc-OS"))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "locos");
|
||||
@@ -273,5 +301,13 @@ void ffDetectOSImpl(FFOSResult* os)
|
||||
if (!detectDebianDerived(os))
|
||||
getDebianVersion(os);
|
||||
}
|
||||
else if(ffStrbufEqualS(&os->id, "linuxmint"))
|
||||
{
|
||||
if (ffStrbufEqualS(&os->name, "LMDE"))
|
||||
{
|
||||
ffStrbufSetS(&os->id, "lmde");
|
||||
ffStrbufSetS(&os->idLike, "linuxmint");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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/"))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user