Compare commits

...

135 Commits

Author SHA1 Message Date
Carter Li 1a9e637134 Merge pull request #1464 from fastfetch-cli/dev
Release: v2.33.0
2024-12-26 09:37:25 +08:00
李通洲 f322405c04 Release: v2.33.0 2024-12-26 09:08:33 +08:00
Carter Li e4202635af Doc: update changelog [ci skip] 2024-12-25 10:47:36 +08:00
Carter Li 2f13ee3814 Media (Linux): set player name manually for musikcube 2024-12-25 10:47:36 +08:00
Carter Li 2bfde87f84 Logo (Builtin): add GoralixOS
Fix #1462
2024-12-25 10:47:36 +08:00
Carter Li f38a51c9bc Media: make it able to print player info in custom format 2024-12-25 09:04:10 +08:00
Carter Li 28ec935c42 Media (Linux): report player name 2024-12-25 08:50:28 +08:00
李通洲 d939f95c69 Vulkan (Android): hard code path of libvulkan.so, so that users don't need to install vulkan-loader wrapper of termux 2024-12-24 21:20:03 +08:00
李通洲 e0fd5111fe Media (Linux): Fix #1461 (WIP) 2024-12-24 19:38:43 +08:00
李通洲 4736031538 Doc: update changelog [ci skip] 2024-12-22 22:19:02 +08:00
李通洲 66085c087e Logo (Builtin): add NurOS
Fix #1456
2024-12-22 21:48:18 +08:00
李通洲 e0253d71c0 Doc: add comments for running fastfetch in root 2024-12-22 20:45:51 +08:00
李通洲 dadd4bfab6 DiskIO (OpenBSD): remove debug output 2024-12-22 20:43:36 +08:00
李通洲 2f3861e732 PhysicalMemory: clean up garbage data 2024-12-22 20:27:27 +08:00
李通洲 851f271ed5 CPU (NetBSD): fix typo 2024-12-22 14:20:32 +08:00
Carter Li d3e40f625b Battery (OpenBSD): fix build 2024-12-22 09:30:42 +08:00
Carter Li 7c1991c2e3 Battery (NetBSD): add support 2024-12-21 23:54:30 +08:00
李通洲 b8048ee488 Bluetooth (BSD): disable
bluez is Linux specific
2024-12-21 23:54:30 +08:00
李通洲 b99f54b9f4 CPU (NetBSD): trim CPU vendor 2024-12-21 23:54:30 +08:00
Carter Li b38d7a4919 Brightness (NetBSD): don't error out if the screen idx isn't 0 2024-12-21 23:54:30 +08:00
李通洲 45f7e2c0b2 Version (NetBSD): report sysname 2024-12-21 23:54:30 +08:00
李通洲 5a8dda27ff CPU (NetBSD): support temp and frequency detection 2024-12-21 23:54:30 +08:00
李通洲 1ea3264b13 SMBIOS (NetBSD): add more data 2024-12-21 23:54:30 +08:00
Carter Li 852a729581 Battary (NetBSD): some basic investigation of acpi battery detection 2024-12-21 23:54:30 +08:00
Carter Li 0f454b7140 Battery (OpenBSD): add support 2024-12-21 23:54:30 +08:00
Carter Li 9c47a3a9e7 Brightness (OpenBSD): add support
Requires root permission. Not tested
2024-12-21 23:54:30 +08:00
李通洲 4adf7fda28 Brightness (NetBSD): add support for builtin display 2024-12-21 23:54:30 +08:00
李通洲 e2fc83fd48 Bluetooth (Windows): silence compiler warnings 2024-12-21 23:54:30 +08:00
Robin Candau dd41dfa000 CMake: Add a cmake option to make flashfetch target optional (#1455)
Introduces the `-DBUILD_FLASHFETCH='ON'/'OFF'` build option so one can skip the `flashfetch` target (both from executable and install targets, option at `ON` by default to preserve compatibility with the current default behavior).
This is useful when distributing pre-built downstream packages (e.g. for Linux distributions packaging `fastfetch`) as building and shipping the `flashfetch` binary in such pre-built packages serves little to no purpose.
2024-12-21 23:53:02 +08:00
Carter Li 14d6157901 PhysicalDisk (Linux): fix interconnect type detection
Regression of b5a9d64

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

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

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

* Refactor Armbian detection

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

* Tidy up detectArmbianVersion
2024-12-19 16:18:42 +08:00
李通洲 b87df82d58 Shell (Windows): use $POWERSHELL_VERSION if available 2024-12-19 11:00:16 +08:00
Carter Li c145ce49a5 Merge pull request #1446 from fastfetch-cli/dev
Release: v2.32.1
2024-12-18 14:41:21 +08:00
李通洲 8c4fb5d6d4 Release: v2.32.1 2024-12-18 14:25:44 +08:00
李通洲 eae0fee032 Packages (OpenBSD): fix a typo that prevents package counting from working 2024-12-18 14:24:13 +08:00
Carter Li 4472a13f41 Packaging: update debian stuff 2024-12-18 14:22:56 +08:00
Carter Li 5b001d6bd6 Merge pull request #1445 from fastfetch-cli/dev
Release: v2.32.0
2024-12-18 10:38:44 +08:00
Carter Li 1b52029fce Release: v2.32.0 2024-12-18 09:58:46 +08:00
Carter Li 2176ea2937 Revert "Display (Linux): prefer detecting physical size from EDID"
Try fixing #1444

This reverts commit 5f3ce50022.
2024-12-18 09:28:42 +08:00
李通洲 ac2266c72f Wifi (FreeBSD): early break if the interface is not associated 2024-12-17 20:55:33 +08:00
Eva 0dc40a2632 WM (Linux): added ratpoison window manager (#1442) 2024-12-17 10:49:55 +08:00
李通洲 ca975f8e81 Version: fix format parameter name
Fix #1443
2024-12-17 10:24:18 +08:00
Kevin c4c6fe6668 Logo (Builtin): improved debian ascii logo (#1441) 2024-12-16 12:05:18 +08:00
Carter Li 0a00f5721e OpenGL (NetBSD): try fixing build 2024-12-14 22:22:35 +08:00
李通洲 69f180beea Display (FreeBSD): don't try to use /sys on FreeBSD 2024-12-14 22:22:35 +08:00
李通洲 0e9cdf75b5 WM (FreeBSD): improve WM detection for Wayland 2024-12-14 22:22:35 +08:00
Carter Li 7d7e219c0a OpenGL (NetBSD): fix build 2024-12-14 13:34:42 +08:00
Carter Li 4937ccfa81 OpenGL (EGL): prefer surfaceless display 2024-12-14 12:56:40 +08:00
JohnTheCoolingFan d0d29c163b Add Armbian-unofficial detection (#1436) 2024-12-14 12:56:13 +08:00
Carter Li 901e0eb177 Logo (Builtin): add Ultramarine Small
Fix #1438
2024-12-14 12:00:33 +08:00
Carter Li 87446e6eef WM (OpenBSD): fix process enumeration 2024-12-14 00:18:41 +08:00
Carter Li bfaa73a2c7 Display (Linux): clean up 2024-12-14 00:05:28 +08:00
Carter Li 373e288d03 WM: add support for fvwm (OpenBSD) and ctwm (NetBSD) 2024-12-14 00:05:02 +08:00
李通洲 82170ceab0 Scripts: fix typo 2024-12-13 16:05:37 +08:00
Carter Li 009a7888b5 OpenGL (Linux): suppress IO
Fix #1435
2024-12-13 15:40:36 +08:00
Carter Li ab1a11c9fa CPU (ARM): add more apple cores 2024-12-13 15:29:24 +08:00
Carter Li 68746275f8 CPU (Linux): detect Virtualized Apple Silicon 2024-12-13 15:28:59 +08:00
李通洲 491cfb94b6 Doc: update changelog [ci skip] 2024-12-12 16:01:56 +08:00
李通洲 79c8919431 Logo (Builtin): add Serpent OS
Ref: https://github.com/serpent-os/recipes/blob/main/f/fastfetch/pkg/0001-logo-Port-our-neofetch-Serpent-OS-logo-from-ermo.patch
2024-12-12 15:43:43 +08:00
李通洲 e98afa8315 JsonSchema: fix typo 2024-12-11 16:41:48 +08:00
李通洲 86783c033b OS (Linux): detect Linux Lite
Fix #1434
2024-12-11 16:40:02 +08:00
李通洲 f01944de41 JsonSchema: add documentation of format args 2024-12-11 16:12:55 +08:00
李通洲 ebfdeef25c Fastfetch: add -h format-json 2024-12-11 16:12:03 +08:00
李通洲 9a36d63d18 Global: refactor code of -h <module>-format 2024-12-11 10:47:02 +08:00
李通洲 e45ff546ed Host: silence compiler warnings 2024-12-10 09:35:52 +08:00
李通洲 2700390371 Host (Sun): fix build 2024-12-09 23:07:24 +08:00
Carter Li 5c01685d69 Host: detect mac model in FreeBSD & Windows 2024-12-09 21:44:31 +08:00
Carter Li d897472572 Edid: use screen size in DTD if make sense 2024-12-06 19:20:06 +08:00
Carter Li 8410a66277 Host (Linux): report mac product name 2024-12-06 18:31:33 +08:00
Carter Li 856d229b36 Wifi (Linux): fix bssid formatting 2024-12-06 09:14:30 +08:00
李通洲 b33692aa7d Logo: randomly select one if the logo source expands to multiple files
Fix #1426
2024-12-05 14:16:30 +08:00
李通洲 e90c5cb241 GPU (OpenBSD): fix pci.ids file location 2024-12-05 08:37:41 +08:00
Carter Li 03cd283755 Packaging: update debian stuff [ci skip] 2024-12-04 08:43:33 +08:00
Carter Li 58a1d965cb Merge pull request #1425 from fastfetch-cli/dev
Release: v2.31.0
2024-12-03 15:00:54 +08:00
Carter Li 6edf763f2b Display (Linux): detect bit depth when libdrm is used 2024-12-03 10:55:00 +08:00
Carter Li ab200d7e4a Terminal: Support sakura version & font detection
Fix #1424
2024-12-02 19:10:47 +08:00
Carter Li dfe36daf79 Release: v2.31.0 2024-12-02 16:36:12 +08:00
李通洲 e9ab67b380 Processing (Linux): interrupt poll & read syscalls when the child process is exited
Fix #1418
2024-12-02 16:02:04 +08:00
Carter Li f073f4882c Wifi (Linux): detect Wifi-7 2024-12-01 18:16:05 +08:00
李通洲 692ad502df Wifi (Windows): make unit of bitrates be consistant
Also fix a copy & paste bug
2024-11-30 23:50:06 +08:00
Raymond Kemboi 3004ce8565 Completion (Zsh): fix syntax error in completion file (#1421)
A syntax error in the file caused the following output when trying to trigger completions in `zsh` (pressing <TAB>):

```zsh
$ fastfetch    File "<stdin>", line 15
    command_prefix = f"--logo-color-{i}[{flag["desc"]} ({i})]"
                                               ^^^^
SyntaxError: f-string: unmatched '['
```
This fix replaces single quotes with double quotes in the f-strings in lines 37 and 41.
2024-11-29 10:25:58 +08:00
Ryan ee8801b54d WM (Linux): fix wl-restart parsing (#1422)
Make the WM name in `wl-restart -n 5 Hyprland` parse as "Hyprland"
instead of "-n".
2024-11-29 08:34:40 +08:00
李通洲 bbe239647b Logo (Builtin): add Windows Server 2025
Fix #1420
2024-11-28 21:55:21 +08:00
Carter Li 77c06193d6 GPU (Linux): detect GPU NV type 2024-11-28 21:28:35 +08:00
李通洲 90bbefe11a CPU (Windows): code cleanup 2024-11-26 22:02:57 +08:00
Carter Li 69a7e64e48 CPU (Linux): support up to 128-socket boards 2024-11-26 21:49:28 +08:00
Carter Li ee564de461 CPU: change cpuCount to packages; support custom format
Fix #1413
2024-11-26 21:37:15 +08:00
Carter Li 9955e9da02 CPU: remove duplicate whitespaces in CPU name
Eg. `Intel(R) Xeon(R) CPU           E5620  @ 2.40GHz`
2024-11-26 21:27:36 +08:00
Carter Li 8b41cbd508 CPU (Linux): refactor; fix cpu count detection 2024-11-26 16:05:01 +08:00
AzimovParviz 7535ce8a18 Support for dual CPU systems (#1417)
* [macOS] Added support for dual CPUs on Mac computers

Signed-off-by: Koneko <azimovp17@gmail.com>

* Change how number of cores is displayed when the system is dual CPU

* Support for dual CPU on Windows

* Dual CPU detection on Linux basic implementation

---------

Signed-off-by: Koneko <azimovp17@gmail.com>
2024-11-26 08:53:01 +08:00
李通洲 b76eb87510 CI: fix building on macOS 2024-11-25 22:46:57 +08:00
李通洲 0cd7aeac19 Display (macOS): don't crash with NULL pointer references
Fix #1393
2024-11-25 22:23:24 +08:00
Carter Li 04088b5b2c Logo (Builtin): update MidOS
Fix #1409
2024-11-25 14:31:07 +08:00
Carter Li e77c3119ca OS (Linux): check for lmde
Fix #1415
2024-11-25 14:20:52 +08:00
Carlos Henrique Lima Melara 3463fc331f Scripts: use datetime to get date and set timezone to UTC (#1410)
This will ensure the package is reproducible even in different
timezones.
2024-11-24 10:22:57 +08:00
李通洲 64287eed21 Display: change physical size detection to use basic display parameters
Some monitor report invalid data in DTD.
Ref: #1406
2024-11-24 01:02:06 +08:00
李通洲 1b835544b6 Users: fix invalid var name
Fix #1408
2024-11-23 22:44:45 +08:00
Carter Li 55352be0cc Wifi (FreeBSD): support channel & frequency detection 2024-11-23 12:21:48 +08:00
Carter Li c0be2637a8 Wifi (Android): silence compiler warnings 2024-11-22 15:37:01 +08:00
Carter Li 864fb918bc Chore: silence some warnings 2024-11-22 14:20:50 +08:00
Carter Li 2197cfb06d Wifi (Android): report more props 2024-11-22 13:53:04 +08:00
Carter Li 94f8ff938b Wifi: print channel band 2024-11-22 11:01:54 +08:00
Carter Li 7000317841 Wifi (Linux): detect frequency & channel number 2024-11-22 10:31:12 +08:00
李通洲 06055cc6c3 Wifi (macOS): fix build on old OS version 2024-11-21 22:03:25 +08:00
李通洲 601b9706b5 Display: report ppi to 0 if screen size is not available 2024-11-21 21:44:05 +08:00
李通洲 d48c76b597 Wifi: detect channel and frequency 2024-11-21 21:37:30 +08:00
李通洲 9a1d18556d Display: don't report screen size when display is mirrored
Fix #1406
2024-11-21 15:29:14 +08:00
李通洲 71b073e1bf CMake: fix possible linking errors in BINARY_LINK_TYPE=dynamic mode 2024-11-20 22:13:10 +08:00
Carter Li a567268ca1 Display (Linux): fix preferred resolution detection for wayland 2024-11-20 21:38:18 +08:00
李通洲 8b62ad72f7 Display (FreeBSD): fix build 2024-11-20 16:39:01 +08:00
李通洲 cee880cb83 Display: print preferred resolution & refresh rate in custom format
Fix #1406
2024-11-20 16:39:01 +08:00
李通洲 925c3471c2 Display: add scale factor in custom format 2024-11-20 16:39:01 +08:00
李通洲 7948e627b0 Display (Android): fix build 2024-11-20 16:39:01 +08:00
李通洲 4cca63a299 Display (Windows): detect preferred resolution & refresh rate 2024-11-20 16:39:01 +08:00
李通洲 21a35769a7 Display (macOS): detect maximum resolution & refresh rate 2024-11-20 16:39:01 +08:00
Carter Li fa9290088d Display (Linux): detect preferred resolution and refresh rate 2024-11-20 16:38:53 +08:00
Carter Li 3d5133eaba DisplayServer (Linux): remove support of xcb & xlib
They don't support multi-monitors. Prefer libdrm.
2024-11-20 09:37:32 +08:00
Carter Li 4cbcd0f107 Wifi (Linux): improve performance 2024-11-20 08:43:41 +08:00
Carter Li fdc9bee4b3 DBus: use general.processingTimeout as its timeout instead hard coding 2024-11-20 08:43:41 +08:00
Carter Li 16b7a4a1be Media (Linux): improve performance of dbus communication 2024-11-20 08:43:41 +08:00
R0CKSTAR 465170428f mtgpu: header file cleanup for forward compatibility (#1405)
Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>
2024-11-19 19:36:12 +08:00
Carter Li e953ed9d88 Packaging: update debian stuff [ci skip] 2024-11-18 15:47:48 +08:00
Carter Li 6d45fe61b5 Merge pull request #1404 from fastfetch-cli/dev
Release: v2.30.1
2024-11-18 14:57:05 +08:00
李通洲 efc8504607 CMake: check return code of python scripts 2024-11-18 14:08:53 +08:00
李通洲 a9a08d8a80 Release: v2.30.1 2024-11-18 13:40:08 +08:00
李通洲 7f63ec1315 CMake: fix the destination where fastfetch_pciids.c.inc is generated 2024-11-18 13:36:31 +08:00
Masato TOYOSHIMA 6cbbe334b5 CMake: Fixed the destination where fastfetch.1 is generated. (#1403)
* Fixed the destination where fastfetch.1 is generated.

* Update CMakeLists.txt

Reappend trailing new line

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-11-18 13:32:49 +08:00
Carter Li 4bde8d3fb3 Packaging: update debian stuff [ci skip] 2024-11-18 09:36:46 +08:00
176 changed files with 5165 additions and 3114 deletions
+2 -2
View File
@@ -274,7 +274,7 @@ jobs:
macos-universal:
name: macOS-universal
runs-on: macos-12
runs-on: macos-latest
permissions:
security-events: write
contents: read
@@ -452,7 +452,7 @@ jobs:
version: '7.5'
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
+103
View File
@@ -1,3 +1,106 @@
# 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:
* Fix the destination where `fastfetch.1` is generated (#1403)
# 2.30.0
Changes:
+68 -43
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.30.0
VERSION 2.33.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)
@@ -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
@@ -268,11 +267,15 @@ else()
file(READ "src/data/help.json" DATATEXT_JSON_HELP)
endif()
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "fastfetch_pciids.c.inc")
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
if(Python_FOUND)
message(STATUS "Generating 'fastfetch_pciids.c.inc'")
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py"
OUTPUT_FILE "fastfetch_pciids.c.inc")
OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc"
RESULT_VARIABLE PYTHON_PCIIDS_RETCODE)
if(NOT PYTHON_PCIIDS_RETCODE EQUAL 0)
message(FATAL_ERROR "Failed to generate 'fastfetch_pciids.c.inc'")
endif()
else()
message(WARNING "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated")
set(ENABLE_EMBEDDED_PCIIDS OFF)
@@ -282,7 +285,11 @@ endif()
if(Python_FOUND)
message(STATUS "Generating 'fastfetch.1'")
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-man.py"
OUTPUT_FILE "fastfetch.1")
OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch.1"
RESULT_VARIABLE PYTHON_MANPAGE_RETCODE)
if(NOT PYTHON_MANPAGE_RETCODE EQUAL 0)
message(FATAL_ERROR "Failed to generate 'fastfetch.1'")
endif()
else()
message(WARNING "Python3 is not found, use basic 'fastfetch.1.in' instead")
string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y" UTC)
@@ -496,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
@@ -609,8 +617,8 @@ 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/bluetooth/bluetooth_nosupport.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
@@ -643,6 +651,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,13 +698,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
@@ -771,13 +780,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
@@ -875,6 +884,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
@@ -943,6 +953,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
@@ -1214,6 +1225,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)
@@ -1269,18 +1283,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"
@@ -1480,6 +1486,7 @@ elseif(OpenBSD)
elseif(NetBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "prop"
)
elseif(SunOS)
target_link_libraries(libfastfetch
@@ -1606,41 +1613,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()
###################
@@ -1682,10 +1700,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
+4
View File
@@ -199,6 +199,10 @@ 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)
+3 -3
View File
@@ -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)
+24
View File
@@ -1,3 +1,27 @@
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
-- Carter Li <zhangsongcui@live.cn> Mon, 18 Nov 2024 09:30:58 +0800
fastfetch (2.29.0) jammy; urgency=medium
* Update to 2.29.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.29.0_source.buildinfo universe/utils optional
fastfetch_2.32.0_source.buildinfo universe/utils optional
+1406 -243
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+5 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+18 -4
View File
@@ -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";
+107
View File
@@ -0,0 +1,107 @@
#include "battery.h"
#include "common/io/io.h"
#include "util/FFstrbuf.h"
#include "util/stringUtils.h"
#include <prop/prop_array.h>
#include <prop/prop_bool.h>
#include <prop/prop_dictionary.h>
#include <prop/prop_object.h>
#include <sys/envsys.h>
#include <prop/proplib.h>
#include <paths.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
bool acConnected = false;
{
prop_array_t acad = prop_dictionary_get(root, "acpiacad0");
if (acad)
{
prop_dictionary_t dict = prop_array_get(acad, 0);
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &acConnected);
}
}
prop_object_iterator_t itKey = prop_dictionary_iterator(root);
for (prop_dictionary_keysym_t key; (key = prop_object_iterator_next(itKey)) != NULL; )
{
if (!ffStrStartsWith(prop_dictionary_keysym_value(key), "acpibat")) continue;
prop_array_t bat = prop_dictionary_get_keysym(root, key);
uint32_t max = 0, curr = 0, dischargeRate = 0;
bool charging = false, critical = false;
prop_object_iterator_t iter = prop_array_iterator(bat);
for (prop_dictionary_t dict; (dict = prop_object_iterator_next(iter)) != NULL;)
{
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
continue;
const char* desc = NULL;
if (!prop_dictionary_get_string(dict, "description", &desc))
continue;
if (ffStrEquals(desc, "present"))
{
int value = 0;
if (prop_dictionary_get_int(dict, "cur-value", &value) && value == 0)
continue;
}
else if (ffStrEquals(desc, "charging"))
{
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &charging);
}
else if (ffStrEquals(desc, "charge"))
{
prop_dictionary_get_uint32(dict, "max-value", &max);
prop_dictionary_get_uint32(dict, "cur-value", &curr);
const char* state = NULL;
if (prop_dictionary_get_string(dict, "state", &state) && ffStrEquals(state, "critical"))
critical = true;
}
else if (ffStrEquals(desc, "discharge rate"))
{
prop_dictionary_get_uint(dict, "cur-value", &dischargeRate);
}
}
if (max > 0)
{
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->timeRemaining = -1;
battery->capacity = (double) curr / max;
if (charging)
ffStrbufAppendS(&battery->status, "Charging, ");
else if (dischargeRate)
ffStrbufAppendS(&battery->status, "Discharging, ");
if (critical)
ffStrbufAppendS(&battery->status, "Critical, ");
if (acConnected)
ffStrbufAppendS(&battery->status, "AC Connected");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
prop_object_iterator_release(itKey);
return NULL;
}
+52
View File
@@ -0,0 +1,52 @@
#include "battery.h"
#include "common/io/io.h"
#include <machine/apmvar.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result)
{
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY);
if (devfd < 0) return "open(dev/apm, O_RDONLY) failed";
struct apm_power_info info = {};
if (ioctl(devfd, APM_IOC_GETPOWER, &info) < 0)
return "ioctl(APM_IOC_GETPOWER) failed";
if (info.battery_state == APM_BATTERY_ABSENT)
return NULL;
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(result);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
battery->timeRemaining = -1;
battery->capacity = info.battery_life;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
if (info.ac_state == APM_AC_ON)
ffStrbufAppendS(&battery->status, "AC Connected");
else if (info.ac_state == APM_AC_BACKUP)
ffStrbufAppendS(&battery->status, "Backup In Use");
else if (info.ac_state == APM_AC_OFF)
{
battery->timeRemaining = (int) info.minutes_left * 60;
ffStrbufAppendS(&battery->status, "Discharging");
}
if (info.battery_state == APM_BATT_CRITICAL || info.battery_state == APM_BATT_CHARGING)
{
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
ffStrbufAppendS(&battery->status, info.battery_state == APM_BATT_CRITICAL ? "Critical" : "Charging");
}
return NULL;
}
+1 -1
View File
@@ -11,4 +11,4 @@ typedef struct FFBluetoothResult
bool connected;
} FFBluetoothResult;
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */);
+4 -1
View File
@@ -10,7 +10,7 @@
@property (nonatomic) uint8_t batteryPercentSingle;
@end
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
if(!ioDevices)
@@ -18,6 +18,9 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
for(IOBluetoothDevice* ioDevice in ioDevices)
{
if (!options->showDisconnected && !ioDevice.isConnected)
continue;
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
+68 -22
View File
@@ -3,6 +3,7 @@
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/io/io.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
@@ -44,16 +45,16 @@ array [ //root
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
static bool detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return true;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
return true;
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
@@ -74,6 +75,13 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
}
else if(ffStrEquals(deviceProperty, "Connected"))
ffDBusGetBool(dbus, &dictIter, &device->connected);
else if(ffStrEquals(deviceProperty, "Paired"))
{
bool paired = true;
ffDBusGetBool(dbus, &dictIter, &paired);
if (!paired) return false;
}
return true;
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
@@ -103,32 +111,37 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
do
{
detectBluetoothValue(dbus, &arrayIter, device);
bool shouldContinue = detectBluetoothValue(dbus, &arrayIter, device);
if (!shouldContinue)
{
ffStrbufClear(&device->name);
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return NULL;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
return NULL;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
// We don't want adapter objects
if(!ffStrContains(objectPath, "/dev_"))
return;
return NULL;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
return NULL;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
@@ -145,16 +158,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}
return device;
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter, int32_t connectedCount)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
@@ -164,11 +171,25 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
FFBluetoothResult* device = detectBluetoothObject(devices, dbus, &arrayIter);
if (device)
{
if(device->name.length == 0 || (connectedCount > 0 && !device->connected))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--devices->length;
}
if (device->connected && --connectedCount == 0)
break;
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices)
static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
{
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
@@ -186,18 +207,43 @@ static const char* detectBluetooth(FFlist* devices)
return "Failed to get root iterator of GetManagedObjects";
}
detectBluetoothRoot(devices, &dbus, &rootIter);
detectBluetoothRoot(devices, &dbus, &rootIter, connectedCount);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
static uint32_t connectedDevices(void)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
return 0;
uint32_t result = 0;
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (strchr(entry->d_name, ':') != NULL)
++result;
}
return result;
}
#endif
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
int32_t connectedCount = -1;
if (!options->showDisconnected)
{
connectedCount = (int32_t) connectedDevices();
if (connectedCount == 0)
return NULL;
}
return detectBluetooth(devices, connectedCount);
#else
return "Fastfetch was compiled without DBus support";
#endif
@@ -1,6 +1,6 @@
#include "bluetooth.h"
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
return "Not supported on this platform";
}
+5 -4
View File
@@ -7,7 +7,7 @@
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
{
// Actually bluetoothapis.dll, but it's missing on Windows 7
FF_LIBRARY_LOAD(bluetoothapis, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
@@ -20,13 +20,14 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) {
.fReturnConnected = TRUE,
.fReturnRemembered = TRUE,
.fReturnAuthenticated = TRUE,
.fReturnUnknown = TRUE,
.fReturnRemembered = options->showDisconnected,
.fReturnAuthenticated = options->showDisconnected,
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)
}, &btdi);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return NULL;
return "BluetoothFindFirstDevice() failed";
}
@@ -55,7 +55,7 @@ const char* ffBluetoothDetectBattery(FFlist* devices)
on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); });
IWbemClassObject* pResultObject = nullptr;
if (FAILED(pCallResult->GetResultObject(WBEM_INFINITE, &pResultObject)))
if (FAILED(pCallResult->GetResultObject((LONG) WBEM_INFINITE, &pResultObject)))
continue;
on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); });
@@ -3,56 +3,47 @@
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/io/io.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
/* Example dbus reply:
array [
dict entry(
object path "/org/bluez/hci0"
array [
dict entry(
string "org.bluez.Adapter1"
array [
dict entry(
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "xxxxxxxx"
)
dict entry(
string "Powered"
variant boolean true
)
dict entry(
string "PowerState"
variant string "on"
)
dict entry(
string "Manufacturer"
variant uint16 2
)
dict entry(
string "Version"
variant byte 12
)
]
)
]
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "xxxxxxxx"
)
dict entry(
string "Powered"
variant boolean true
)
dict entry(
string "PowerState"
variant string "on"
)
dict entry(
string "Manufacturer"
variant uint16 2
)
dict entry(
string "Version"
variant byte 12
)
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
static const char* detectBluetoothProperty(FFBluetoothRadioResult* device, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
return "Expected dict entry";
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
return "Expected dict entry key to be a string";
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
@@ -77,121 +68,73 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
ffDBusGetBool(dbus, &dictIter, &device->discoverable);
else if(ffStrEquals(deviceProperty, "Pairable"))
ffDBusGetBool(dbus, &dictIter, &device->connectable);
return NULL;
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const char* hciName, FFDBusData* dbus)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
char objPath[300];
snprintf(objPath, sizeof(objPath), "/org/bluez/%s", hciName);
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
DBusMessage* properties = ffDBusGetMethodReply(dbus, "org.bluez", objPath, "org.freedesktop.DBus.Properties", "GetAll", "org.bluez.Adapter1");
if(!properties)
return "Failed to call org.freedesktop.DBus.Properties.GetAll";
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(!ffStrContains(propertyType, ".Adapter"))
return; //We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
do
DBusMessageIter rootIter;
if(!dbus->lib->ffdbus_message_iter_init(properties, &rootIter))
{
detectBluetoothValue(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We want adapter objects
if(!ffStrStartsWith(objectPath, "/org/bluez/hci") || ffStrContains(objectPath, "/dev_"))
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
do
{
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
--devices->length;
dbus->lib->ffdbus_message_unref(properties);
return "Failed to get root iterator of org.freedesktop.DBus.Properties.GetAll";
}
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
if(dbus->lib->ffdbus_message_iter_get_arg_type(&rootIter) != DBUS_TYPE_ARRAY)
{
dbus->lib->ffdbus_message_unref(properties);
return "Expected array";
}
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
dbus->lib->ffdbus_message_iter_recurse(&rootIter, &arrayIter);
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
detectBluetoothProperty(device, dbus, &arrayIter);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
dbus->lib->ffdbus_message_unref(properties);
return NULL;
}
static const char* detectBluetooth(FFlist* devices)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
if(dirp == NULL)
return "Failed to open /sys/class/bluetooth";
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
if(!managedObjects)
return "Failed to call GetManagedObjects";
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
dbus.lib->ffdbus_message_unref(managedObjects);
return "Failed to get root iterator of GetManagedObjects";
if (entry->d_name[0] == '.')
continue;
if (strchr(entry->d_name, ':') != NULL) // ignore connected devices
continue;
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
detectBluetoothRoot(device, entry->d_name, &dbus);
}
detectBluetoothRoot(devices, &dbus, &rootIter);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
@@ -202,7 +145,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
#else
FF_UNUSED(devices)
FF_UNUSED(devices)
return "Fastfetch was compiled without DBus support";
#endif
}
+2
View File
@@ -10,6 +10,8 @@ const char* ffDetectBoard(FFBoardResult* board)
ffCleanUpSmbiosValue(&board->version);
if (ffSysctlGetString("machdep.dmi.board-vendor", &board->vendor) == NULL)
ffCleanUpSmbiosValue(&board->vendor);
if (ffSysctlGetString("machdep.dmi.board-serial", &board->serial) == NULL)
ffCleanUpSmbiosValue(&board->serial);
return NULL;
}
+1 -1
View File
@@ -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, &param) < 0)
return "ioctl(WSDISPLAYIO_GETPARAM) failed";
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitStatic(&brightness->name, "wsdisplay");
brightness->max = param.max;
brightness->min = param.min;
brightness->current = param.curval;
return NULL;
}
+2
View File
@@ -10,6 +10,8 @@ const char* ffDetectChassis(FFChassisResult* chassis)
ffCleanUpSmbiosValue(&chassis->version);
if (ffSysctlGetString("machdep.dmi.chassis-vendor", &chassis->vendor) == NULL)
ffCleanUpSmbiosValue(&chassis->vendor);
if (ffSysctlGetString("machdep.dmi.chassis-serial", &chassis->serial) == NULL)
ffCleanUpSmbiosValue(&chassis->serial);
return NULL;
}
+1
View File
@@ -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;
}
+1
View File
@@ -15,6 +15,7 @@ typedef struct FFCPUResult
FFstrbuf name;
FFstrbuf vendor;
uint16_t packages;
uint16_t coresPhysical;
uint16_t coresLogical;
uint16_t coresOnline;
+1
View File
@@ -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");
+5 -1
View File
@@ -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;
}
}
+62 -34
View File
@@ -159,40 +159,44 @@ static void detectAndroid(FFCPUResult* cpu)
#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");
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 +224,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')
@@ -465,11 +469,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 +504,15 @@ 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);
#endif
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
ffCPUDetectSpeedByCpuid(cpu);
@@ -519,7 +547,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;
+38 -26
View File
@@ -1,26 +1,42 @@
#include "cpu.h"
#include "common/sysctl.h"
#include <sys/sysctl.h>
#include "common/io/io.h"
#include <sys/envsys.h>
#include <prop/proplib.h>
#include <paths.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
static const char* detectCpuTemp(double* current)
{
int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed";
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
return NULL;
}
prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
static const char* detectThermalTemp(double* current)
{
int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed";
prop_array_t array = prop_dictionary_get(root, "coretemp0");
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
if (!array) array = prop_dictionary_get(root, "viac7temp0");
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
if (!array) return "No temp data found in root dictionary";
if (prop_array_count(array) != 2)
return "Unexpected `xtemp0` data";
prop_dictionary_t dict = prop_array_get(array, 0);
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
return "Unexpected `xtemp0[0]`";
int temp = 0; // in µK
if (!prop_dictionary_get_int(dict, "cur-value", &temp))
return "Failed to get temperature";
*current = temp / 1e6 - 273.15;
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
return NULL;
}
@@ -32,26 +48,22 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
return "sysctlbyname(machdep.cpu_brand) failed";
}
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL)
ffStrbufTrimRightSpace(&cpu->vendor);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresLogical = cpu->coresPhysical;
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.ncpuonline", cpu->coresLogical);
ffCPUDetectSpeedByCpuid(cpu);
{
struct clockinfo info;
size_t length = sizeof(info);
if (sysctl((int[]) {CTL_KERN, KERN_CLOCKRATE}, 2, &info, &length, NULL, 0) == 0)
cpu->frequencyBase = (uint32_t) info.hz / 1000;
}
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
if (freq > cpu->frequencyBase)
cpu->frequencyBase = freq;
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
{
if (detectCpuTemp(&cpu->temperature) != NULL)
detectThermalTemp(&cpu->temperature);
}
if (options->temp) detectCpuTemp(&cpu->temperature);
return NULL;
}
+5 -3
View File
@@ -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;
-2
View File
@@ -13,8 +13,6 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
return "sysctl({HW_DISKSTATS}, NULL) failed";
uint32_t nDrive = (uint32_t) (len / sizeof(struct diskstats));
printf("C: %d\n", nDrive);
struct diskstats* stats = malloc(len);
if (sysctl(mib, ARRAY_SIZE(mib), stats, &len, NULL, 0) < 0)
@@ -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;
+16 -8
View File
@@ -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);
+47 -24
View File
@@ -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
+8 -2
View File
@@ -126,8 +126,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 +302,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;
+35 -93
View File
@@ -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,
+26 -76
View File
@@ -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 -16
View File
@@ -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;
}
+6 -9
View File
@@ -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
+20 -26
View File
@@ -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);
+4
View File
@@ -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);
+1 -174
View File
@@ -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)
+4
View File
@@ -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;
}
+4
View File
@@ -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 ");
+193
View File
@@ -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") ||
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;
}
#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
+4
View File
@@ -12,6 +12,10 @@ const char* ffDetectHost(FFHostResult* host)
ffCleanUpSmbiosValue(&host->vendor);
if (ffSysctlGetString("machdep.dmi.system-version", &host->version) == NULL)
ffCleanUpSmbiosValue(&host->version);
if (ffSysctlGetString("machdep.dmi.system-serial", &host->serial) == NULL)
ffCleanUpSmbiosValue(&host->serial);
if (ffSysctlGetString("machdep.dmi.system-uuid", &host->uuid) == NULL)
ffCleanUpSmbiosValue(&host->uuid);
return NULL;
}
+4
View File
@@ -72,5 +72,9 @@ const char* ffDetectHost(FFHostResult* host)
ffCleanUpSmbiosValue(&host->family);
}
#if _WIN32 && __x86_64__
ffHostDetectMac(host);
#endif
return NULL;
}
+83 -42
View File
@@ -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,49 @@ 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);
FF_STRBUF_AUTO_DESTROY desktopIdentity = ffStrbufCreate();
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 +124,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 +163,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);
+3
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include "opengl.h"
#include "common/io/io.h"
#include <string.h>
@@ -140,6 +141,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);
}
+17 -3
View File
@@ -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
{
@@ -102,9 +105,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)
+38 -10
View File
@@ -46,12 +46,41 @@ 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;
}
if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu"))
{
ffStrbufSetS(&result->name, "Kubuntu");
@@ -155,17 +184,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 +293,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
}
+1 -1
View File
@@ -27,7 +27,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
{
result->pkg = getNumElementsImpl(FASTFETCH_TARGET_DIR_ROOT
#if __OpenBSD
#if __OpenBSD__
"/var/db/pkg"
#else
"/usr/pkg/pkgdb"
+20 -16
View File
@@ -80,24 +80,28 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
{
ffStrbufInit(&device->interconnect);
char pathSysDeviceReal[PATH_MAX];
ssize_t pathLength = readlinkat(dfd, "device", pathSysDeviceReal, ARRAY_SIZE(pathSysDeviceReal) - 1);
if (pathLength > 0)
if (ffStrStartsWith(devName, "nvme"))
ffStrbufSetStatic(&device->interconnect, "NVMe");
else
{
pathSysDeviceReal[pathLength] = '\0';
if (strstr(pathSysDeviceReal, "/usb") != NULL)
ffStrbufSetS(&device->interconnect, "USB");
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
ffStrbufSetS(&device->interconnect, "NVMe");
else if (strstr(pathSysDeviceReal, "/ata") != NULL)
ffStrbufSetS(&device->interconnect, "ATA");
else if (strstr(pathSysDeviceReal, "/scsi") != NULL)
ffStrbufSetS(&device->interconnect, "SCSI");
else
char pathSysDeviceLink[64];
snprintf(pathSysDeviceLink, ARRAY_SIZE(pathSysDeviceLink), "/sys/block/%s/device", devName);
char pathSysDeviceReal[PATH_MAX];
if (realpath(pathSysDeviceLink, pathSysDeviceReal))
{
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
ffStrbufTrimRightSpace(&device->interconnect);
if (strstr(pathSysDeviceReal, "/usb") != NULL)
ffStrbufSetStatic(&device->interconnect, "USB");
else if (strstr(pathSysDeviceReal, "/ata") != NULL)
ffStrbufSetStatic(&device->interconnect, "ATA");
else if (strstr(pathSysDeviceReal, "/scsi") != NULL)
ffStrbufSetStatic(&device->interconnect, "SCSI");
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
ffStrbufSetStatic(&device->interconnect, "NVMe");
else
{
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
ffStrbufTrimRightSpace(&device->interconnect);
}
}
}
}
@@ -23,6 +23,7 @@ static inline const char* getVendorString(unsigned vendorId)
void FFPhysicalMemoryUpdateVendorString(FFPhysicalMemoryResult* device)
{
if (device->vendor.length == 0) return;
if (ffStrbufEqualS(&device->vendor, "Unknown"))
{
ffStrbufClear(&device->vendor);
@@ -191,6 +191,7 @@ const char* ffDetectPhysicalMemory(FFlist* result)
device->maxSpeed = data->Speed == 0xFFFF ? data->ExtendedSpeed : data->Speed;
ffStrbufSetStatic(&device->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&device->vendor);
FFPhysicalMemoryUpdateVendorString(device);
ffStrbufSetStatic(&device->serial, ffSmbiosLocateString(strings, data->SerialNumber));
@@ -250,7 +250,7 @@ static void detectFootTerminal(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, font.chars, "8");
return;
}
uint32_t size = equal + strlen("size=");
uint32_t size = equal + (uint32_t) strlen("size=");
uint32_t comma = ffStrbufNextIndexC(&font, size, ',');
if (comma < font.length)
font.chars[comma] = '\0';
@@ -454,4 +454,6 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
detectWestonTerminal(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "terminator"))
detectTerminator(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "sakura"))
detectFromConfigFile("sakura/sakura.conf", "font=", terminalFont);;
}
@@ -109,6 +109,15 @@ static bool getShellVersionFish(FFstrbuf* exe, FFstrbuf* version)
static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
{
// Requires manually setting $POWERSHELL_VERSION
// $env:POWERSHELL_VERSION = $PSVersionTable.PSVersion.ToString(); fastfetch.exe
const char* env = getenv("POWERSHELL_VERSION");
if (env)
{
ffStrbufSetS(version, env);
return true;
}
#ifdef _WIN32
if(getFileVersion(exe->chars, version))
{
@@ -249,6 +258,13 @@ static bool getShellVersionZsh(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* versi
#ifdef _WIN32
static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
{
const char* env = getenv("POWERSHELL_VERSION");
if (env)
{
ffStrbufSetS(version, env);
return true;
}
return ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"-NoLogo",
@@ -661,6 +677,19 @@ FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* ver
ffStrbufSubstrAfter(version, index);
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionSakura(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL) // sakura version is 3.8.8
return false;
ffStrbufSubstrAfterLastC(version, ' ');
return true;
}
#endif
#ifdef _WIN32
@@ -763,6 +792,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
if(ffStrbufIgnCaseEqualS(processName, "tilix"))
return getTerminalVersionTilix(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "sakura"))
return getTerminalVersionSakura(exe, version);
#endif
#ifdef _WIN32
@@ -57,6 +57,9 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "flashfetch") ||
ffStrbufContainS(&result->processName, "debug") ||
ffStrbufContainS(&result->processName, "not-found") ||
#ifdef __ANDROID__
ffStrbufEqualS(&result->processName, "proot") ||
#endif
ffStrbufEndsWithS(&result->processName, ".sh")
)
{
@@ -105,6 +108,9 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "login") ||
ffStrbufEqualS(&result->processName, "clifm") || // https://github.com/leo-arch/clifm/issues/289
ffStrbufEqualS(&result->processName, "chezmoi") || // #762
#ifdef __ANDROID__
ffStrbufEqualS(&result->processName, "proot") ||
#endif
#ifdef __linux__
ffStrbufStartsWithS(&result->processName, "flatpak-") || // #707
#endif
+2
View File
@@ -40,6 +40,8 @@
#define FF_SYSNAME "SunOS"
#elif defined(__OpenBSD__)
#define FF_SYSNAME "OpenBSD"
#elif defined(__NetBSD__)
#define FF_SYSNAME "NetBSD"
#else
#define FF_SYSNAME "unknown"
#endif
+13 -6
View File
@@ -39,13 +39,20 @@ static void applyDriverName(VkPhysicalDeviceDriverPropertiesKHR* properties, FFs
static const char* detectVulkan(FFVulkanResult* result)
{
FF_LIBRARY_LOAD(vulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed",
#ifdef __APPLE__
"libMoltenVK"FF_LIBRARY_EXTENSION, -1
#elif defined(_WIN32)
"vulkan-1"FF_LIBRARY_EXTENSION, -1
FF_LIBRARY_LOAD(vulkan, "dlopen libvulkan" FF_LIBRARY_EXTENSION " failed",
#if __ANDROID__
#if UINTPTR_MAX == UINT32_MAX
"/system/lib/"
#else
"/system/lib64/"
#endif
"libvulkan" FF_LIBRARY_EXTENSION, -1
#elif __APPLE__
"libMoltenVK" FF_LIBRARY_EXTENSION, -1
#elif _WIN32
"vulkan-1" FF_LIBRARY_EXTENSION, -1
#else
"libvulkan"FF_LIBRARY_EXTENSION, 2
"libvulkan" FF_LIBRARY_EXTENSION, 2
#endif
)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr)
+14
View File
@@ -18,6 +18,8 @@ struct FFWifiConnection
double signalQuality; // Percentage
double rxRate;
double txRate;
uint16_t channel;
uint16_t frequency; // MHz
};
typedef struct FFWifiResult
@@ -27,3 +29,15 @@ typedef struct FFWifiResult
} FFWifiResult;
const char* ffDetectWifi(FFlist* result /*list of FFWifiItem*/);
static inline uint16_t ffWifiFreqToChannel(uint16_t frequency)
{
// https://github.com/opetryna/win32wifi/blob/master/win32wifi/Win32Wifi.py#L140
// FIXME: Does it work for 6 GHz?
if (frequency == 2484)
return 14;
else if (frequency < 2484)
return (uint16_t) ((frequency - 2407) / 5);
else
return (uint16_t) ((frequency / 5) - 1000);
}
+5
View File
@@ -43,6 +43,8 @@ const char* ffDetectWifi(FFlist* result)
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
ffStrbufAppendS(&item->inf.status, yyjson_get_str(yyjson_obj_get(root, "supplicant_state")));
if(!item->inf.status.length)
@@ -60,6 +62,9 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufAppendS(&item->inf.description, yyjson_get_str(yyjson_obj_get(root, "ip")));
ffStrbufAppendS(&item->conn.bssid, yyjson_get_str(yyjson_obj_get(root, "bssid")));
ffStrbufAppendS(&item->conn.ssid, yyjson_get_str(yyjson_obj_get(root, "ssid")));
item->conn.frequency = (uint16_t) yyjson_get_int(yyjson_obj_get(root, "frequency_mhz"));
item->conn.txRate = yyjson_get_num(yyjson_obj_get(root, "link_speed_mbps"));
item->conn.channel = ffWifiFreqToChannel(item->conn.frequency);
return NULL;
}
+11
View File
@@ -80,6 +80,8 @@ const char* ffDetectWifi(FFlist* result)
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String);
ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off");
@@ -289,6 +291,15 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security);
break;
}
item->conn.channel = (uint16_t) inf.wlanChannel.channelNumber;
switch (inf.wlanChannel.channelBand)
{
case kCWChannelBand2GHz: item->conn.frequency = 2400; break;
case kCWChannelBand5GHz: item->conn.frequency = 5400; break;
case 3 /*kCWChannelBand6GHz*/: item->conn.frequency = 6400; break;
default: item->conn.frequency = 0; break;
}
}
return NULL;
}
+19 -7
View File
@@ -34,18 +34,32 @@ const char* ffDetectWifi(FFlist* result)
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
ffParsePropLines(ifconfig.chars, "status: ", &item->conn.status);
if (!ffStrbufEqualS(&item->conn.status, "associated"))
continue;
ffParsePropLines(ifconfig.chars, "ssid ", &item->conn.ssid);
if (item->conn.ssid.length)
{
uint32_t ibssid = ffStrbufFirstIndexS(&item->conn.ssid, " bssid ");
if (ibssid < item->conn.ssid.length)
// This doesn't work for quoted SSID values
uint32_t idx = ffStrbufFirstIndexS(&item->conn.ssid, " bssid ");
if (idx < item->conn.ssid.length)
{
ibssid += (uint32_t) strlen(" bssid ");
ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + ibssid);
ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + idx + (uint32_t) strlen(" bssid "));
ffStrbufSubstrBefore(&item->conn.ssid, idx);
}
ffStrbufSubstrBeforeFirstC(&item->conn.ssid, ' ');
idx = ffStrbufFirstIndexS(&item->conn.ssid, " channel ");
if (idx < item->conn.ssid.length)
{
const char* pchannel = item->conn.ssid.chars + idx + strlen(" channel ");
sscanf(pchannel, "%hu (%hu MHz %*s)", &item->conn.channel, &item->conn.frequency);
}
ffStrbufSubstrBefore(&item->conn.ssid, idx);
}
ffParsePropLines(ifconfig.chars, "media: ", &item->conn.protocol);
@@ -60,8 +74,6 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufPrependS(&item->conn.protocol, "802.");
}
}
ffParsePropLines(ifconfig.chars, "status: ", &item->conn.status);
}
}
+112 -14
View File
@@ -36,6 +36,13 @@ typedef enum {
NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000,
} NM80211ApSecurityFlags;
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
{ \
if(!(dbus).lib->ffdbus_message_iter_next(iterator)) \
break; \
continue; \
}
static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer)
{
FFDBusData dbus;
@@ -72,24 +79,80 @@ static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer)
if (!item->conn.status.length)
ffStrbufSetStatic(&item->conn.status, "connected");
if (!item->conn.ssid.length)
ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Ssid", &item->conn.ssid);
DBusMessage* reply = ffDBusGetAllProperties(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint");
if(reply == NULL)
return "Failed to get access point properties";
if (!item->conn.bssid.length)
ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "HwAddress", &item->conn.bssid);
if (item->conn.signalQuality != item->conn.signalQuality)
DBusMessageIter rootIterator;
if(!dbus.lib->ffdbus_message_iter_init(reply, &rootIterator) &&
dbus.lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
{
uint32_t strengthPercent;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Strength", &strengthPercent))
item->conn.signalQuality = strengthPercent;
dbus.lib->ffdbus_message_unref(reply);
return "Invalid type of access point properties";
}
DBusMessageIter arrayIterator;
dbus.lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
NM80211ApFlags flags;
NM80211ApSecurityFlags wpaFlags, rsnFlags;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Flags", &flags) &&
ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "WpaFlags", &wpaFlags) &&
ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars , "org.freedesktop.NetworkManager.AccessPoint", "RsnFlags", &rsnFlags))
int flagCount = 0;
while(true)
{
if(dbus.lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
FF_DBUS_ITER_CONTINUE(dbus, &arrayIterator)
DBusMessageIter dictIterator;
dbus.lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
const char* key;
dbus.lib->ffdbus_message_iter_get_basic(&dictIterator, &key);
dbus.lib->ffdbus_message_iter_next(&dictIterator);
if (ffStrEquals(key, "Ssid"))
{
if (!item->conn.ssid.length)
ffDBusGetString(&dbus, &dictIterator, &item->conn.ssid);
}
else if (ffStrEquals(key, "HwAddress"))
{
if (!item->conn.bssid.length)
ffDBusGetString(&dbus, &dictIterator, &item->conn.bssid);
}
else if (ffStrEquals(key, "Strength"))
{
if (item->conn.signalQuality != item->conn.signalQuality)
{
uint32_t strengthPercent;
if (ffDBusGetUint(&dbus, &dictIterator, &strengthPercent))
item->conn.signalQuality = strengthPercent;
}
}
else if (ffStrEquals(key, "Frequency"))
{
if (item->conn.frequency == 0)
{
uint32_t frequency;
if (ffDBusGetUint(&dbus, &dictIterator, &frequency))
{
item->conn.frequency = (uint16_t) frequency;
if (item->conn.channel == 0)
item->conn.channel = ffWifiFreqToChannel(item->conn.frequency);
}
}
}
else if ((ffStrEquals(key, "Flags") && ffDBusGetUint(&dbus, &dictIterator, &flags)) ||
(ffStrEquals(key, "WpaFlags") && ffDBusGetUint(&dbus, &dictIterator, &wpaFlags)) ||
(ffStrEquals(key, "RsnFlags") && ffDBusGetUint(&dbus, &dictIterator, &rsnFlags))
)
++flagCount;
FF_DBUS_ITER_CONTINUE(dbus, &arrayIterator)
}
if (flagCount == 3)
{
if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE)
&& (rsnFlags == NM_802_11_AP_SEC_NONE))
@@ -166,7 +229,9 @@ static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer)
{
item->conn.txRate = ffStrbufToDouble(buffer);
if(ffStrbufContainS(buffer, " HE-MCS "))
if(ffStrbufContainS(buffer, " EHT-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)");
else if(ffStrbufContainS(buffer, " HE-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else if(ffStrbufContainS(buffer, " VHT-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
@@ -174,6 +239,13 @@ static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer)
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
}
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "freq: ", buffer))
{
item->conn.frequency = (uint16_t) ffStrbufToUInt(buffer, 0);
item->conn.channel = ffWifiFreqToChannel(item->conn.frequency);
}
return NULL;
}
@@ -213,12 +285,36 @@ static const char* detectWifiWithIoctls(FFWifiResult* item)
{
for(int i = 0; i < 6; ++i)
ffStrbufAppendF(&item->conn.bssid, "%.2X:", (uint8_t) iwr.u.ap_addr.sa_data[i]);
ffStrbufTrimRight(&item->conn.bssid, '-');
ffStrbufTrimRight(&item->conn.bssid, ':');
}
if(ioctl(sock, SIOCGIWRATE, &iwr) >= 0)
item->conn.txRate = iwr.u.bitrate.value / 1000000.;
if(ioctl(sock, SIOCGIWFREQ, &iwr) >= 0)
{
if (iwr.u.freq.e == 0 && iwr.u.freq.m <= 1000)
{
item->conn.channel = (uint16_t) iwr.u.freq.m;
}
else
{
// convert it to MHz
while (iwr.u.freq.e < 6)
{
iwr.u.freq.m /= 10;
iwr.u.freq.e++;
}
while (iwr.u.freq.e > 6)
{
iwr.u.freq.m *= 10;
iwr.u.freq.e--;
}
item->conn.frequency = (uint16_t) iwr.u.freq.m;
item->conn.channel = ffWifiFreqToChannel(item->conn.frequency);
}
}
struct iw_statistics stats;
iwr.u.data.pointer = &stats;
iwr.u.data.length = sizeof(stats);
@@ -289,6 +385,8 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result)
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name);
if (!ffAppendFileBuffer(buffer.chars, &item->inf.status))
+38 -8
View File
@@ -49,6 +49,7 @@ const char* ffDetectWifi(FFlist* result)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanQueryInterface)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanFreeMemory)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanCloseHandle)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanGetNetworkBssList)
DWORD curVersion;
HANDLE hClient = NULL;
@@ -82,21 +83,23 @@ const char* ffDetectWifi(FFlist* result)
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
convertIfStateToString(ifInfo->isState, &item->inf.status);
if(ifInfo->isState != wlan_interface_state_connected)
continue;
DWORD connectInfoSize = sizeof(WLAN_CONNECTION_ATTRIBUTES);
WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid;
WLAN_CONNECTION_ATTRIBUTES* connInfo = NULL;
DWORD bufSize = sizeof(*connInfo);
WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_query_only;
if(ffWlanQueryInterface(hClient,
&ifInfo->InterfaceGuid,
wlan_intf_opcode_current_connection,
NULL,
&connectInfoSize,
&bufSize,
(PVOID*)&connInfo,
&opCode) != ERROR_SUCCESS
) continue;
@@ -107,8 +110,8 @@ const char* ffDetectWifi(FFlist* result)
(const char *)connInfo->wlanAssociationAttributes.dot11Ssid.ucSSID);
for (size_t i = 0; i < sizeof(connInfo->wlanAssociationAttributes.dot11Bssid); i++)
ffStrbufAppendF(&item->conn.bssid, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]);
ffStrbufTrimRight(&item->conn.bssid, '-');
ffStrbufAppendF(&item->conn.bssid, "%.2X:", connInfo->wlanAssociationAttributes.dot11Bssid[i]);
ffStrbufTrimRight(&item->conn.bssid, ':');
switch (connInfo->wlanAssociationAttributes.dot11PhyType)
{
@@ -151,8 +154,8 @@ const char* ffDetectWifi(FFlist* result)
}
item->conn.signalQuality = connInfo->wlanAssociationAttributes.wlanSignalQuality;
item->conn.rxRate = connInfo->wlanAssociationAttributes.ulRxRate;
item->conn.txRate = connInfo->wlanAssociationAttributes.ulTxRate;
item->conn.rxRate = connInfo->wlanAssociationAttributes.ulRxRate / 1000.;
item->conn.txRate = connInfo->wlanAssociationAttributes.ulTxRate / 1000.;
if(connInfo->wlanSecurityAttributes.bSecurityEnabled)
{
@@ -189,7 +192,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufAppendS(&item->conn.security, "OWE");
break;
case 11 /* DOT11_AUTH_ALGO_WPA3_ENT */:
ffStrbufAppendS(&item->conn.security, "OWE-ENT");
ffStrbufAppendS(&item->conn.security, "WPA3-ENT");
break;
default:
ffStrbufAppendF(&item->conn.security, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11AuthAlgorithm);
@@ -201,7 +204,34 @@ const char* ffDetectWifi(FFlist* result)
else
ffStrbufAppendS(&item->conn.security, "Insecure");
WLAN_BSS_LIST* bssList = NULL;
if (ffWlanGetNetworkBssList(hClient,
&ifInfo->InterfaceGuid,
&connInfo->wlanAssociationAttributes.dot11Ssid,
connInfo->wlanAssociationAttributes.dot11BssType,
connInfo->wlanSecurityAttributes.bSecurityEnabled,
NULL,
&bssList) == ERROR_SUCCESS && bssList->dwNumberOfItems > 0
) {
item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000);
ffWlanFreeMemory(bssList);
}
ffWlanFreeMemory(connInfo);
ULONG* channelNumber = 0;
bufSize = sizeof(*channelNumber);
if(ffWlanQueryInterface(hClient,
&ifInfo->InterfaceGuid,
wlan_intf_opcode_channel_number,
NULL,
&bufSize,
(PVOID*)&channelNumber,
&opCode) == ERROR_SUCCESS
) {
item->conn.channel = (uint16_t) *channelNumber;
ffWlanFreeMemory(channelNumber);
}
}
exit:
+54 -2
View File
@@ -2,6 +2,7 @@
#include "common/commandoption.h"
#include "common/io/io.h"
#include "common/jsonconfig.h"
#include "common/printing.h"
#include "detection/version/version.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
@@ -15,16 +16,65 @@
#include "util/windows/getline.h"
#endif
static void printCommandFormatHelpJson(void)
{
yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val* root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
for (uint32_t i = 0; i <= 'Z' - 'A'; ++i)
{
for (FFModuleBaseInfo** modules = ffModuleInfos[i]; *modules; ++modules)
{
FFModuleBaseInfo* baseInfo = *modules;
if (!baseInfo->formatArgs.count) continue;
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&type);
ffStrbufAppendS(&type, "Format");
yyjson_mut_val* obj = yyjson_mut_obj(doc);
if (yyjson_mut_obj_add(root, yyjson_mut_strbuf(doc, &type), obj))
{
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreateF("Output format of the module `%s`. See `-h format` for formatting syntax\n", baseInfo->name);
for (unsigned i = 0; i < baseInfo->formatArgs.count; i++)
{
const FFModuleFormatArg* arg = &baseInfo->formatArgs.args[i];
ffStrbufAppendF(&content, " %u. {%s}: %s\n", i + 1, arg->name, arg->desc);
}
ffStrbufTrimRight(&content, '\n');
yyjson_mut_obj_add_strbuf(doc, obj, "description", &content);
yyjson_mut_obj_add_str(doc, obj, "type", "string");
}
}
}
yyjson_mut_write_fp(stdout, doc, YYJSON_WRITE_PRETTY, NULL, NULL);
putchar('\n');
yyjson_mut_doc_free(doc);
}
static void printCommandFormatHelp(const char* command)
{
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateNS((uint32_t) (strlen(command) - strlen("-format")), command);
ffStrbufLowerCase(&type);
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(command[0]) - 'A']; *modules; ++modules)
{
FFModuleBaseInfo* baseInfo = *modules;
if (ffStrbufIgnCaseEqualS(&type, baseInfo->name))
{
if (baseInfo->printHelpFormat)
baseInfo->printHelpFormat();
if (baseInfo->formatArgs.count > 0)
{
printf("--%s-format:\n", type.chars);
printf("Sets the format string for %s output.\n", baseInfo->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 < baseInfo->formatArgs.count; i++)
{
const FFModuleFormatArg* arg = &baseInfo->formatArgs.args[i];
printf("%16s {%u}: %s\n", arg->name, i + 1, arg->desc);
}
}
else
fprintf(stderr, "Error: Module '%s' doesn't support output formatting\n", baseInfo->name);
return;
@@ -252,6 +302,8 @@ static void printCommandHelp(const char* command)
puts(FASTFETCH_DATATEXT_HELP_COLOR);
else if(ffStrEqualsIgnCase(command, "format"))
puts(FASTFETCH_DATATEXT_HELP_FORMAT);
else if(ffStrEqualsIgnCase(command, "format-json"))
printCommandFormatHelpJson();
else if(ffCharIsEnglishAlphabet(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // <module>-format
printCommandFormatHelp(command);
else if(!printSpecificCommandHelp(command))
+9 -9
View File
@@ -1,17 +1,17 @@
$2_,met$$$$$$$$$$gg.
,g$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$P.
,g$$$$P" """Y$$$$.".
,$$$$P' `$$$$$$.
$2_,met$$$$$$$$$$gg.
,g$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$P.
,g$$$$P"" """Y$$$$.".
,$$$$P' `$$$$$$.
',$$$$P ,ggs. `$$$$b:
`d$$$$' ,$P"' $1.$2 $$$$$$
$$$$P d$' $1,$2 $$$$$$P
$$$$: $$. $1-$2 ,d$$$$'
$$$$P d$' $1,$2 $$$$P
$$$$: $$$. $1-$2 ,d$$$$'
$$$$; Y$b._ _,d$P'
Y$$$$. $1`.$2`"Y$$$$$$$$P"'
`$$$$b $1"-.__
$2`Y$$$$
$2`Y$$$$b
`Y$$$$.
`$$$$b.
`Y$$$$b.
`"Y$$b._
`"""
`"Y$$b._
`""""
+11
View File
@@ -0,0 +1,11 @@
.7J~
~G@&#5^ .^.
:5&&&&##B?. !B&G7
7B##&&B##BBP~ ^P&@&##P~
$2^YGP5PBPPP5YY55?: .7GGGB#BPPP7.
.?PPPPPPPPPP55YYY5Y!.^YPPPPPP5YYY5J~
!PPPPPPPPPPPPPP5YYYY5JY5PPPPPPP55YY55?:
^YPPPPPPPPPPPPPPPPYYYYYYYYY5PPPPPPP5YYY5Y!.
.7PPPPPPPPPPPPPPPPPP5YYYYYYYYY55PPPPP5YYYYY5J~
!5GPPPPPPPPPPPPPPPPPPPP55555555YY5PPPPPP5555555?:
7777777777777777777777777!!!!!!!!!77777777!!!!!7!:
+17 -17
View File
@@ -1,20 +1,20 @@
,xXc
.l0MMMMMO
.kNMMMMMWMMMN,
KMMMMMMKMMMMMMo
'MMMMMMNKMMMMMM:
kMMMMMMOMMMMMMO
.MMMMMMX0MMMMMW.
oMMMMMMxWMMMMM:
WMMMMMNkMMMMMO
:MMMMMMOXMMMMW
.0MMMMMxMMMMM;
:;cKMMWxMMMMO
'MMWMMXOMMMMl
kMMMMKOMMMMMX:
.WMMMMKOWMMM0c
lMMMMMWO0MNd:'
oollXMKXoxl;.
':. .: .'
..
.kNMMMMM$2W$1MMMN,
KMMMMMM$2K$1MMMMMMo
'MMMMMMN$2K$1MMMMMM:
kMMMMMM$2O$1MMMMMMO
.MMMMMM$20$1XMMMMMW.
oMMMMM$2x$1MMMMMMM:
WMMMMM$2x$1MMMMMMO
:MMMMMM$2O$1XMMMMW
.0MMMMM$2x$1MMMMM;
:;cKMMW$2x$1MMMMO
'MMWMMX$2O$1MMMMl
kMMMMK$2O$1MMMMMX:
.WMMMMK$2O$1WMMM0c
lMMMMMW$2O$1WMNd:'
oollXMK$2o$1Xxl;.
':. .:$2 .$1'
$2..
.
+5 -5
View File
@@ -1,7 +1,7 @@
${c1} /\\
/ \\
/ ${c2}/ ${c1}/
> ${c2}/ ${c1}/
/\\
/ \\
/ ${c2}/ ${c1}/
> ${c2}/ ${c1}/
\\ ${c2}\\ ${c1}\\
\\_${c2}\\${c1}_\\
${c2} \\
${c2} \\
+20 -20
View File
@@ -1,20 +1,20 @@
.:=+*#%%@@@@@@%%#*+=:.
.=*%@@@@@@@@@@@@@@@@@@@@@@%*=:
.=%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+.
:*@@@@@@@@@@@@@@@@@$2++$1%@@@@@@@@@@@@@@@@#-
.*@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@#.
-%@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@-
-@@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@@=
:@@@@@@@@@@@@@@@@@%%@@@%$2..$1#@@@@#@@@@@@@@@@@@@@@@@:
*@@@@@@@@@@@@#$2*=:..$1*@@@%$2..$1#@@@#$2..:=+$1#@@@@@@@@@@@@*
%@@@@@@@#+$2=:...-+$1#@@@@@%$2..$1#@@@@@#$2+=:..:-$1+#@@@@@@@%
%@@@@@$2:..:=+-..-+$1#@@@@@%$2..$1#@@@@@%$2+-..-+=:..:$1@@@@@@
*@@@@@$2*%$1@@@@@@%$2+-..$1#@@@%$2..$1#@@@%$2..-+$1#@@@@@@$2%*$1@@@@@*
:@@@@@@@@@@@@@@@@@$2#%$1@@@%$2..$1#@@@$2%#$1@@@@@@@@@@@@@@@@@:
=@@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@@=
-@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@=
.*@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@#:
:*@@@@@@@@@@@@@@@@@$2==$1%@@@@@@@@@@@@@@@@#-.
.+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+:
:=*%@@@@@@@@@@@@@@@@@@@@@@%*=:.
.-=+*#%%@@@@@@%%#*+=-.
▁▂▃▄▅▆▇▇████▇▇▆▅▄▃▂▁
▃▅▇████████████████████▇▅▃
▂▅████████████████████████████▅▁
▗▟██████████████▛▀▀▜██████████████▙▖
▗▟████████████████▌ ▐████████████████▙▖
▗██████████████████▌ ▐██████████████████▖
▗███████████████████▌ ▐███████████████████▖
▕███████████████▀▘ ██▌ ▐██ ▝▀███████████████▏
▐██████████▛▀▀ ▂██▌ ▐██▂ ▀▀▜██████████▌
███████▀▀ ▁▄▆████▌ ▐████▆▄▁ ▀▀███████
█████ ▂▄▂ ▔▀▜████▌ ▐████▛▀▔ ▂▄▂ █████
▐████▄▄▆█████▄▂ ▔▀██▌ ▐██▀▔ ▂▄█████▆▄▄████▌
▕██████████████▇▄▂ ██▌ ▐██ ▂▄▇██████████████▏
▝███████████████████▌ ▐███████████████████▘
▝██████████████████▌ ▐██████████████████▘
▝▜████████████████▌ ▐████████████████▛▘
▝▜██████████████▙▄▄▟██████████████▛▘
▔▀▜██████████████████████████▛▀▔
▔▀▜████████████████████▛▀▔
▔▔▀▀▀▜██████▛▀▀▀▔▔
+20
View File
@@ -0,0 +1,20 @@
.:=+*#%%@@@@@@%%#*+=:.
.=*%@@@@@@@@@@@@@@@@@@@@@@%*=:
.=%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+.
:*@@@@@@@@@@@@@@@@@$2++$1%@@@@@@@@@@@@@@@@#-
.*@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@#.
-%@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@-
-@@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@@=
:@@@@@@@@@@@@@@@@@%%@@@%$2..$1#@@@@#@@@@@@@@@@@@@@@@@:
*@@@@@@@@@@@@#$2*=:..$1*@@@%$2..$1#@@@#$2..:=+$1#@@@@@@@@@@@@*
%@@@@@@@#+$2=:...-+$1#@@@@@%$2..$1#@@@@@#$2+=:..:-$1+#@@@@@@@%
%@@@@@$2:..:=+-..-+$1#@@@@@%$2..$1#@@@@@%$2+-..-+=:..:$1@@@@@@
*@@@@@$2*%$1@@@@@@%$2+-..$1#@@@%$2..$1#@@@%$2..-+$1#@@@@@@$2%*$1@@@@@*
:@@@@@@@@@@@@@@@@@$2#%$1@@@%$2..$1#@@@$2%#$1@@@@@@@@@@@@@@@@@:
=@@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@@=
-@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@=
.*@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@#:
:*@@@@@@@@@@@@@@@@@$2==$1%@@@@@@@@@@@@@@@@#-.
.+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+:
:=*%@@@@@@@@@@@@@@@@@@@@@@%*=:.
.-=+*#%%@@@@@@%%#*+=-.
+12
View File
@@ -0,0 +1,12 @@
___╓╓___
_▄▄▓▓▀▀╜╜╨▀▓▓▓╗_
╓▓▓▀² `╙▓▓╖
╣▓▀ _▄▓▓▓▓▓▓W_ ╙▓▓
╣▓╜ ,▓▓▓▓▓▓▓▓▓▓▓▓_ ²▓▓
╒▓▌ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║▓m
╞▓▓ í▓▓▓▓▓▓▓▓▓▓▓▓▓▓h ╞▓╡
²▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ║▓h
║▓▄ ╙▓▓▓▓▓▓▓▓▓▓╜ ƒ▓▓
╙▓▓_ ⁿ╙╨╝╝╝╜² _╢▓╜
╙▓▓╗__ _╗▓▓╜
`╙╝▓▓▓▓▓▓▓▓╝╙
+18
View File
@@ -0,0 +1,18 @@
,dKNWWNKOxo;.
;xKXOdoloOWMWX0d:.
.dNNd' cNMMMMNKOx;.
.dWNo .:oxO000KXKl.
.OMNl .....
oNMXd,.
.lKWMNKkdollccc:::;;;,'..
.;ox0KNWWMMMMMMMMWWWWNK0xl,.
..,;:ccloodxO0KNWMMMMNOc.
.';lxKWMMWk'
..,:ccc:,. .oXMMMO
.:d0NWWWWWMWXOo,. .,cc:;,,'..oWMMW
.c0WW0xl:;,;cd0NMNO:'..ldl;. .'.:XMMM
xWMKc. .;OWMWX0xl. .dWMMK
WMWd. .oKWMMXx, .dNMMXc
NMMK:. ..:oxo:oOXMMNOdc:;;cxKWMWO;
;kXWN0xooodkOOko;. .lONMMMMWWMMWKx;.
,okKXXXKOxc'. .:kKWMMWXOl'
+14
View File
@@ -0,0 +1,14 @@
@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@*=+*%@@@@@@@@@@@@
@@@@@@@@@@: :#@@@@@@@@@@
@@@@@@@@@# -#@@@@@@@@
@@%###*=. :=*#@@@@
@@= =@@
@@= -@@
@@*: :*@@
@%*=: :=*@@
@@@%%##%%@@@
+17
View File
@@ -0,0 +1,17 @@
$1 ##%%%%%%%%% $2%%%%%%%%%##
$1 ###%%%%%%%%%% $2%%%%%%%%%%###
$1 ####%%%%%%%%%%% $2%%%%%%%%%%%####
$1 ##%%%%%%%%%%%%%% $2%%%%%%%%%%%%%%##
$1#%%%%%%%%%%%%%%%% $2%%%%%%%%%%%%%%%%#
$1%%%%%%%%%%%%%%%%% $2%%%%%%%%%%%%%%%%%
$1%%%%%%%%%%%%%%%%% $2%%%%%%%%%%%%%%%%%
$1%%%%%%%%%%%%%%%%% $2#%%%%%%%%%%%%%%%%
$3%%%%%%%%%%%%%%%%% $4#%%%%%%%%%%%%%%%%
$3%%%%%%%%%%%%%%%%% $4%%%%%%%%%%%%%%%%%
$3%%%%%%%%%%%%%%%%% $4%%%%%%%%%%%%%%%%%
$3%%%%%%%%%%%%%%%%% $4%%%%%%%%%%%%%%%%#
$3 ###%%%%%%%%%%%%% $4%%%%%%%%%%%%%%%##
$3 ####%%%%%%%%%%% $4%%%%%%%%%%%#%####
$3 ##%#%%%%%%%%% $4%%%%%%%%%%%######
$3 ##%%%%%%%%% $4%%%%%%%%%########
+63 -4
View File
@@ -1912,6 +1912,15 @@ static const FFlogo G[] = {
.colorKeys = FF_COLOR_FG_MAGENTA,
.colorTitle = FF_COLOR_FG_WHITE,
},
// GoralixOS
{
.names = {"GoralixOS"},
.lines = FASTFETCH_DATATEXT_LOGO_GORALIXOS,
.colors = {
FF_COLOR_FG_WHITE,
FF_COLOR_FG_LIGHT_BLACK,
},
},
// GrapheneOS
{
.names = {"GrapheneOS"},
@@ -2477,10 +2486,10 @@ static const FFlogo L[] = {
.names = {"LinuxLite", "Linux Lite", "linux_lite"},
.lines = FASTFETCH_DATATEXT_LOGO_LINUXLITE,
.colors = {
FF_COLOR_FG_YELLOW,
FF_COLOR_FG_GREEN,
FF_COLOR_FG_WHITE,
},
.colorKeys = FF_COLOR_FG_YELLOW,
.colorKeys = FF_COLOR_FG_GREEN,
.colorTitle = FF_COLOR_FG_WHITE,
},
// LinuxLightSmall
@@ -2489,10 +2498,10 @@ static const FFlogo L[] = {
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_LINUXLITE_SMALL,
.colors = {
FF_COLOR_FG_YELLOW,
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
.colorKeys = FF_COLOR_FG_YELLOW,
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_WHITE,
},
// LinuxMint
@@ -2837,6 +2846,17 @@ static const FFlogo M[] = {
{
.names = {"MidOS"},
.lines = FASTFETCH_DATATEXT_LOGO_MIDOS,
.colors = {
FF_COLOR_FG_LIGHT_BLACK,
},
.colorKeys = FF_COLOR_FG_LIGHT_BLACK,
.colorTitle = FF_COLOR_FG_WHITE,
},
// MidOSOld
{
.names = {"MidOS_old"},
.lines = FASTFETCH_DATATEXT_LOGO_MIDOS_OLD,
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
.colors = {
FF_COLOR_FG_LIGHT_BLACK,
FF_COLOR_FG_WHITE,
@@ -3075,6 +3095,15 @@ static const FFlogo N[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_WHITE,
},
// NurOS
{
.names = {"NurOS"},
.lines = FASTFETCH_DATATEXT_LOGO_NUROS,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
},
// Nurunner
{
.names = {"Nurunner"},
@@ -4041,6 +4070,14 @@ static const FFlogo S[] = {
FF_COLOR_FG_RED,
},
},
// Serpent OS
{
.names = {"Serpent OS"},
.lines = FASTFETCH_DATATEXT_LOGO_SERPENT_OS,
.colors = {
FF_COLOR_FG_WHITE,
},
},
// Semc
{
.names = {"semc"},
@@ -4616,6 +4653,15 @@ static const FFlogo U[] = {
FF_COLOR_FG_WHITE,
},
},
// Ultramarine Small
{
.names = {"Ultramarine_small"},
.lines = FASTFETCH_DATATEXT_LOGO_ULTRAMARINE_SMALL,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
},
// Unifi
{
.names = {"Unifi"},
@@ -4809,6 +4855,19 @@ static const FFlogo W[] = {
FF_COLOR_FG_WHITE,
},
},
// Windows2025
{
.names = {"Windows Server 2025"},
.lines = FASTFETCH_DATATEXT_LOGO_WINDOWS_2025,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_BLUE,
FF_COLOR_FG_BLUE,
FF_COLOR_FG_BLUE,
},
.colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_CYAN,
},
// Windows11
{
.names = {"Windows 11", "Windows Server 2022"},
+28 -34
View File
@@ -7,8 +7,6 @@
#include "modules/battery/battery.h"
#include "util/stringUtils.h"
#define FF_BATTERY_NUM_FORMAT_ARGS 14
static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index)
{
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
@@ -22,7 +20,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
else
{
ffStrbufClear(&key);
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 2, ((FFformatarg[]){
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
FF_FORMAT_ARG(index, "index"),
FF_FORMAT_ARG(result->modelName, "name"),
}));
@@ -105,7 +103,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
ffTempsAppendNum(result->temperature, &tempStr, options->tempConfig, &options->moduleArgs);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BATTERY_NUM_FORMAT_ARGS, ((FFformatarg[]) {
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
FF_FORMAT_ARG(result->manufacturer, "manufacturer"),
FF_FORMAT_ARG(result->modelName, "model-name"),
FF_FORMAT_ARG(result->technology, "technology"),
@@ -270,39 +268,35 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc,
}
}
void ffPrintBatteryHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BATTERY_MODULE_NAME, "{4} ({12} hours {13} mins) [{5}]", FF_BATTERY_NUM_FORMAT_ARGS, ((const char* []) {
"Battery manufacturer - manufacturer",
"Battery model name - model-name",
"Battery technology - technology",
"Battery capacity (percentage num) - capacity",
"Battery status - status",
"Battery temperature (formatted) - temperature",
"Battery cycle count - cycle-count",
"Battery serial number - serial",
"Battery manufactor date - manufacture-date",
"Battery capacity (percentage bar) - capacity-bar",
"Battery time remaining days - time-days",
"Battery time remaining hours - time-hours",
"Battery time remaining minutes - time-minutes",
"Battery time remaining seconds - time-seconds",
}));
}
static FFModuleBaseInfo ffModuleInfo = {
.name = FF_BATTERY_MODULE_NAME,
.description = "Print battery capacity, status, etc",
.parseCommandOptions = (void*) ffParseBatteryCommandOptions,
.parseJsonObject = (void*) ffParseBatteryJsonObject,
.printModule = (void*) ffPrintBattery,
.generateJsonResult = (void*) ffGenerateBatteryJsonResult,
.generateJsonConfig = (void*) ffGenerateBatteryJsonConfig,
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
{"Battery manufacturer", "manufacturer"},
{"Battery model name", "model-name"},
{"Battery technology", "technology"},
{"Battery capacity (percentage num)", "capacity"},
{"Battery status", "status"},
{"Battery temperature (formatted)", "temperature"},
{"Battery cycle count", "cycle-count"},
{"Battery serial number", "serial"},
{"Battery manufactor date", "manufacture-date"},
{"Battery capacity (percentage bar)", "capacity-bar"},
{"Battery time remaining days", "time-days"},
{"Battery time remaining hours", "time-hours"},
{"Battery time remaining minutes", "time-minutes"},
{"Battery time remaining seconds", "time-seconds"},
}))
};
void ffInitBatteryOptions(FFBatteryOptions* options)
{
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_BATTERY_MODULE_NAME,
"Print battery capacity, status, etc",
ffParseBatteryCommandOptions,
ffParseBatteryJsonObject,
ffPrintBattery,
ffGenerateBatteryJsonResult,
ffPrintBatteryHelpFormat,
ffGenerateBatteryJsonConfig
);
options->moduleInfo = ffModuleInfo;
ffOptionInitModuleArg(&options->moduleArgs, "");
options->temp = false;
options->tempConfig = (FFColorRangeConfig) { 60, 80 };
+19 -25
View File
@@ -4,8 +4,6 @@
#include "modules/bios/bios.h"
#include "util/stringUtils.h"
#define FF_BIOS_NUM_FORMAT_ARGS 5
void ffPrintBios(FFBiosOptions* options)
{
FFBiosResult bios;
@@ -43,7 +41,7 @@ void ffPrintBios(FFBiosOptions* options)
else
{
ffStrbufClear(&key);
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 2, ((FFformatarg[]){
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
FF_FORMAT_ARG(bios.type, "type"),
FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"),
}));
@@ -60,7 +58,7 @@ void ffPrintBios(FFBiosOptions* options)
}
else
{
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BIOS_NUM_FORMAT_ARGS, ((FFformatarg[]) {
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
FF_FORMAT_ARG(bios.date, "date"),
FF_FORMAT_ARG(bios.release, "release"),
FF_FORMAT_ARG(bios.vendor, "vendor"),
@@ -144,30 +142,26 @@ exit:
ffStrbufDestroy(&bios.type);
}
void ffPrintBiosHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BIOS_MODULE_NAME, "{4} ({2})", FF_BIOS_NUM_FORMAT_ARGS, ((const char* []) {
"bios date - date",
"bios release - release",
"bios vendor - vendor",
"bios version - version",
"firmware type - type",
}));
}
static FFModuleBaseInfo ffModuleInfo = {
.name = FF_BIOS_MODULE_NAME,
.description = "Print information of 1st-stage bootloader (name, version, release date, etc)",
.parseCommandOptions = (void*) ffParseBiosCommandOptions,
.parseJsonObject = (void*) ffParseBiosJsonObject,
.printModule = (void*) ffPrintBios,
.generateJsonResult = (void*) ffGenerateBiosJsonResult,
.generateJsonConfig = (void*) ffGenerateBiosJsonConfig,
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
{"Bios date", "date"},
{"Bios release", "release"},
{"Bios vendor", "vendor"},
{"Bios version", "version"},
{"Firmware type", "type"},
}))
};
void ffInitBiosOptions(FFBiosOptions* options)
{
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_BIOS_MODULE_NAME,
"Print information of 1st-stage bootloader (name, version, release date, etc)",
ffParseBiosCommandOptions,
ffParseBiosJsonObject,
ffPrintBios,
ffGenerateBiosJsonResult,
ffPrintBiosHelpFormat,
ffGenerateBiosJsonConfig
);
options->moduleInfo = ffModuleInfo;
ffOptionInitModuleArg(&options->moduleArgs, "");
}

Some files were not shown because too many files have changed in this diff Show More