Compare commits

..

158 Commits

Author SHA1 Message Date
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
Carter Li 62dcd1257e Merge pull request #1401 from fastfetch-cli/dev
Release: v2.30.0
2024-11-18 09:21:24 +08:00
Carter Li dbb6a4b265 Release: v2.30.0 2024-11-18 09:04:17 +08:00
Carter Li a73a3089af Doc: remove guix package installer as it's outdated [ci skip] 2024-11-18 08:40:45 +08:00
李通洲 dcdf2b570e Display: concat flags 2024-11-15 20:01:56 +08:00
李通洲 ba7d3ed27b GPU (Windows): fix a bad assignment 2024-11-15 19:47:24 +08:00
Carter Li b7a9fe58b4 Terminal (Linux): support tilix version detection 2024-11-15 16:18:43 +08:00
李通洲 e5451b6826 NetIO (BSD): remove unnecessary checks
Seems...
2024-11-15 15:13:09 +08:00
李通洲 9f314a208b NetIO (BSD): add txDrops detection if supported 2024-11-15 15:13:09 +08:00
李通洲 56eb8b80c6 NetIO (macOS): fix 32bit trancation 2024-11-15 15:11:55 +08:00
Dariqq 563ed58b4f Scripts: gen-man.py honors SOURCE_DATE_EPOCH. (#1400) 2024-11-15 08:50:47 +08:00
李通洲 b8ec07092a Logo (Builtin): update openSUSE Tumbleweed
Fix #1398
2024-11-15 08:41:14 +08:00
李通洲 e77a4e8262 Doc: update changelog [ci skip] 2024-11-14 16:40:45 +08:00
李通洲 782af250ff Percent: in custom format, only set num and bar string if enabled in percent config
Also fix `percentage-bar` printing in Brightness module
2024-11-14 15:45:25 +08:00
李通洲 6801fe3d9c Doc: update schema for percent type config 2024-11-14 14:26:18 +08:00
李通洲 1c41c6ccb1 Percent: allow use enum to set type value in JSON config 2024-11-14 14:21:55 +08:00
李通洲 c9e3f8d95c Global: support percent type config in module level 2024-11-14 13:52:02 +08:00
李通洲 97e1b987dd Global: pack all enums and make flag enums unsigned 2024-11-14 11:00:44 +08:00
Carter Li e821a99873 CPU (Linux): add more Apple SOC code names 2024-11-13 16:44:24 +08:00
李通洲 bad85a557a Host (Android): detect marketing name of vivo smartphone 2024-11-13 15:53:14 +08:00
李通洲 1d92bf864a IO (macOS): fix logo fails to load from symlinked files
Fix #1395
2024-11-13 15:15:50 +08:00
李通洲 2cfc8ec0db Processing (macOS): fix exe path detection 2024-11-13 10:46:30 +08:00
李通洲 5efb87997b Util (macOS): cleanup cf_helpers.c 2024-11-13 10:38:40 +08:00
李通洲 d7fa0417ed CMake: use gen-man.py to generate man file 2024-11-13 10:24:57 +08:00
李通洲 fe57b28581 Scripts: clean up gen-man.py 2024-11-13 10:18:11 +08:00
李通洲 5a1be2535b Scripts: make gen-pciids.py executable 2024-11-13 10:17:06 +08:00
Tibo bccf241816 Scripts: Add python script to generate man page (#1392)
*  Add man generating script

*  Add arguments and description

* 🐛 Add shebang

* 📝 Add documentation & text for sections

* 🐛 Fix italic text (italic is not supported for man pages)

* 🗑️ Remove .1 generated file

* ✏️ Fix type "abbreviation" gen-man.py:24

* 🐛 Fix invalid escape sequence

*  Add version finder

*  Example & config sections

* 🗑️ Delete generated .1 file

---------

Co-authored-by: tgallone <thibaut.gallone@etu.unistra.fr>
2024-11-13 09:13:13 +08:00
李通洲 c70c37c50c GPU (macOS): apply the same logic as CPU just in case 2024-11-12 22:58:22 +08:00
李通洲 644458bc74 CPU (macOS): try fixing CPU freq detection on Apple M4
Fix #1394
2024-11-12 22:34:57 +08:00
李通洲 e618303343 Media (macOS): try fixing error CFStringGetCString() failed 2024-11-12 21:52:12 +08:00
李通洲 748b7df0d7 Smbios: clean up more garbage values
Ref: #1391
2024-11-12 10:45:09 +08:00
李通洲 7c8250c68c StringUtil: rename ffStrCopy and correctly reflect its usage 2024-11-11 18:02:23 +08:00
Carter Li c368908b7d Shell (macOS): try fixing segfault in old macOS
Ref: #1388
2024-11-11 17:49:49 +08:00
李通洲 830c71ddc4 DisplayServer (NetBSD): detect WM / DE by process name 2024-11-11 17:37:01 +08:00
李通洲 5e7d9ed45e Packages (Linux): add qi support 2024-11-11 17:37:01 +08:00
Carter Li 4799f9277e Revert "IO: optimize createSubfolders (#1382)" (#1390)
This reverts commit 0284e4ccc4.
2024-11-11 17:33:22 +08:00
apocelipes 0a61031463 tests: add FFstrbuf smallest allocation test & minor fix (#1387) 2024-11-11 07:58:24 +08:00
Tibo G 07d0743a18 Logo (Builtin): add cosmicDE logo (#1386)
* add cosmicDE logo

* Update cosmic.txt

* Update builtin.c

---------

Co-authored-by: tgallone <thibaut.gallone@etu.unistra.fr>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-11-11 00:43:43 +08:00
Emily Astranova f989a1a982 Doc: fix typo in README (#1385) [ci skip]
Changed "deserved" to "derived"
2024-11-10 23:37:29 +08:00
李通洲 f9713d5ee2 OS (Android): display android icon 2024-11-10 13:57:57 +08:00
李通洲 4f9645e7ff Logo (Builtin): add Unifi 2024-11-10 13:35:22 +08:00
Carter Li 08a92a4324 CPU (OpenBSD): support CPU temp detection 2024-11-10 13:28:48 +08:00
李通洲 d10c14721a Disk: be able to print disk indices 2024-11-10 13:07:30 +08:00
李通洲 4534f18525 Battery: don't print index in multi-battery device 2024-11-10 13:07:12 +08:00
Carter Li f98e6c9d4e Sound (BSD): trim device names 2024-11-10 12:47:26 +08:00
Carter Li 59c666515a Version (MidnightBSD): support libc version detection 2024-11-10 12:47:26 +08:00
李通洲 7fab6f27ee Packages (BSD): support mport 2024-11-10 12:47:26 +08:00
李通洲 7d406bbae1 Logo (Builtin): add MidnightBSD 2024-11-10 12:47:26 +08:00
apocelipes 7b81ffc8e4 FFstrbuf: fix small FFstrbuf allocations in ffStrbufEnsureFree (#1383) 2024-11-10 08:27:57 +08:00
apocelipes 0284e4ccc4 IO: optimize createSubfolders (#1382) 2024-11-10 08:27:34 +08:00
Carter Li 837903e845 DisplayServer: fix deprecation warnings 2024-11-09 21:36:48 +08:00
xiaoran007 3fa0d1ab19 Host (macOS): add HwModel support for new Mac (2024) (#1381)
* host(macOS): add HwModel support for new Mac (iMac, Mac mini and Macbook Pro 2024)

* Update host_apple.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-11-09 20:32:35 +08:00
李通洲 07f2a71b3c Bluetooth (Windows): detect battery level 2024-11-09 20:23:25 +08:00
李通洲 acb38fa3ee Bluetooth (Windows): detect battery (WIP) 2024-11-06 08:25:54 +08:00
李通洲 7396208809 Logo (Builtin): fix Lilidog
Fix #1373
2024-11-06 08:25:48 +08:00
李通洲 2389d7b580 FFstrbuf: correct definition of StrStrIA 2024-11-06 08:25:06 +08:00
李通洲 8f750da559 Bluetooth (Windows): fix mac address detection 2024-11-06 08:25:06 +08:00
Lucas Holt f69a9dab33 CMake: Add initial support for MidnightBSD (#1377)
* Add initial support for MidnightBSD

* Cleanup some issues identified through code review.

Add libzfs check as MidnightBSD does have zfs.

* Add MidnightBSD check to the version.c detection

* Remove `OR MidnightBSD` tests

* Clean up

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-11-06 00:17:23 +08:00
李通洲 9a34cb98dc Bluetooth (macOS): normalize mac address strings 2024-11-05 16:39:04 +08:00
李通洲 ef974ef8c0 Bluetooth (macOS): support battery level detection 2024-11-05 11:06:54 +08:00
李通洲 40671c78f1 Monitor: don't display () if display name is not available 2024-11-05 10:01:43 +08:00
李通洲 211fd4b197 Display: add hdr-compatible
Fix #1376
2024-11-05 09:59:25 +08:00
Carter Li 722063401c Packaging: update debian stuff [ci skip] 2024-11-04 15:06:33 +08:00
218 changed files with 5829 additions and 3154 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
+123
View File
@@ -1,3 +1,126 @@
# 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:
* Percent: bar type must be enabled in `percent.type` before using percent bar in custom format
Features:
* Port to MidnightBSD; add mport package manager support
* Support bluetooth battery detection for macOS and Windows (Bluetooth, macOS / Windows)
* Support M4 model detection (Host, macOS)
* Support CPU temperature detection on OpenBSD (CPU, OpenBSD)
* Display Android icon in Android devices (OS, Android)
* Support qi package manager detection (Packages, Linux)
* Detect WM / DE by enumerating running processes (WM / DE, NetBSD)
* Generate manual pages from `help.json` (Doc)
* Detect marketing name of vivo smartphone (Host, Android)
* Add txDrops detection if supported (NetIO, *BSD)
* Support tilix version detection (Terminal, Linux)
* Support percent type config in module level. Example:
```json
{
"type": "memory",
"percent": {
"green": 20, // [0%, 20%) will be displayed in green
"yellow": 40, // [20, 40) will be displayed in yellow and [40, 100] will be displayed in red
"type": [ // Display percent value in monochrome bar, same as 10
"bar",
"bar-monochrome"
]
}
}
```
Bugfixes:
* Don't display `()` in key if display name is not available (Display)
* Fix & normalize bluetooth mac address detection (Bluetooth, macOS / Windows)
* Don't print index in multi-battery devices (Battery)
* Fix segfault in macOS (#1388, macOS)
* Fix `CFStringGetCString() failed` errors (#1394, Media, macOS)
* Fix CPU frequency detection on Apple M4 (#1394, CPU, macOS)
* Fix exe path detection on macOS (Shell / Terminal, macOS)
* Fix logo fails to load from symlinked files on macOS (#1395, Logo, macOS)
* Fix 32-bit truncation (NetIO, macOS)
Logos:
* Fix Lilidog
* Add MidnightBSD
* Add Unifi
* Add Cosmic DE
* Update openSUSE Tumbleweed
# 2.29.0
Changes:
+60 -23
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.29.0
VERSION 2.32.1
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -20,6 +20,9 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
set(FreeBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
set(OpenBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "MidnightBSD")
set(FreeBSD TRUE CACHE BOOL "..." FORCE)
set(MidnightBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "NetBSD")
set(NetBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")
@@ -54,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)
@@ -253,6 +254,7 @@ endfunction(fastfetch_load_text)
find_package(Python)
if(Python_FOUND)
message(STATUS "Minifying 'help.json'")
execute_process(COMMAND ${Python_EXECUTABLE} -c "import json,sys;json.dump(json.load(sys.stdin),sys.stdout,separators=(',',':'))"
INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/data/help.json"
OUTPUT_VARIABLE DATATEXT_JSON_HELP)
@@ -260,20 +262,39 @@ if(Python_FOUND)
message(ERROR "DATATEXT_JSON_HELP is empty, which should not happen!")
endif()
else()
message(STATUS "Python3 is not found, 'help.json' will not be minified")
message(WARNING "Python3 is not found, 'help.json' will not be minified")
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(STATUS "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated")
message(WARNING "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated")
set(ENABLE_EMBEDDED_PCIIDS OFF)
endif()
endif()
if(Python_FOUND)
message(STATUS "Generating 'fastfetch.1'")
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-man.py"
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)
configure_file(doc/fastfetch.1.in fastfetch.1 @ONLY)
endif()
fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER)
@@ -286,9 +307,6 @@ if(APPLE)
configure_file(src/util/apple/Info.plist.in Info.plist @ONLY)
endif()
string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y" UTC)
configure_file(doc/fastfetch.1.in fastfetch.1 @ONLY)
####################
# Ascii image data #
####################
@@ -484,6 +502,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
@@ -631,6 +650,7 @@ elseif(FreeBSD)
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_bsd.c
src/detection/host/host_mac.c
src/detection/lm/lm_linux.c
src/detection/icons/icons_linux.c
src/detection/initsystem/initsystem_linux.c
@@ -863,6 +883,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
@@ -875,7 +896,7 @@ elseif(APPLE)
src/detection/media/media_apple.m
src/detection/memory/memory_apple.c
src/detection/mouse/mouse_apple.c
src/detection/netio/netio_bsd.c
src/detection/netio/netio_apple.c
src/detection/opengl/opengl_apple.c
src/detection/os/os_apple.m
src/detection/packages/packages_apple.c
@@ -912,6 +933,7 @@ elseif(WIN32)
src/detection/battery/battery_windows.c
src/detection/bios/bios_windows.c
src/detection/bluetooth/bluetooth_windows.c
src/detection/bluetooth/bluetooth_windows.cpp
src/detection/bluetoothradio/bluetoothradio_windows.c
src/detection/board/board_windows.c
src/detection/bootmgr/bootmgr_windows.c
@@ -930,6 +952,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
@@ -1123,17 +1146,25 @@ if(APPLE AND EXISTS "/usr/bin/otool")
target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(FreeBSD AND EXISTS "/usr/local/bin/objdump")
if(MidnightBSD AND EXISTS "/usr/bin/objdump")
execute_process(COMMAND /bin/sh -c "/usr/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1"
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
message(STATUS "Found FBSD ${CMAKE_MATCH_1}")
target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
endif()
elseif(FreeBSD AND EXISTS "/usr/local/bin/objdump")
execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1"
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
message(STATUS "Found FBSD ${CMAKE_MATCH_1}")
target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(DragonFly AND EXISTS "/usr/local/bin/objdump")
elseif(DragonFly AND EXISTS "/usr/local/bin/objdump")
execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'DF[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1"
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
if("${OBJDUMP_T_RESULT}" MATCHES "DF([0-9]+\\.[0-9]+)")
message(STATUS "Found DF ${CMAKE_MATCH_1}")
target_compile_definitions(libfastfetch PUBLIC FF_DF_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
@@ -1143,7 +1174,7 @@ if(LINUX)
elseif(ANDROID)
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _FILE_OFFSET_BITS=64 "$<$<CONFIG:DEBUG>:__BIONIC_FORTIFY>" "$<$<CONFIG:DEBUG>:__BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED>")
elseif(WIN32)
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00 NOMINMAX) # "$<$<CONFIG:Release>:_FORTIFY_SOURCE=3>"
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0A00 NOMINMAX UNICODE) # "$<$<CONFIG:Release>:_FORTIFY_SOURCE=3>"
elseif(APPLE)
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE)
elseif(OpenBSD)
@@ -1159,6 +1190,16 @@ elseif(NetBSD)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/usr/X11R7/lib -Wl,-rpath,/usr/pkg/lib") # ditto
endif()
if(FreeBSD OR OpenBSD OR NetBSD)
include(CheckStructHasMember)
set(CMAKE_REQUIRED_DEFINITIONS "-D_IFI_OQDROPS=1")
CHECK_STRUCT_HAS_MEMBER("struct if_data" ifi_oqdrops net/if.h HAVE_IFI_OQDROPS LANGUAGE C)
if(HAVE_IFI_OQDROPS)
target_compile_definitions(libfastfetch PUBLIC _IFI_OQDROPS FF_HAVE_IFI_OQDROPS)
endif()
unset(CMAKE_REQUIRED_DEFINITIONS)
endif()
if(HAVE_STATX)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_STATX)
endif()
@@ -1183,6 +1224,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)
@@ -1238,18 +1282,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"
@@ -1425,6 +1461,7 @@ elseif(WIN32)
PRIVATE "imagehlp"
PRIVATE "cfgmgr32"
PRIVATE "winbrand"
PRIVATE "propsys"
)
elseif(FreeBSD)
target_link_libraries(libfastfetch
+1 -2
View File
@@ -40,7 +40,6 @@ Some distros package an outdated fastfetch version. Older versions receive no su
* openSUSE: `zypper install fastfetch`
* ALT Linux: `apt-get install fastfetch`
* Exherbo: `cave resolve --execute app-misc/fastfetch`
* GNU Guix: `guix install fastfetch`
* Solus: `eopkg install fastfetch`
* Slackware: `sbopkg -i fastfetch`
* Void Linux: `xbps-install fastfetch`
@@ -194,7 +193,7 @@ See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096).
Neofetch incorrectly counts `rc` packages ( the package has been removed, but that the configuration files remain ). Bug https://github.com/dylanaraps/neofetch/issues/2278
### Q: I use Debian / Ubuntu / Debian deserved distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug?
### Q: I use Debian / Ubuntu / Debian derived distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug?
Try upgrading `pci.ids`: Download <https://pci-ids.ucw.cz/v2.2/pci.ids> and overwrite file `/usr/share/hwdata/pci.ids`. For AMD GPUs, you should also upgrade `amdgpu.ids`: Download <https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids> and overwrite file `/usr/share/libdrm/amdgpu.ids`
+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)
+30
View File
@@ -1,3 +1,33 @@
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
-- Carter Li <zhangsongcui@live.cn> Mon, 04 Nov 2024 15:05:02 +0800
fastfetch (2.28.0) jammy; urgency=medium
* Update to 2.28.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.28.0_source.buildinfo universe/utils optional
fastfetch_2.32.0_source.buildinfo universe/utils optional
+1443 -248
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",
+258
View File
@@ -0,0 +1,258 @@
#!/usr/bin/env python3
"""
Python script to generate a man page for the command `fastfetch`.
The man content will be printed to stdout so you will need to
pipe it to a file if you want to save it.
The command options will be generated using a JSON file.
For the format of the JSON file, see https://github.com/fastfetch-cli/fastfetch/blob/dev/src/data/help.json
"""
from json import load
from datetime import datetime, timezone
from time import time
from re import search
from os import environ, path
###### Text Decorations Tags ######
startUnderline = r"\fI" # start underline text tag
endUnderline = r"\fR" # end underline text tag
startBold = r"\fB" # start bold text tag
endBold = r"\fR" # end bold text tag
###### Parameters ######
# path to the current directory
pathToCurrentDir = path.dirname(__file__)
# path to the JSON option file
pathToHelpFile = path.join(pathToCurrentDir, "../src/data/help.json")
# man page section
manSection = 1
# title (center header)
titlePage = "Fastfetch man page"
# date (center footer)
# format : "Month (abbreviation) Day Year"
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")
###### Sections Text ######
# text displayed in the "NAME" section
nameSection = r"fastfetch \- A maintained, feature\-rich and performance oriented, neofetch like system information tool"
# text displayed at the beginning of the "OPTIONS" section
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 brackets, it is optional.
An optional boolean value defaults to true if not specified.
More detailed help messages for each options can be printed
with \fB-h <option_without_dash_prefix>\fR.
All options can be made permanent with command
\fBfastfetch <options> --gen-config\fR.
"""
# text displayed in the "CONFIGURATION"
configurationSection = f"""
.SS Fetch Structure
The structure of a fetch describes the modules that should
be included in the output. It consists of a string of modules,
separated by a colon (:). To list all available modules,
use --list-modules.
.SS Config Files
Fastfetch uses JSONC based format for configuration.
Fastfetch doesn't generate config file automatically;
it should be generated manually by {startBold}--gen-config{endBold}.
The config file will be saved in
{startBold}~/.config/fastfetch/config.jsonc{endBold} by default.
A JSONC config file is a JSON file that also supports comments
with (// and /* */). Those files must have the extension '.jsonc'.
The specified configuration/preset files are searched in the following order:
{startBold}1.{endBold} relative to the current working directory
{startBold}2.{endBold} relative to ~/.local/share/fastfetch/presets/
{startBold}3.{endBold} relative to /usr/share/fastfetch/presets/
Fastfetch provides some default presets. List them with --list-presets.
"""
# text displayed in the "EXAMPLE" section
exampleSection = """
.SS Config files:
.nf
// ~/.config/fastfetch/config.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"modules": [
"title",
"separator",
"module1",
{
"type": "module2",
"module2-option": "value"
}
]
}
.fi
"""
# text displayed in the "BUGS" section
bugSection = "Please report bugs to : \
https://github.com/fastfetch-cli/fastfetch/issues"
# text displayed in the "WIKI" section
wikiSection = "Fastfetch github wiki : https://github.com/fastfetch-cli/fastfetch/wiki/Configuration"
###### Argument decoration ######
### optional arguments tags ###
# if an optional argument is displayed as [?optArg] (with "optArg" underlined)
# this value should be f"[?{startUnderline}"
startOptionalArgument = f"[{startUnderline}?"
# if an optional argument is displayed as [?optArg] (with "optArg underlined")
# this value should be f"{endUnderline}]"
endOptionalArgument = f"{endUnderline}]"
### mandatory arguments tags ###
startMandatoryArgument = f"{startUnderline}"
endMandatoryArgument = f"{endUnderline}"
def main():
# importing the JSON file
with open(pathToHelpFile, 'r') as jsonFile:
helpFileData = load(jsonFile) # json.load
######## Start printing the generated .1 file ########
###### header, footer & config #####
print(f".TH FASTFETCH {manSection} ", end=" ")
print(f"\"{todayDate}\"", end=" ")
# version number
with open(pathToVersionFile, 'r') as versionFile:
# research version number in file with regex
for line in versionFile:
researchVersion = search(r"^\s*VERSION (\d+\.\d+\.\d+)$", line)
if (researchVersion):
print(f"\"{researchVersion.group(1)}\"", end=" ")
break
print(f"\"{titlePage}\"")
###### Name ######
print(".SH NAME")
print(nameSection)
##### Synopsis ######
print(".SH SYNOPSIS")
print(".B fastfetch")
print(f"[{startUnderline}OPTIONS{endUnderline}]")\
###### Wiki ######
print(".SH WIKI")
print(wikiSection)
###### Configuration ######
print(".SH CONFIGURATION")
print(configurationSection)
###### Options ######
print(".SH OPTIONS")
print(optionSection)
print()
# loop through every options sections
for key, value in helpFileData.items():
# print new subsection
print(f".SS {key}:")
# loop through every option in a section
for option in value:
# list of existing keys for this option
keyList = option.keys()
# start a new "option" entry
print(".TP")
print(startBold, end="")
# short option (-opt)
if "short" in keyList:
print(fr"\-{ option['short'] }", end="")
# if also have a long option, print a comma
if "long" in keyList:
print(", ", end="")
# long option (--option)
if "long" in keyList:
print(fr"\-\-{ option['long'] }", end="")
print(endBold, end=" ")
# arguments
if "arg" in keyList:
# if argument is optional, print "[arg]"
if "optional" in option["arg"].keys() and option["arg"]["optional"]:
print(startOptionalArgument + option['arg']['type'] + endOptionalArgument, end="")
# if argument is mandatory, print "arg"
else:
print(startMandatoryArgument + option['arg']['type'] + endMandatoryArgument, end="")
# description
print(f"\n {option['desc']} \n")
###### Examples ######
print(".SH EXAMPLES")
print(exampleSection)
###### Bugs ######
print(".SH BUGS")
print(bugSection)
if __name__ == "__main__":
main()
Regular → Executable
+2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env python3
from requests import get as http_get
class PciDeviceModel:
+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
+3 -5
View File
@@ -2,7 +2,7 @@
#include "util/FFstrbuf.h"
typedef enum FFformatArgType
typedef enum __attribute__((__packed__)) FFformatArgType
{
FF_FORMAT_ARG_TYPE_NULL = 0,
FF_FORMAT_ARG_TYPE_UINT,
@@ -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
+16 -1
View File
@@ -87,11 +87,12 @@ static inline bool ffReadFileBufferRelative(FFNativeFD dfd, const char* fileName
}
//Bit flags, combine with |
typedef enum FFPathType
typedef enum __attribute__((__packed__)) FFPathType
{
FF_PATHTYPE_FILE = 1 << 0,
FF_PATHTYPE_DIRECTORY = 1 << 1,
FF_PATHTYPE_ANY = FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY,
FF_PATHTYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFPathType;
static inline bool ffPathExists(const char* path, FFPathType pathType)
@@ -118,6 +119,19 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
}
else
{
#if __APPLE__ // #1395
struct stat fileStat;
if(stat(path, &fileStat) != 0)
return false;
unsigned int mode = fileStat.st_mode & S_IFMT;
if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR)
return true;
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
return true;
#else
size_t len = strlen(path);
assert(len < PATH_MAX);
if (len == 0) return false;
@@ -134,6 +148,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
else
ret = access(path, F_OK);
return pathType == FF_PATHTYPE_DIRECTORY ? ret == 0 : ret == -1 && errno == ENOTDIR;
#endif
}
#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);
+17 -24
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,38 +33,17 @@ 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 FFModuleKeyType
typedef enum __attribute__((__packed__)) FFModuleKeyType
{
FF_MODULE_KEY_TYPE_NONE = 0,
FF_MODULE_KEY_TYPE_STRING = 1 << 0,
FF_MODULE_KEY_TYPE_ICON = 1 << 1,
FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON,
FF_MODULE_KEY_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFModuleKeyType;
typedef struct FFModuleArgs
+72 -10
View File
@@ -14,7 +14,46 @@ static void appendOutputColor(FFstrbuf* buffer, const FFModuleArgs* module)
ffStrbufAppendF(buffer, "\e[%sm", instance.config.display.colorOutput.chars);
}
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config, const FFModuleArgs* module)
const char* ffPercentParseTypeJsonConfig(yyjson_val* jsonVal, FFPercentageTypeFlags* result)
{
if (yyjson_is_uint(jsonVal))
{
*result = (FFPercentageTypeFlags) yyjson_get_uint(jsonVal);
return NULL;
}
if (yyjson_is_arr(jsonVal))
{
FFPercentageTypeFlags flags = 0;
yyjson_val* item;
size_t idx, max;
yyjson_arr_foreach(jsonVal, idx, max, item)
{
const char* flag = yyjson_get_str(item);
if (!flag)
return "Error: percent.type: invalid flag string";
if (ffStrEqualsIgnCase(flag, "num"))
flags |= FF_PERCENTAGE_TYPE_NUM_BIT;
else if (ffStrEqualsIgnCase(flag, "bar"))
flags |= FF_PERCENTAGE_TYPE_BAR_BIT;
else if (ffStrEqualsIgnCase(flag, "hide-others"))
flags |= FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT;
else if (ffStrEqualsIgnCase(flag, "num-color"))
flags |= FF_PERCENTAGE_TYPE_NUM_COLOR_BIT;
else if (ffStrEqualsIgnCase(flag, "bar-monochrome"))
flags |= FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT;
else
return "Error: percent.type: unknown flag string";
}
*result = flags;
return NULL;
}
return "Error: usage: percent.type must be a number or an array of strings";
}
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, const FFModuleArgs* module)
{
uint8_t green = config.green, yellow = config.yellow;
assert(green <= 100 && yellow <= 100);
@@ -41,15 +80,18 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig con
}
else
{
const char* colorGreen = instance.config.display.percentColorGreen.chars;
const char* colorYellow = instance.config.display.percentColorYellow.chars;
const char* colorRed = instance.config.display.percentColorRed.chars;
const char* colorGreen = options->percentColorGreen.chars;
const char* colorYellow = options->percentColorYellow.chars;
const char* colorRed = options->percentColorRed.chars;
FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type;
bool monochrome = !!(percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT);
for (uint32_t i = 0; i < blocksPercent; ++i)
{
if(!options->pipe)
{
if (options->percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT)
if (monochrome)
{
const char* color = NULL;
if (green <= yellow)
@@ -104,14 +146,15 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig con
}
}
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses, const FFModuleArgs* module)
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, bool parentheses, const FFModuleArgs* module)
{
uint8_t green = config.green, yellow = config.yellow;
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type;
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
bool colored = !!(percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
@@ -156,7 +199,7 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig con
ffStrbufAppendC(buffer, ')');
}
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config)
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config)
{
if (!ffStrStartsWithIgnCase(subkey, "percent-"))
return false;
@@ -187,10 +230,16 @@ bool ffPercentParseCommandOptions(const char* key, const char* subkey, const cha
return true;
}
if (ffStrEqualsIgnCase(subkey, "type"))
{
config->type = (FFPercentageTypeFlags) ffOptionParseUInt32(key, value);
return true;
}
return false;
}
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config)
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config)
{
if (!ffStrEqualsIgnCase(key, "percent"))
return false;
@@ -225,10 +274,21 @@ bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeCo
config->yellow = (uint8_t) num;
}
yyjson_val* typeVal = yyjson_obj_get(value, "type");
if (typeVal)
{
const char* error = ffPercentParseTypeJsonConfig(typeVal, &config->type);
if (error)
{
fputs(error, stderr);
exit(480);
}
}
return true;
}
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config)
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config)
{
if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow)
return;
@@ -238,4 +298,6 @@ void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF
yyjson_mut_obj_add_uint(doc, percent, "green", config.green);
if (config.yellow != defaultConfig.yellow)
yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow);
if (config.type != defaultConfig.type)
yyjson_mut_obj_add_uint(doc, percent, "type", config.type);
}
+18 -7
View File
@@ -4,14 +4,24 @@
#include "common/parsing.h"
#include "common/option.h"
enum FFPercentageTypeFlags
typedef enum __attribute__((__packed__)) FFPercentageTypeFlags
{
FF_PERCENTAGE_TYPE_NONE = 0,
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT = FF_PERCENTAGE_TYPE_NUM_COLOR_BIT,
};
FF_PERCENTAGE_TYPE_FORCE_UNSIGNED_ = UINT8_MAX,
} FFPercentageTypeFlags;
static_assert(sizeof(FFPercentageTypeFlags) == 1, "");
typedef struct FFPercentageModuleConfig
{
uint8_t green;
uint8_t yellow;
FFPercentageTypeFlags type;
} FFPercentageModuleConfig;
// if (green <= yellow)
// [0, green]: print green
@@ -23,12 +33,13 @@ enum FFPercentageTypeFlags
// [yellow, green): print yellow
// [0, yellow): print red
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config, const FFModuleArgs* module);
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses, const FFModuleArgs* module);
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, const FFModuleArgs* module);
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, bool parentheses, const FFModuleArgs* module);
typedef struct yyjson_val yyjson_val;
typedef struct yyjson_mut_doc yyjson_mut_doc;
typedef struct yyjson_mut_val yyjson_mut_val;
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config);
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config);
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config);
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config);
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config);
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config);
const char* ffPercentParseTypeJsonConfig(yyjson_val* value, FFPercentageTypeFlags* result);
+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);
}
+4 -11
View File
@@ -3,26 +3,19 @@
#include "fastfetch.h"
#include "common/format.h"
typedef enum FFPrintType {
typedef enum __attribute__((__packed__)) FFPrintType {
FF_PRINT_TYPE_DEFAULT = 0,
FF_PRINT_TYPE_NO_CUSTOM_KEY = 1 << 0, // key has been formatted outside
FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR = 1 << 1,
FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH = 1 << 2,
FF_PRINT_TYPE_NO_CUSTOM_OUTPUT_FORMAT = 1 << 3, // reserved
FF_PRINT_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} 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)
+24 -11
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";
@@ -147,7 +161,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
if (length > 0) // doesn't contain trailing NUL
{
buf[length] = '\0';
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length + 1); // +1 for the NUL
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
}
}
@@ -158,10 +172,8 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid };
if (sysctl(mibs, ARRAY_SIZE(mibs), NULL, &len, NULL, 0) == 0)
{// try get arg0
#ifndef MAC_OS_X_VERSION_10_15
//don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version.
len++;
#endif
FF_AUTO_FREE char* const procArgs2 = malloc(len);
if (sysctl(mibs, ARRAY_SIZE(mibs), procArgs2, &len, NULL, 0) == 0)
{
@@ -195,11 +207,12 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
}
else
{
ffStrbufEnsureFixedLengthFree(exe, PATH_MAX);
int length = proc_pidpath(pid, exe->chars, exe->allocated);
char buf[PROC_PIDPATHINFO_MAXSIZE];
int length = proc_pidpath(pid, buf, ARRAY_SIZE(buf));
if (length > 0)
{
exe->length = (uint32_t) length;
ffStrbufEnsureFixedLengthFree(exe, (uint32_t) length);
ffStrbufAppendNS(exe, (uint32_t) length, buf);
if (exePath)
ffStrbufSet(exePath, exe);
}
@@ -275,7 +288,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
if (length > 0) // doesn't contain trailing NUL
{
buf[length] = '\0';
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length + 1); // +1 for the NUL
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
#include "fastfetch.h"
typedef enum FFvarianttype
typedef enum __attribute__((__packed__)) FFvarianttype
{
FF_VARIANT_TYPE_STRING,
FF_VARIANT_TYPE_BOOL,
+18
View File
@@ -1602,6 +1602,24 @@
},
"pseudo": true
},
{
"long": "<module>-percent-type",
"desc": "Set the percentage output type",
"remark": [
"0 for use global `--percent-type` value",
"1 for percentage number",
"2 for multi-color bar",
"3 for both",
"6 for bar only",
"9 for colored number",
"10 for monochrome bar"
],
"arg": {
"type": "num",
"default": 0
},
"pseudo": true
},
{
"long": "<module>-temp-green",
"desc": [
+18 -1
View File
@@ -2,6 +2,14 @@
#import <IOBluetooth/IOBluetooth.h>
@interface IOBluetoothDevice()
@property (nonatomic) uint8_t batteryPercentCase;
@property (nonatomic) uint8_t batteryPercentCombined;
@property (nonatomic) uint8_t batteryPercentLeft;
@property (nonatomic) uint8_t batteryPercentRight;
@property (nonatomic) uint8_t batteryPercentSingle;
@end
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
{
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
@@ -13,8 +21,17 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
ffStrbufReplaceAllC(&device->address, '-', ':');
ffStrbufUpperCase(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
if (ioDevice.batteryPercentSingle)
device->battery = ioDevice.batteryPercentSingle;
else if (ioDevice.batteryPercentCombined)
device->battery = ioDevice.batteryPercentCombined;
else if (ioDevice.batteryPercentCase)
device->battery = ioDevice.batteryPercentCase;
device->connected = !!ioDevice.isConnected;
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode)
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
+9 -6
View File
@@ -33,13 +33,13 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
do {
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitWS(&device->name, btdi.szName);
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
btdi.Address.rgBytes[0],
btdi.Address.rgBytes[1],
btdi.Address.rgBytes[2],
btdi.Address.rgBytes[3],
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X",
btdi.Address.rgBytes[5],
btdi.Address.rgBytes[4],
btdi.Address.rgBytes[5]);
btdi.Address.rgBytes[3],
btdi.Address.rgBytes[2],
btdi.Address.rgBytes[1],
btdi.Address.rgBytes[0]);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
@@ -121,5 +121,8 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
ffBluetoothFindDeviceClose(hFind);
const char* ffBluetoothDetectBattery(FFlist* result);
ffBluetoothDetectBattery(devices);
return NULL;
}
@@ -0,0 +1,122 @@
extern "C"
{
#include "bluetooth.h"
}
#include "util/windows/wmi.hpp"
#include "util/windows/unicode.hpp"
STDAPI InitVariantFromStringArray(_In_reads_(cElems) PCWSTR *prgsz, _In_ ULONG cElems, _Out_ VARIANT *pvar);
template <typename Fn>
struct on_scope_exit {
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
~on_scope_exit() { this->_fn(); }
private:
Fn _fn;
};
extern "C"
const char* ffBluetoothDetectBattery(FFlist* devices)
{
FFWmiQuery query(L"SELECT __PATH FROM Win32_PnPEntity WHERE Service = 'BthHFEnum'", nullptr, FFWmiNamespace::CIMV2);
if(!query)
return "Query WMI service failed";
IWbemClassObject* pInParams = nullptr;
on_scope_exit releaseInParams([&] { pInParams && pInParams->Release(); });
{
IWbemClassObject* pnpEntityClass = nullptr;
if (FAILED(query.pService->GetObjectW(bstr_t(L"Win32_PnPEntity"), 0, nullptr, &pnpEntityClass, nullptr)))
return "Failed to get PnP entity class";
on_scope_exit releasePnpEntityClass([&] { pnpEntityClass && pnpEntityClass->Release(); });
if (FAILED(pnpEntityClass->GetMethod(bstr_t(L"GetDeviceProperties"), 0, &pInParams, NULL)))
return "Failed to get GetDeviceProperties method";
VARIANT devicePropertyKeys;
PCWSTR props[] = { L"{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2", L"DEVPKEY_Bluetooth_DeviceAddress" };
if (FAILED(InitVariantFromStringArray(props, ARRAY_SIZE(props), &devicePropertyKeys)))
return "Failed to init variant from string array";
on_scope_exit releaseDevicePropertyKeys([&] { VariantClear(&devicePropertyKeys); });
if (FAILED(pInParams->Put(L"devicePropertyKeys", 0, &devicePropertyKeys, CIM_FLAG_ARRAY | CIM_STRING)))
return "Failed to put devicePropertyKeys";
}
while (FFWmiRecord record = query.next())
{
IWbemCallResult* pCallResult = nullptr;
if (FAILED(query.pService->ExecMethod(record.get(L"__PATH").bstrVal, bstr_t(L"GetDeviceProperties"), 0, nullptr, pInParams, nullptr, &pCallResult)))
continue;
on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); });
IWbemClassObject* pResultObject = nullptr;
if (FAILED(pCallResult->GetResultObject(WBEM_INFINITE, &pResultObject)))
continue;
on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); });
VARIANT propArray;
if (FAILED(pResultObject->Get(L"deviceProperties", 0, &propArray, nullptr, nullptr)))
continue;
on_scope_exit releasePropArray([&] { VariantClear(&propArray); });
if (propArray.vt != (VT_ARRAY | VT_UNKNOWN) ||
(propArray.parray->fFeatures & FADF_UNKNOWN) == 0 ||
propArray.parray->cDims != 1 ||
propArray.parray->rgsabound[0].cElements != 2
)
continue;
uint8_t batt = 0;
for (LONG i = 0; i < 2; i++)
{
IWbemClassObject* object = nullptr;
if (FAILED(SafeArrayGetElement(propArray.parray, &i, &object)))
continue;
FFWmiRecord rec(object);
auto data = rec.get(L"Data");
if (data.vt == VT_EMPTY)
break;
if (i == 0)
batt = data.get<uint8_t>();
else
{
FF_STRBUF_AUTO_DESTROY addr; // MAC address without colon
ffStrbufInitWSV(&addr, data.get<std::wstring_view>());
if (__builtin_expect(addr.length != 12, 0))
continue;
FF_LIST_FOR_EACH(FFBluetoothResult, bt, *devices)
{
if (bt->address.length != 12 + 5)
continue;
if (addr.chars[0] == bt->address.chars[0] &&
addr.chars[1] == bt->address.chars[1] &&
addr.chars[2] == bt->address.chars[3] &&
addr.chars[3] == bt->address.chars[4] &&
addr.chars[4] == bt->address.chars[6] &&
addr.chars[5] == bt->address.chars[7] &&
addr.chars[6] == bt->address.chars[9] &&
addr.chars[7] == bt->address.chars[10] &&
addr.chars[8] == bt->address.chars[12] &&
addr.chars[9] == bt->address.chars[13] &&
addr.chars[10] == bt->address.chars[15] &&
addr.chars[11] == bt->address.chars[16])
{
bt->battery = batt;
break;
}
}
}
}
}
return NULL;
}
@@ -84,12 +84,12 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
addr.rgBytes[0],
addr.rgBytes[1],
addr.rgBytes[2],
addr.rgBytes[3],
addr.rgBytes[5],
addr.rgBytes[4],
addr.rgBytes[5]);
addr.rgBytes[3],
addr.rgBytes[2],
addr.rgBytes[1],
addr.rgBytes[0]);
device->lmpVersion = blri.radioInfo.lmpVersion;
device->lmpSubversion = blri.radioInfo.lmpSubversion;
+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)
+3
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;
}
@@ -37,6 +38,8 @@ const char* ffCPUAppleCodeToName(uint32_t code)
case 6031:
case 6034: return "Apple M3 Max";
case 8132: return "Apple M4";
case 6040: return "Apple M4 Pro";
case 6041: return "Apple M4 Max";
default: 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;
+7 -1
View File
@@ -59,7 +59,12 @@ static const char* detectFrequency(FFCPUResult* cpu)
pMax = pMax > pStart[i] ? pMax : pStart[i];
if (pMax > 0)
cpu->frequencyMax = pMax / 1000 / 1000;
{
if (pMax > 100000000) // Assume that pMax is in Hz, M1~M3
cpu->frequencyMax = pMax / 1000 / 1000;
else // Assume that pMax is in kHz, M4 and later (#1394)
cpu->frequencyMax = pMax / 1000;
}
return NULL;
}
@@ -104,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;
+11 -1
View File
@@ -1,6 +1,9 @@
#include "cpu.h"
#include "common/sysctl.h"
#include <sys/time.h>
#include <sys/sensors.h>
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name))
@@ -13,7 +16,14 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffCPUDetectSpeedByCpuid(cpu);
cpu->frequencyBase = (uint32_t) ffSysctlGetInt(CTL_HW, HW_CPUSPEED, 0);
cpu->temperature = FF_CPU_TEMP_UNSET; // HW_SENSORS?
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
{
struct sensor sensors;
size_t size = sizeof(sensors);
if (sysctl((int[]) {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0}, 5, &sensors, &size, NULL, 0) == 0)
cpu->temperature = (double) (sensors.value - 273150000) / 1E6;
}
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;
+1 -1
View File
@@ -2,7 +2,7 @@
#include "fastfetch.h"
typedef enum FFCPUCacheType
typedef enum __attribute__((__packed__)) FFCPUCacheType
{
FF_CPU_CACHE_TYPE_UNIFIED = 0,
FF_CPU_CACHE_TYPE_INSTRUCTION = 1,
+7 -7
View File
@@ -20,35 +20,35 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
{
*pNum = (char) ('0' + i);
ffStrCopyN(pSubkey, "physicalcpu", lenLeft);
ffStrCopy(pSubkey, "physicalcpu", lenLeft);
uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (ncpu <= 0) continue;
ffStrCopyN(pSubkey, "l1icachesize", lenLeft);
ffStrCopy(pSubkey, "l1icachesize", lenLeft);
uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu;
ffStrCopyN(pSubkey, "l1dcachesize", lenLeft);
ffStrCopy(pSubkey, "l1dcachesize", lenLeft);
size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_DATA)->num = ncpu;
ffStrCopyN(pSubkey, "l2cachesize", lenLeft);
ffStrCopy(pSubkey, "l2cachesize", lenLeft);
size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
{
ffStrCopyN(pSubkey, "cpusperl2", lenLeft);
ffStrCopy(pSubkey, "cpusperl2", lenLeft);
uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (cpuSper)
ffCPUCacheAddItem(result, 2, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
}
ffStrCopyN(pSubkey, "l3cachesize", lenLeft);
ffStrCopy(pSubkey, "l3cachesize", lenLeft);
size = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (size)
{
ffStrCopyN(pSubkey, "cpusperl3", lenLeft);
ffStrCopy(pSubkey, "cpusperl3", lenLeft);
uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0);
if (cpuSper)
ffCPUCacheAddItem(result, 3, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper;
@@ -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;
+18 -10
View File
@@ -36,19 +36,21 @@
#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"
#define FF_WM_PROTOCOL_WAYLAND "Wayland"
typedef enum FFDisplayType {
typedef enum __attribute__((__packed__)) FFDisplayType {
FF_DISPLAY_TYPE_UNKNOWN,
FF_DISPLAY_TYPE_BUILTIN,
FF_DISPLAY_TYPE_EXTERNAL,
} FFDisplayType;
typedef enum FFDisplayHdrStatus
typedef enum __attribute__((__packed__)) FFDisplayHdrStatus
{
FF_DISPLAY_HDR_STATUS_UNKNOWN,
FF_DISPLAY_HDR_STATUS_UNSUPPORTED,
@@ -58,17 +60,20 @@ typedef enum 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,
@@ -36,6 +36,8 @@ static void detectDisplays(FFDisplayServerResult* ds)
if (refreshRate == 0)
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
CVDisplayLinkRef link;
if(CVDisplayLinkCreateWithCGDisplay(screen, &link) == kCVReturnSuccess)
{
@@ -44,6 +46,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
refreshRate = time.timeScale / (double) time.timeValue; //59.97...
CVDisplayLinkRelease(link);
}
#pragma clang diagnostic pop
}
ffStrbufClear(&buffer);
@@ -57,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;
@@ -73,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);
@@ -88,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,
@@ -99,6 +135,10 @@ static void detectDisplays(FFDisplayServerResult* ds)
);
if (display)
{
#ifndef MAC_OS_X_VERSION_10_11
FF_CFTYPE_AUTO_RELEASE CFStringRef pe = CGDisplayModeCopyPixelEncoding(mode);
if (pe) display->bitDepth = (uint8_t) (CFStringGetLength(pe) - CFStringFind(pe, CFSTR("B"), 0).location);
#else
// https://stackoverflow.com/a/33519316/9976392
// Also shitty, but better than parsing `CFCopyDescription(mode)`
CFDictionaryRef dict = (CFDictionaryRef) *((int64_t *)mode + 2);
@@ -108,8 +148,9 @@ static void detectDisplays(FFDisplayServerResult* ds)
ffCfDictGetInt(dict, kCGDisplayBitsPerSample, &bitDepth);
display->bitDepth = (uint8_t) bitDepth;
}
#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
@@ -127,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);
}
@@ -9,7 +9,7 @@
#include "../displayserver_linux.h"
typedef enum WaylandProtocolType
typedef enum __attribute__((__packed__)) WaylandProtocolType
{
FF_WAYLAND_PROTOCOL_TYPE_NONE,
FF_WAYLAND_PROTOCOL_TYPE_GLOBAL,
@@ -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
+37 -5
View File
@@ -8,16 +8,19 @@
#include <string.h>
#include <unistd.h>
#ifdef __FreeBSD__
#if __FreeBSD__
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/user.h>
#elif defined(__OpenBSD__)
#elif __OpenBSD__
#include <sys/param.h>
#include <sys/sysctl.h>
#include <kvm.h>
#elif defined(__sun)
#elif __sun
#include <procfs.h>
#elif __NetBSD__
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
static const char* parseEnv(void)
@@ -123,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)
@@ -293,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;
@@ -388,6 +397,29 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
if(result->wmPrettyName.length == 0)
applyNameIfWM(result, processName.chars);
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
break;
}
#elif __NetBSD__
int request[] = {CTL_KERN, KERN_PROC2, KERN_PROC_UID, (int) userId, sizeof(struct kinfo_proc2), INT_MAX};
size_t size = 0;
if(sysctl(request, ARRAY_SIZE(request), NULL, &size, NULL, 0) != 0)
return "sysctl(KERN_PROC_UID, NULL) failed";
FF_AUTO_FREE struct kinfo_proc2* procs = malloc(size);
if(sysctl(request, ARRAY_SIZE(request), procs, &size, NULL, 0) != 0)
return "sysctl(KERN_PROC_UID, procs) failed";
for(struct kinfo_proc2* proc = procs; proc < procs + (size / sizeof(struct kinfo_proc2)); proc++)
{
if(result->dePrettyName.length == 0)
applyPrettyNameIfDE(result, proc->p_comm);
if(result->wmPrettyName.length == 0)
applyNameIfWM(result, proc->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,
+1 -1
View File
@@ -66,7 +66,7 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
*result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
if (result.index)
*result.type = (uint32_t) device->adlAdapterIndex;
*result.index = (uint32_t) device->adlAdapterIndex;
if (result.name)
ffStrbufSetS(result.name, device->adapterString);
+7 -1
View File
@@ -68,7 +68,13 @@ static const char* detectFrequency(FFGPUResult* gpu)
pMax = pMax > pStart[i] ? pMax : pStart[i];
if (pMax > 0)
gpu->frequency = pMax / 1000 / 1000;
{
// While this is not necessary for now (seems), we add this logic just in case. See cpu_apple.c
if (pMax > 100000000) // Assume that pMax is in Hz
gpu->frequency = pMax / 1000 / 1000;
else // Assume that pMax is in kHz
gpu->frequency = pMax / 1000;
}
return NULL;
}
+2 -1
View File
@@ -2,11 +2,12 @@
#include "gpu.h"
typedef enum FFGpuDriverConditionType
typedef enum __attribute__((__packed__)) FFGpuDriverConditionType
{
FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID = 1 << 0,
FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID = 1 << 1,
FF_GPU_DRIVER_CONDITION_TYPE_LUID = 1 << 2,
FF_GPU_DRIVER_CONDITION_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFGpuDriverConditionType;
typedef struct FFGpuDriverPciBusId
+17 -17
View File
@@ -460,7 +460,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
{
if (ffStrStartsWith(entry->d_name, "card"))
{
ffStrCopyN(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer));
ffStrCopy(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer));
drmKey = drmKeyBuffer;
break;
}
@@ -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);
+1 -1
View File
@@ -18,7 +18,7 @@ static inline bool allValuesSet(const FFQtResult* result)
result->wallpaper.length > 0;
}
typedef enum PlasmaCategory
typedef enum __attribute__((__packed__)) PlasmaCategory
{
PLASMA_CATEGORY_GENERAL,
PLASMA_CATEGORY_KDE,
+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);
+3 -2
View File
@@ -9,11 +9,12 @@ const char* ffDetectHost(FFHostResult* host)
ffSettingsGetAndroidProperty("ro.product.marketname", &host->name)
|| ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->name)
|| ffSettingsGetAndroidProperty("ro.vivo.market.name", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name)
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name)
|| ffSettingsGetAndroidProperty("ro.config.devicename", &host->name)
|| ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name)
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.brand", &host->name);
if (ffSettingsGetAndroidProperty("ro.product.model", &host->version))
+1 -165
View File
@@ -5,170 +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, "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"));
@@ -208,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
@@ -72,5 +72,9 @@ const char* ffDetectHost(FFHostResult* host)
ffCleanUpSmbiosValue(&host->family);
}
#if _WIN32 && __x86_64__
ffHostDetectMac(host);
#endif
return NULL;
}
+2 -2
View File
@@ -231,7 +231,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
FF_LIST_FOR_EACH(FFLocalIpResult, iface, *results)
{
struct ifreq ifr;
ffStrCopyN(ifr.ifr_name, iface->name.chars, IFNAMSIZ);
ffStrCopy(ifr.ifr_name, iface->name.chars, IFNAMSIZ);
if (options->showType & FF_LOCALIP_TYPE_MTU_BIT)
{
@@ -248,7 +248,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android
#elif __FreeBSD__ || __APPLE__ || __OpenBSD__ || __NetBSD__
struct ifmediareq ifmr = {};
ffStrCopyN(ifmr.ifm_name, iface->name.chars, IFNAMSIZ);
ffStrCopy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ);
if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0 && (IFM_TYPE(ifmr.ifm_active) & IFM_ETHER))
{
switch (IFM_SUBTYPE(ifmr.ifm_active))
+85 -45
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,53 @@ 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", "");
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);
else if(ffStrEquals(key, "Identity"))
ffDBusGetString(data, &dictIterator, &result->player);
else if(ffStrEquals(key, "DesktopEntry"))
ffDBusGetString(data, &dictIterator, &desktopIdentity);
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
}
if(result->song.length == 0)
{
@@ -91,17 +128,20 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
return false;
}
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "PlaybackStatus", &result->status);
if (result->player.length == 0)
{
if (desktopIdentity.length > 0)
{
ffStrbufDestroy(&result->player);
ffStrbufInitMove(&result->player, &desktopIdentity);
}
else
{
ffStrbufAppend(&result->player, &result->playerId);
}
}
//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);
data->lib->ffdbus_message_unref(reply);
return true;
}
@@ -122,9 +162,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);
+56
View File
@@ -0,0 +1,56 @@
#include "netio.h"
#include "common/netif/netif.h"
#include "util/mallocHelper.h"
#include <net/if.h>
#include <net/if_mib.h>
#include <sys/sysctl.h>
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
{
int mib[] = {CTL_NET, PF_LINK, NETLINK_GENERIC,
options->defaultRouteOnly ? IFMIB_IFDATA : IFMIB_IFALLDATA,
options->defaultRouteOnly ? (int) ffNetifGetDefaultRouteIfIndex() : 0,
IFDATA_GENERAL};
size_t bufSize = 0;
if (sysctl(mib, ARRAY_SIZE(mib), NULL, &bufSize, 0, 0) < 0)
return "sysctl(mib, ARRAY_SIZE(mib), NULL, &bufSize, 0, 0) failed";
assert(bufSize % sizeof(struct ifmibdata) == 0);
FF_AUTO_FREE struct ifmibdata* buf = (struct ifmibdata*) malloc(bufSize);
if (sysctl(mib, ARRAY_SIZE(mib), buf, &bufSize, 0, 0) < 0)
return "sysctl(mib, ARRAY_SIZE(mib), buf, &bufSize, 0, 0) failed";
size_t ifCount = bufSize / sizeof(struct ifmibdata);
const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName();
for (size_t i = 0; i < ifCount; i++)
{
struct ifmibdata* mibdata = &buf[i];
if (!(mibdata->ifmd_flags & IFF_RUNNING) || (mibdata->ifmd_flags & IFF_NOARP))
continue;
if (options->namePrefix.length && strncmp(mibdata->ifmd_name, options->namePrefix.chars, options->namePrefix.length) != 0)
continue;
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
*counters = (FFNetIOResult) {
.name = ffStrbufCreateS(mibdata->ifmd_name),
.txBytes = mibdata->ifmd_data.ifi_obytes,
.rxBytes = mibdata->ifmd_data.ifi_ibytes,
.txPackets = mibdata->ifmd_data.ifi_opackets,
.rxPackets = mibdata->ifmd_data.ifi_ipackets,
.txErrors = mibdata->ifmd_data.ifi_oerrors,
.rxErrors = mibdata->ifmd_data.ifi_ierrors,
.txDrops = mibdata->ifmd_snd_drops,
.rxDrops = mibdata->ifmd_data.ifi_iqdrops,
.defaultRoute = strncmp(mibdata->ifmd_name, defaultRouteIfName, IFNAMSIZ) == 0,
};
}
return NULL;
}
+2 -5
View File
@@ -1,8 +1,6 @@
#include "netio.h"
#include "common/io/io.h"
#include "common/netif/netif.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <net/if.h>
@@ -32,7 +30,6 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1);
assert(sdl->sdl_family == AF_LINK);
if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue;
sdl->sdl_data[sdl->sdl_nlen] = 0;
@@ -48,8 +45,8 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
.rxPackets = ifm->ifm_data.ifi_ipackets,
.txErrors = ifm->ifm_data.ifi_oerrors,
.rxErrors = ifm->ifm_data.ifi_ierrors,
#ifdef _IFI_OQDROPS
.txDrops = if2m->ifm_data.ifi_oqdrops,
#ifdef FF_HAVE_IFI_OQDROPS
.txDrops = ifm->ifm_data.ifi_oqdrops,
#else
.txDrops = 0, // unsupported
#endif
+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)
+28
View File
@@ -52,6 +52,15 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
if(!ffStrSet(xdgConfigDirs))
return;
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");
@@ -166,6 +175,17 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
return true;
}
else if (ffStrbufStartsWithS(&result->prettyName, "Armbian-unofficial ")) // Unofficial Armbian image built from source
{
ffStrbufSetS(&result->name, "Armbian (custom build)");
ffStrbufSetS(&result->id, "armbian");
ffStrbufSetS(&result->idLike, "debian");
ffStrbufClear(&result->versionID);
uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1;
uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' ');
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
return true;
}
else if (ffStrbufStartsWithS(&result->name, "Loc-OS"))
{
ffStrbufSetS(&result->id, "locos");
@@ -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
}
+4 -2
View File
@@ -20,22 +20,24 @@ typedef struct FFPackagesResult
uint32_t linglong;
uint32_t lpkg;
uint32_t lpkgbuild;
uint32_t macports;
uint32_t mport;
uint32_t nixDefault;
uint32_t nixSystem;
uint32_t nixUser;
uint32_t opkg;
uint32_t pacman;
uint32_t pacstall;
uint32_t paludis;
uint32_t pkg;
uint32_t pkgtool;
uint32_t macports;
uint32_t qi;
uint32_t rpm;
uint32_t scoop;
uint32_t snap;
uint32_t sorcery;
uint32_t winget;
uint32_t xbps;
uint32_t pacstall;
uint32_t all; //Make sure this goes last
+2 -2
View File
@@ -21,7 +21,7 @@ static uint32_t getSQLite3Int(const char* dbPath, const char* query, const char*
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
{
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
{
result->pkg = getSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages", "pkg");
}
if (!(options->disabled & FF_PACKAGES_FLAG_MPORT_BIT))
result->mport = getSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/mport/master.db", "SELECT count(*) FROM packages", "mport");
}
+1
View File
@@ -573,6 +573,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
}
if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", DT_DIR);
if (!(options->disabled & FF_PACKAGES_FLAG_PACSTALL_BIT)) packageCounts->pacstall += getNumElements(baseDir, "/var/lib/pacstall/metadata", DT_REG);
if (!(options->disabled & FF_PACKAGES_FLAG_QI_BIT)) packageCounts->qi += getNumStrings(baseDir, "/var/qi/installed_packages.list", "\n", "qi");
}
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
+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"
+4 -4
View File
@@ -58,8 +58,8 @@ static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result)
return;
char chocoPath[MAX_PATH + 3];
char* pend = ffStrCopyN(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath));
ffStrCopyN(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath));
char* pend = ffStrCopy(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath));
ffStrCopy(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath));
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco");
}
@@ -71,8 +71,8 @@ static void detectPacman(FFPackagesResult* result)
// MSYS2
char pacmanPath[MAX_PATH + 3];
char* pend = ffStrCopyN(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath));
ffStrCopyN(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath));
char* pend = ffStrCopy(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath));
ffStrCopy(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath));
result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL);
}
+4 -1
View File
@@ -2,7 +2,7 @@
#define FF_PHYSICALDISK_TEMP_UNSET (0/0.0)
typedef enum FFPhysicalDiskType
typedef enum __attribute__((__packed__)) FFPhysicalDiskType
{
FF_PHYSICALDISK_TYPE_NONE = 0,
@@ -15,7 +15,10 @@ typedef enum FFPhysicalDiskType
FF_PHYSICALDISK_TYPE_READWRITE = 1 << 4,
FF_PHYSICALDISK_TYPE_READONLY = 1 << 5,
FF_PHYSICALDISK_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFPhysicalDiskType;
static_assert(sizeof(FFPhysicalDiskType) == sizeof(uint8_t), "");
typedef struct FFPhysicalDiskResult
{
+1
View File
@@ -39,6 +39,7 @@ const char* ffDetectSound(FFlist* devices)
FFSoundDevice* device = ffListAdd(devices);
ffStrbufInitS(&device->identifier, path);
ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info);
ffStrbufTrimRightSpace(&device->name);
device->volume = mutemask & SOUND_MASK_VOLUME
? 0
: ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2;
@@ -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);;
}
@@ -98,12 +98,12 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon
if(terminalExe && terminalExe->length > 0 && !ffStrbufEqualS(terminalExe, "Windows Terminal"))
{
char jsonPath[MAX_PATH + 1];
char* pathEnd = ffStrCopyN(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1);
ffStrCopyN(pathEnd, ".portable", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
char* pathEnd = ffStrCopy(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1);
ffStrCopy(pathEnd, ".portable", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
if(ffPathExists(jsonPath, FF_PATHTYPE_ANY))
{
ffStrCopyN(pathEnd, "settings\\settings.json", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
ffStrCopy(pathEnd, "settings\\settings.json", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
if(!ffAppendFileBuffer(jsonPath, &json))
error = "Error reading Windows Terminal portable settings JSON file";
}
@@ -641,6 +641,39 @@ FF_MAYBE_UNUSED static bool getTerminalVersionPtyxis(FF_MAYBE_UNUSED FFstrbuf* e
ffStrbufSubstrAfterFirstC(version, ' ');
return true;
}
FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]) {
exe->chars,
"--version",
NULL
}) != NULL)
return false;
uint32_t index = ffStrbufFirstIndexS(version, "Tilix version: ");
if (index == version->length) return false;
index += (uint32_t) strlen("Tilix version:");
uint32_t end = ffStrbufNextIndexC(version, index, '\n');
ffStrbufSubstrBefore(version, end);
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
@@ -740,6 +773,12 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
if(ffStrbufIgnCaseEqualS(processName, "ptyxis-agent"))
return getTerminalVersionPtyxis(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "tilix"))
return getTerminalVersionTilix(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "sakura"))
return getTerminalVersionSakura(exe, version);
#endif
#ifdef _WIN32
+2
View File
@@ -28,6 +28,8 @@
#define FF_SYSNAME "Linux"
#elif defined(__DragonFly__) // We define `__FreeBSD__` on DragonFly BSD for simplification
#define FF_SYSNAME "DragonFly"
#elif defined(__MidnightBSD__)
#define FF_SYSNAME "MidnightBSD"
#elif defined(__FreeBSD__)
#define FF_SYSNAME "FreeBSD"
#elif defined(__APPLE__)
+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);
}
}
+113 -15
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;
}
@@ -190,7 +262,7 @@ static const char* detectWifiWithIoctls(FFWifiResult* item)
return "socket() failed";
struct iwreq iwr;
ffStrCopyN(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ);
ffStrCopy(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ);
ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE);
iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars;
iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1;
@@ -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))
+11
View File
@@ -0,0 +1,11 @@
.xMMMMMMMMMMMMMMMMMMMMMMx.
JDMMMMMMMMMMMMMMMMMMMMMMMMOL
IMMMY' 'YMMMI
MMMM MMMM
MMMM MMMM
IMMMb dMMMI
'YMMMMMMMMb. .dMMMMMMMMK'
'OMMMMMMMP' 'YMMMMMMMP'
$2.x76767$36767676$476767$5676x.
$2'*76767$36767676$476767$5676*'
+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._
`""""
+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} \\
+16
View File
@@ -0,0 +1,16 @@
..:::'''':::..
.:'''` `''':.
.:'` .::` `'::
:' .::' ':.
.:` .:::' `:.
:` :::: `:
:: ::::: ::
: ::::: :: :
: :::::: .:::' :
:: ::::::. : .:::::: ::
:. :::::::. : :::::::' .:
`:. `':::::::.'.:::::': .:'
`:. '':::::::::::::.: .:`
':. `''::::::::''' .:'
'':.. ``'`` ..:''
''''::::::''''
+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%@@@@@@@@@@@@@@@@#-.
.+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+:
:=*%@@@@@@@@@@@@@@@@@@@@@@%*=:.
.-=+*#%%@@@@@@%%#*+=-.
▁▂▃▄▅▆▇▇████▇▇▆▅▄▃▂▁
▃▅▇████████████████████▇▅▃
▂▅████████████████████████████▅▁
▗▟██████████████▛▀▀▜██████████████▙▖
▗▟████████████████▌ ▐████████████████▙▖
▗██████████████████▌ ▐██████████████████▖
▗███████████████████▌ ▐███████████████████▖
▕███████████████▀▘ ██▌ ▐██ ▝▀███████████████▏
▐██████████▛▀▀ ▂██▌ ▐██▂ ▀▀▜██████████▌
███████▀▀ ▁▄▆████▌ ▐████▆▄▁ ▀▀███████
█████ ▂▄▂ ▔▀▜████▌ ▐████▛▀▔ ▂▄▂ █████
▐████▄▄▆█████▄▂ ▔▀██▌ ▐██▀▔ ▂▄█████▆▄▄████▌
▕██████████████▇▄▂ ██▌ ▐██ ▂▄▇██████████████▏
▝███████████████████▌ ▐███████████████████▘
▝██████████████████▌ ▐██████████████████▘
▝▜████████████████▌ ▐████████████████▛▘
▝▜██████████████▙▄▄▟██████████████▛▘
▔▀▜██████████████████████████▛▀▔
▔▀▜████████████████████▛▀▔
▔▔▀▀▀▜██████▛▀▀▀▔▔

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