Compare commits

..

332 Commits

Author SHA1 Message Date
Carter Li 912f6c4f3c Merge pull request #752 from fastfetch-cli/dev
Release: v2.8.8
2024-03-08 09:54:06 +08:00
李通洲 77d71b5fef Doc: update changelog 2024-03-08 09:36:35 +08:00
Carter Li 6938a73a8a Users (Linux): fix detection of client ip 2024-03-08 09:17:40 +08:00
李通洲 cee9df189d Release: v2.8.8 2024-03-08 08:40:40 +08:00
李通洲 2a125e226b Terminal (Linux): ignore SessionLeader
I don't know why it's there, but let's ignore it for now
2024-03-07 22:38:03 +08:00
李通洲 4a7e60ef57 CPU (Linux): don't crash if /sys/devices/system/cpu/cpufreq/ doesn't exist
Ref: #750
2024-03-07 21:31:23 +08:00
李通洲 0a6140346e DisplayServer (Linux): fix old libdrm version compatibility
Ref: #748
2024-03-07 19:20:56 +08:00
Carter Li 01862ebc04 Display (Linux): fix width being detected as height when using libdrm 2024-03-07 14:39:13 +08:00
李通洲 3185299214 Doc: update changelog 2024-03-07 14:00:57 +08:00
李通洲 5b6ebe4f11 Doc: update README 2024-03-07 13:56:40 +08:00
李通洲 6274ef591b Vulkan: try fixing old vulkan-header library compatibility
Ref: #748
2024-03-07 13:34:31 +08:00
李通洲 7acdaebee4 Printing: merge ffPrintError and ffPrintErrorString 2024-03-07 11:10:18 +08:00
李通洲 6dcfb6b88f Fastfetch: fully resolve the format arg num issue
Ref: #749
2024-03-07 10:47:28 +08:00
李通洲 064972aecd Disk: fix segfault with --help disk-format
Fix #749
2024-03-07 09:04:22 +08:00
李通洲 b9dbb66bd7 fastfetch: revert changes of FASTFETCH_DATATEXT_STRUCTURE
Also add comments
2024-03-04 13:47:17 +08:00
李通洲 a01792c06c Doc: rename help.txt to help_footer.txt 2024-03-04 10:22:29 +08:00
李通洲 d707a67f89 Merge remote-tracking branch 'origin/master' into dev 2024-03-04 09:14:11 +08:00
李通洲 5d8aa11d81 Fastfetch: small performace optimization 2024-03-04 08:50:38 +08:00
李通洲 a87463fc09 Doc: fix truncated texts 2024-03-04 08:50:38 +08:00
李通洲 d0a4a012c4 Completions (Fish): fix old version compatibility
Fix #744
2024-03-03 18:48:05 +08:00
Carter Li 6a82d73fe9 Merge pull request #743 from fastfetch-cli/dev
Release: v2.8.7
2024-03-02 19:14:35 +08:00
李通洲 7504484f21 Release: v2.8.7 2024-03-02 18:46:48 +08:00
李通洲 d497853af5 Doc: update changelog 2024-03-02 18:45:48 +08:00
李通洲 c2f815f5ba Uptime (Android): fix implementation
Regression of 41fed1da5f
2024-03-02 18:37:32 +08:00
李通洲 4bd4ec2897 Terminal (Linux): detect zellij version 2024-03-02 18:32:31 +08:00
Adam Thiede fc685e9aa0 fix postmarketos logos (#742) 2024-03-01 23:54:47 +08:00
李通洲 14d3bd89a7 Brightness (Linux): fix ddcutil 2.1 compatibility 2024-03-01 22:07:54 +08:00
李通洲 c3970154d6 GPU (Linux): fix memleaks 2024-03-01 11:07:16 +08:00
李通洲 66aee54401 CMake: add more debug flags 2024-03-01 10:27:25 +08:00
Carter Li 979f7d19b1 CPU (Linux): fix max / min frequency detection for multi policy systems 2024-02-29 10:20:50 +08:00
Carter Li f238138711 Packaging: update debian stuff 2024-02-28 10:03:26 +08:00
李通洲 6c88981b05 JsonSchema: disallow additional properties 2024-02-28 09:17:29 +08:00
Carter Li c935527e6f Merge pull request #740 from fastfetch-cli/dev
Release: v2.8.6
2024-02-28 00:04:20 +08:00
李通洲 04915945f5 Doc: update changelog 2024-02-27 23:42:36 +08:00
李通洲 153df44282 TerminalFont (Linux): support warp terminal 2024-02-27 23:40:42 +08:00
李通洲 22012556f8 Terminal (Linux): support warp version detection 2024-02-27 23:35:07 +08:00
李通洲 d0b03c380b CI: build for FreeBSD aarch64 too 2024-02-27 22:29:00 +08:00
Carter Li de2cd79632 Merge pull request #739 from fastfetch-cli/dev
Release: v2.8.6
2024-02-27 22:05:53 +08:00
李通洲 cc40ef42f0 Release: v2.8.6 2024-02-27 21:28:01 +08:00
李通洲 ba45073e04 CI: fix windows build 2024-02-27 19:20:13 +08:00
李通洲 a3c3f3829d Shell (Linux): always detect tty id 2024-02-27 16:35:47 +08:00
李通洲 79b7b15b46 Terminal: detect tty name
Fix #738
2024-02-27 16:19:42 +08:00
李通洲 111f7111b2 GPU (Linux): Support specifying custom pci.ids path for Linux 2024-02-27 15:29:19 +08:00
李通洲 5147651bcb Temps: rename display.temperature to display.temp 2024-02-27 13:11:39 +08:00
李通洲 ba60d9059f Temps: support color range customization 2024-02-27 11:00:43 +08:00
李通洲 8f205b8c30 Percent: rename FFPercentConfig to FFColorRangeConfig 2024-02-27 08:32:31 +08:00
李通洲 e046787aec Terminal: better tmux version detection 2024-02-26 23:33:30 +08:00
李通洲 743eebaa6b CMake (macOS): force dlopen searching for /usr/local/lib 2024-02-26 13:35:11 +08:00
李通洲 609caad02f Global: use FASTFETCH_TARGET_DIR_USR where applicable 2024-02-26 13:30:09 +08:00
李通洲 a0c47204bb Temp: Display: support better temperature value formatting
Fix #737
2024-02-26 11:09:00 +08:00
李通洲 1c87693867 Percent: tidy 2024-02-26 10:23:00 +08:00
李通洲 42b756e703 GPU (Linux): revert show sub-device if available 2024-02-24 12:52:22 +08:00
Carter Li d317997396 Merge pull request #735 from fastfetch-cli/dev
Release: v2.8.5
2024-02-23 20:36:52 +08:00
李通洲 91dac1563b Release: v2.8.5 2024-02-23 20:34:39 +08:00
李通洲 73cfae97d2 DiskIO / NetIO: fix uninitialized variables 2024-02-23 20:30:54 +08:00
李通洲 78a606c1e1 Doc: update ubuntu ppa 2024-02-23 16:34:23 +08:00
Carter Li f258e484d9 Packaging: update debian stuff 2024-02-23 16:17:57 +08:00
Carter Li ea162fd452 Merge pull request #734 from fastfetch-cli/dev
Release: v2.8.4
2024-02-23 16:09:51 +08:00
李通洲 b80391b183 Release: v2.8.4 2024-02-23 15:56:12 +08:00
李通洲 4c7a9e4394 Doc: update changelog 2024-02-23 10:01:05 +08:00
李通洲 4b747f70a4 Disk (Linux): ensure only physical devices are detected
Ref: https://github.com/fastfetch-cli/fastfetch/issues/731#issuecomment-1955814211
2024-02-23 09:29:39 +08:00
李通洲 5fb4b6dc04 Display: --display-compact-type support *-with-refresh-rate
Ref: https://github.com/fastfetch-cli/fastfetch/discussions/732
2024-02-22 18:45:57 +08:00
李通洲 5e7cfe2976 Display: add option --display-order 2024-02-22 10:47:13 +08:00
李通洲 77db2d84a3 FFstrbuf: remove ffStrbufCompAlphabetically 2024-02-22 10:38:33 +08:00
李通洲 15bb5bfb24 Packages: add ability to disable specified package manager
Fix #729
2024-02-22 10:03:38 +08:00
李通洲 4e9ee9aa03 Package: code cleanup 2024-02-21 15:40:04 +08:00
李通洲 6a0c7ca788 Disk (Linux): try fixing multidevice bcachefs filesystem compatibility
Ref: #731
2024-02-21 09:05:26 +08:00
李通洲 90e99bcf69 Doc: fix invalid commands 2024-02-21 09:05:26 +08:00
Lenny0939 5b20a86d53 Fix mistake in README.md (#730)
Sudo is not necessary to use nix-shell, and puts you in a shell as root which is not ideal
2024-02-20 18:42:59 -06:00
李通洲 6ad1262f4a NetIO: add option --netio-detect-total 2024-02-20 14:44:55 +08:00
李通洲 e0297e1dd1 DiskIO: add option --diskio-detect-total 2024-02-20 14:43:50 +08:00
李通洲 937611aa29 Colors: support JSON config generation 2024-02-15 22:05:34 +08:00
李通洲 eda38e16db Colors: don't print extra empty lines 2024-02-15 21:55:33 +08:00
李通洲 2731756c39 Platform (Windows): small optimization 2024-02-15 20:29:57 +08:00
李通洲 853ca0f608 Platform (Windows): don't assume x86 as i686 2024-02-15 20:29:34 +08:00
李通洲 17f4a6e055 Colors: support block related settings
Fix #721
2024-02-14 22:09:12 +08:00
李通洲 925dc6f681 TerminalFont (Windows): support portable Windows Terminal settings
Fix #720
2024-02-13 19:49:49 +08:00
李通洲 706527eab4 Github: update ISSUE_TEMPLATE 2024-02-13 19:19:29 +08:00
李通洲 3a96ade423 CPU (Linux): don't segfault if we fail to find Vendor ID in lscpu
Fix #718
2024-02-13 19:08:44 +08:00
李通洲 da9c928286 CMake: make artifact file names consistant
Fix #719
2024-02-13 19:02:03 +08:00
Carter Li 30d3d00900 Merge pull request #717 from fastfetch-cli/dev
Release v2.8.3
2024-02-12 10:59:30 +08:00
李通洲 99fce80d0d CI: fix windows artifacts generation 2024-02-12 10:46:57 +08:00
Herby Gillot a5a28e30a0 README: add MacPorts install info (#716)
Add info on installing `fastfetch` on macOS via MacPorts: https://ports.macports.org/port/fastfetch/
2024-02-12 10:43:23 +08:00
李通洲 7fe39353df Release: v2.8.3 2024-02-12 10:28:29 +08:00
李通洲 a3576b3154 CI: release file name without version
Fix #714
2024-02-12 10:28:29 +08:00
AlbydS c5d0d84001 Add installation instructions for even more Linux distributions (#715)
Added Alpine (now with the right command), ALT Linux and Arch AUR to the installation instructions.
2024-02-12 10:20:10 +08:00
李通洲 467ed54a3b GPU (Linux): lazy load pci.ids 2024-02-12 10:12:34 +08:00
Carter 7ea8882843 GPU (FreeBSD): detect correct AMD card names 2024-02-12 18:09:11 +08:00
李通洲 f4cb3bb33f GPU (Linux): use amdgpu.ids 2024-02-12 00:43:06 +08:00
李通洲 330eb9fa21 GPU: show sub-device if available
Try fixing #713
2024-02-11 23:01:14 +08:00
李通洲 1006f513f5 Release: v2.8.2 2024-02-10 14:38:47 +08:00
李通洲 652c4b2e82 CI: don't upload old artifacts 2024-02-10 14:37:27 +08:00
李通洲 3c618a8cd0 Merge remote-tracking branch 'upstream/master' into dev 2024-02-10 14:14:09 +08:00
李通洲 b5821de793 Release: v2.8.1 2024-02-10 14:02:22 +08:00
李通洲 dec604691c CMake: try fixing packaging name conflicting 2024-02-10 13:59:34 +08:00
Carter Li 72baa6cca9 Merge pull request #712 from fastfetch-cli/dev
Release v2.8.0
2024-02-10 12:02:58 +08:00
李通洲 34b023a74f Release: 2.8.0 (ci skip)
For Luna New Year!
2024-02-10 10:32:14 +08:00
李通洲 8249a8ed6a Doc: update changelog 2024-02-09 00:10:29 +08:00
李通洲 7e1ac5e24a Terminal (Windows): code cleanup 2024-02-08 23:15:58 +08:00
李通洲 55c72a8bb3 Camera (Windows): fix Windows Server Core compatibility 2024-02-08 19:14:09 +08:00
Carter Li b602bb20c2 Battery (Linux): print the same format of battery status as other platforms 2024-02-08 14:10:51 +08:00
Carter Li 46ed24275f Battery (FreeBSD): fix typos 2024-02-08 13:59:02 +08:00
Carter Li 71db83f806 PowerAdapter (Linux): don't print not connected either
To align result to macOS
2024-02-08 13:51:30 +08:00
李通洲 0746afa0c2 PowerAdapter (macOS): don't show not connected if no power adapter is detected 2024-02-08 10:53:58 +08:00
李通洲 805c384819 Battery (macOS): don't show an empty battery if no battery is detected 2024-02-08 10:37:06 +08:00
Carter Li 9e4c0e318c Chore: add dpkg related stuff 2024-02-07 14:39:19 +08:00
李通洲 51eaac2fd7 Doc: update changelog 2024-02-06 09:54:33 +08:00
李通洲 92c3df82e6 Logo (Builtin): add PikaOS
Ref: https://github.com/hykilpikonna/hyfetch/pull/231
2024-02-06 09:30:24 +08:00
李通洲 7f238a701e Logo (Builtin): add tatra
Ref: https://github.com/dylanaraps/neofetch/pull/2439
2024-02-06 09:25:44 +08:00
李通洲 72236f62ad Logo (Builtin): add z/OS
Ref: https://github.com/dylanaraps/neofetch/pull/2436
2024-02-06 09:03:01 +08:00
李通洲 51b0c43d76 Platform (Windows): use %USERNAME% if available 2024-02-05 20:01:19 +08:00
李通洲 79e2007d30 Revert "Platform (Linux): use $HOSTNAME if available"
$HOSTNAME doesn't seem to be a standard variable

This reverts commit 02eb604ceb.
2024-02-05 20:01:18 +08:00
李通洲 02eb604ceb Platform (Linux): use $HOSTNAME if available
Ref: #710
2024-02-05 18:23:21 +08:00
李通洲 ce6b2b85f7 Locale (Linux): use environment variable if available
In some machine `setlocale(LC_MESSAGES, NULL)` returns `C` for some reason.
2024-02-05 16:25:12 +08:00
李通洲 48d1980061 CI: build linux old 2024-02-05 14:32:17 +08:00
李通洲 40fae5c5f1 Camera (Android): add empty color space result 2024-02-04 19:07:47 +08:00
李通洲 e296ee1040 CI (Linux): bump version of linux runners
Drop support of Debian 11
2024-02-04 15:48:58 +08:00
李通洲 199e71553d CI: run camera module 2024-02-04 15:14:18 +08:00
李通洲 13fa218e5a Camera: adjust output format 2024-02-04 14:17:18 +08:00
李通洲 eed5efabea Camera (Windows): detect color space 2024-02-04 14:17:18 +08:00
李通洲 d2315e967e Camera (macOS): detect color space 2024-02-04 14:17:18 +08:00
Carter Li cbe3c70480 Camera (Linux): add property colorspace 2024-02-04 14:17:18 +08:00
李通洲 c918226909 Fastfetch: print videodev2 in --list-features 2024-02-04 09:56:22 +08:00
李通洲 18472660ae CI (FreeBSD): remove unused depenencies 2024-02-04 09:27:04 +08:00
李通洲 458c2ccd01 Camera (FreeBSD): enable support
Requires build dependency `v4l_compat`
2024-02-04 09:26:19 +08:00
李通洲 7bb9efcebb Camera (Android): init support 2024-02-02 23:22:40 +08:00
李通洲 8a42dfd68d Camera: tidy; add module to all.jsonc 2024-02-02 22:43:01 +08:00
李通洲 3edd8a6740 Camera (Linux): init support 2024-02-02 22:14:25 +08:00
李通洲 cba22b7155 Camera (Windows): init support 2024-02-02 20:36:22 +08:00
李通洲 246ad6d288 Sound (Windows): tidy 2024-02-02 20:36:22 +08:00
李通洲 295e119810 Camera (macOS): new module 2024-02-02 20:36:22 +08:00
李通洲 cfe22f9524 Terminal (Linux): try fixing #707 (v2) 2024-02-01 17:56:40 +08:00
李通洲 de2c1d7786 CI: unify artifacts name (v2) 2024-02-01 16:00:33 +08:00
李通洲 7d74339aa0 CI: build in parallel 2024-02-01 15:43:56 +08:00
李通洲 7589e962c2 CI: unify artifact names 2024-02-01 15:25:05 +08:00
李通洲 9a189694f9 CI: silence more warnings 2024-02-01 15:24:07 +08:00
李通洲 4069fbfe7b CI: upgrade codeql-action 2024-02-01 15:02:37 +08:00
李通洲 7ccd886909 CI: build aarch64 binaries 2024-02-01 14:29:28 +08:00
李通洲 42957356b2 GPU: remove libpci related stuff 2024-02-01 13:38:15 +08:00
李通洲 9038cd32b2 Terminal (Linux): don't assume blackbox is build for flatpak 2024-02-01 09:14:06 +08:00
李通洲 128c3bfea6 TerminalShell (Linux): try supporting blackbox
Fix #707
2024-02-01 09:02:49 +08:00
李通洲 60ed822f6a GPU (Linux): fix detection in some cases 2024-01-31 18:58:48 +08:00
Carter Li 527ec1bc61 Logo (Builtin): add asahi2; make asahi logo actually work 2024-01-31 16:47:22 +08:00
Carter Li cbf203901b CPU (Linux): code refactor 2024-01-31 14:36:00 +08:00
Carter Li cf6f3dbe0c CI (Windows): fix build 2024-01-31 13:35:57 +08:00
Carter Li ab625497ce CPU (Linux): code refactor 2024-01-31 13:28:18 +08:00
Yussef Dalton 83532b68dd CPU (Linux): use marketing name on Asahi Linux 2024-01-31 11:02:41 +08:00
Carter Li cd2a1495b8 GPU (FreeBSD): use ffGPUParsePciIds 2024-01-31 10:39:09 +08:00
Carter Li b01d2bdd8c GPU (Linux): rewrite; drop libpci dependency 2024-01-31 10:20:49 +08:00
Carter Li 736d5316cc Merge pull request #705 from fastfetch-cli/dev
Release v2.7.1
2024-01-30 19:25:55 +08:00
李通洲 efe42a2c7d GPU: fix a copy-paste error 2024-01-30 18:54:26 +08:00
李通洲 ee07755139 Release: v2.7.1 2024-01-30 18:45:56 +08:00
李通洲 3d924eeadd Merge remote-tracking branch 'upstream/master' into dev 2024-01-30 18:27:24 +08:00
李通洲 aaa091f23b Terminal (Linux): fix segfault 2024-01-30 15:22:26 +08:00
李通洲 53cd1e5378 DateTime: print timezone info; simplify code 2024-01-29 22:01:54 +08:00
李通洲 3747683f0d GPU: add vendor code of QTI & MTK 2024-01-29 21:49:42 +08:00
李通洲 59c1e3d8c5 Platform: detect real path of exe path 2024-01-28 10:45:21 +08:00
Carter Li 1206f6d2ba Merge pull request #701 from fastfetch-cli/dev
Release v2.7.0
2024-01-26 11:06:32 +08:00
李通洲 9aad3e339a CMake: remove unused deps 2024-01-26 10:44:20 +08:00
李通洲 ef9221f305 CI: generate sha512sums [no ci] 2024-01-26 10:41:31 +08:00
李通洲 391a3a0430 Release: v2.7.0
Bump minor version because of rewriting the FreeBSD GPU detection code
2024-01-26 10:23:44 +08:00
李通洲 6b0314f14b Platform: fix exe path detection 2024-01-26 10:19:21 +08:00
李通洲 8e316eb080 Release: v2.6.4 2024-01-26 10:10:11 +08:00
李通洲 999f2170fe Terminal: ignore sshd 2024-01-26 09:53:12 +08:00
李通洲 0282b884cc OpenCL: fix possible segfaults
Found in Alpine Linux
2024-01-26 09:38:08 +08:00
李通洲 ef7e6d0a6a GPU (WSL): fix uninitialized variables 2024-01-26 09:20:58 +08:00
李通洲 77253a8d81 GPU (FreeBSD): better name detection 2024-01-26 09:20:58 +08:00
Carter Li 2041272f5f GPU (Linux): simpify code 2024-01-25 18:32:40 +08:00
Carter Li d2a41bdfe1 GPU (FreeBSD): drop pciutils dep 2024-01-25 10:33:06 +08:00
Carter Li 025a708ecb Shell: remove trailing \0 in JSON output 2024-01-25 10:33:06 +08:00
John Mertz 4e2c124442 ASCII logos for fedora immutable variants (#700)
Container Linux is also deprecated and continued as Fedora CoreOS
2024-01-23 23:38:41 -06:00
李通洲 79ba9d7a68 TerminalShell (Linux): fix segfault 2024-01-23 18:51:00 +08:00
李通洲 ee60ec3530 TerminalShell: don't detect sh as a terminal 2024-01-23 16:38:43 +08:00
李通洲 9d7cbb0fe3 Revert "3rdparty: use a newer wcwidch implementation"
Unwanted change

This reverts commit 28ea765f19.
2024-01-23 14:42:00 +08:00
李通洲 0b98a14977 Fastfetch: don't expand envs in --config
Since it can only be used in command line
2024-01-23 13:14:53 +08:00
李通洲 8f51763374 Linux: allow command substitution when expanding paths
Ref: https://github.com/fastfetch-cli/fastfetch/discussions/698
2024-01-23 13:13:30 +08:00
李通洲 28ea765f19 3rdparty: use a newer wcwidch implementation 2024-01-23 10:19:02 +08:00
李通洲 5378d05bfb Doc: update changelog 2024-01-22 19:33:27 +08:00
李通洲 bbf04f0d40 Doc: add TerminalTheme 2024-01-22 18:50:11 +08:00
李通洲 ec6195133b TerminalTheme: add new module 2024-01-22 16:40:27 +08:00
李通洲 fa8c99601c TerminalSize: tidy 2024-01-22 14:34:19 +08:00
李通洲 a5d5de90f8 Terminal (Linux): support screen version detection 2024-01-22 14:33:55 +08:00
李通洲 994fd359a5 Terminal (Linux): fix kgx version detection 2024-01-22 11:10:40 +08:00
李通洲 a9a5790cba TerminalShell (Linux): improve terminal detection by env 2024-01-22 11:10:40 +08:00
李通洲 31b3fe403a Wifi (Linux): remove trailing \n
Fix #697
2024-01-22 11:10:30 +08:00
李通洲 14b74fe51d Doc: update issue template 2024-01-22 09:10:03 +08:00
Carter Li 35a5a03cd7 Merge pull request #696 from fastfetch-cli/dev
Release v2.6.3
2024-01-21 23:04:15 +08:00
李通洲 f927b8ea87 Release: v2.6.3 2024-01-21 23:01:49 +08:00
李通洲 ebefcec3e2 Bluetooth: fix result printing 2024-01-21 23:00:38 +08:00
Carter Li c151bf0b37 Merge pull request #695 from fastfetch-cli/dev
Release v2.6.2
2024-01-21 17:54:12 +08:00
李通洲 a767104b96 TerminalShell (Windows): more variable initialization fixes 2024-01-21 17:52:03 +08:00
Carter Li 18fced9b2e Merge pull request #694 from fastfetch-cli/dev
Release 2.6.2
2024-01-21 17:46:02 +08:00
李通洲 713ef0ce34 Release: v2.6.2 2024-01-21 17:41:34 +08:00
李通洲 5b2db02bc1 CI: Fix building for GCC in Windows 2024-01-21 17:39:31 +08:00
Carter Li 0f69dc5980 Merge pull request #692 from fastfetch-cli/dev
Release 2.6.1
2024-01-20 22:34:06 +08:00
李通洲 6af57ff5b6 Doc: update changelog 2024-01-20 22:20:28 +08:00
Carter Li 7d7789565b PowerAdapter (macOS): improve detection for Intel macbook 2024-01-20 21:46:57 +08:00
Carter Li 0eb76e9636 Battery (macOS): improve manufacture info detection 2024-01-20 21:38:24 +08:00
李通洲 8b1ee64a3e GPU (macOS): fix gpu type detection 2024-01-20 20:57:33 +08:00
李通洲 b0acf168bf Doc: update changelog 2024-01-20 20:14:56 +08:00
李通洲 7ddc207574 Percentage: add options --percent-color-* 2024-01-20 20:06:42 +08:00
李通洲 d1a791b333 Global: make threshold of percentage colors configurable
Fix #689
2024-01-20 18:40:12 +08:00
李通洲 62ca495155 Percentage: prepare to make threshold configurable 2024-01-20 14:10:56 +08:00
李通洲 e7974a7cea Percentage: refactor function names 2024-01-20 13:49:04 +08:00
李通洲 24cb83dd18 Bluetooth / Gamepad / Sound: support percentage number formatting 2024-01-20 13:48:42 +08:00
李通洲 da5c44b3d0 Percentage: simplify usage of ffAppendPercentBar 2024-01-20 13:27:55 +08:00
李通洲 bd71aa931f Global: rename common/bar to common/percent 2024-01-20 11:28:38 +08:00
李通洲 4d1f242e1d Terminal (Windows): tidy 2024-01-19 22:23:32 +08:00
李通洲 d810245d55 Doc: update changelog 2024-01-19 21:54:44 +08:00
李通洲 06181ec433 Terminal (Windows): default default terminal to conhost 2024-01-19 21:54:44 +08:00
李通洲 8404ae034f Locale: improve detection
Linux: always use `setlocale`, fix #688
Windows: don't append `UTF-8`
2024-01-19 21:15:05 +08:00
李通洲 8e7d465333 Fastfetch: create sub folders when writing config file
Fix #690
2024-01-19 21:01:02 +08:00
李通洲 87813b3306 Shell: detect associated TTY 2024-01-19 16:43:08 +08:00
李通洲 9610a1ab23 TerminalShell (Windows): simplify nested shell detection by looking up GUI objects 2024-01-19 15:00:10 +08:00
李通洲 5f14781970 TerminalShell (Windows): set exePath 2024-01-19 14:40:07 +08:00
Carter Li 356488be0c TerminalShell (FreeBSD): detect real exe path 2024-01-19 14:40:07 +08:00
Carter Li e013c87890 TerminalShell (Linux): detect real exe path 2024-01-19 14:40:07 +08:00
李通洲 7d78d92a92 TerminalShell (macOS): detect full exe path 2024-01-19 14:40:07 +08:00
李通洲 06af39835a Terminal: don't use login as terminal process; set ppid 2024-01-19 14:40:07 +08:00
Carter Li eee8fb78d2 Shell (FreeBSD): detect arg0 instead of exe path 2024-01-19 14:40:07 +08:00
Carter Li 413f91260d Processes (FreeBSD): don't count sub-threads as processes 2024-01-19 14:40:07 +08:00
李通洲 a44daa04d6 Shell (Windows): better support xonsh detection 2024-01-18 18:08:08 +08:00
李通洲 d6cb405afe Release: v2.6.1 2024-01-18 15:31:36 +08:00
李通洲 b2a853cb6e Doc: update changelog 2024-01-18 15:28:49 +08:00
李通洲 0168f2e9a8 Shell: improve xonsh version detection 2024-01-18 15:27:31 +08:00
李通洲 3992d85eb6 CPU (Linux): show vendor if no model name available 2024-01-18 15:16:46 +08:00
李通洲 5096180e92 CPU (Linux): don't access out-of-bound memory 2024-01-18 15:06:47 +08:00
李通洲 947d2ff0a9 Processing (Linux): return error when command is not found 2024-01-18 14:54:14 +08:00
李通洲 1e4f174415 Shell (macOS): improve handling of xonsh 2024-01-18 14:07:29 +08:00
李通洲 2808b1a653 TerminalShell: improve xonsh version detection 2024-01-17 23:45:39 +08:00
李通洲 c749f214e0 Global: silence warnings when building in 32bit environments 2024-01-17 23:12:55 +08:00
Carter Li d0d9831d41 Merge pull request #686 from fastfetch-cli/dev
Release v2.6.0
2024-01-17 15:20:56 +08:00
李通洲 b3945e277c Global: review code 2024-01-17 15:06:52 +08:00
李通洲 9f77851176 JsonSchema: make it a valid json document 2024-01-17 14:08:31 +08:00
李通洲 963eaa5395 Release: v2.6.0 2024-01-17 14:02:07 +08:00
李通洲 07dfe57386 Doc: update changelog 2024-01-17 14:00:55 +08:00
Carter Li a3c0085e2b Sound: tidy 2024-01-17 13:31:34 +08:00
Carter Li c8f28e4c79 Sound (FreeBSD): don't use mixer.h
It's only supported in FreeBSD 14 and later
2024-01-17 10:22:56 +08:00
Carter Li 861eea5899 Sound (FreeBSD): new impl; drop pulseaudio dep 2024-01-16 17:40:41 +08:00
李通洲 1227799a38 Vulkan: print platformApi in JSON format 2024-01-15 18:14:40 +08:00
李通洲 35d1497053 Doc: update changelog 2024-01-15 15:48:39 +08:00
李通洲 ea3734f004 Locale (Windows): fix typo 2024-01-15 15:48:32 +08:00
李通洲 5d35dade60 DisplayServer (Windows): don't detect unknown display type as external 2024-01-15 15:22:33 +08:00
李通洲 0c844fc342 FFstrbuf: don't crash with ffStrbufInitStatic(&buf, NULL) 2024-01-15 15:22:33 +08:00
李通洲 c1ed0a4e91 Locale (Windows): print standard format 2024-01-15 15:22:33 +08:00
李通洲 e1af6fc0fe Locale: display only LC_MESSAGES if available, which is used by gettext 2024-01-15 14:27:29 +08:00
李通洲 c1d41a36bb CMake: fix build in macOS with -DENABLE_SYSTEM_YYJSON 2024-01-15 14:21:23 +08:00
李通洲 958bde228b Doc: fix typo 2024-01-15 13:30:18 +08:00
李通洲 6655c446ba Revert "Image: silence compiler warnings"
This reverts commit afa0a7dac8.
2024-01-15 13:15:43 +08:00
李通洲 43657e8fd6 Doc: update changelog 2024-01-15 11:29:29 +08:00
李通洲 38f216291e CMake: use system <yyjson.h> in fastfetch.c and flashfetch.c too
Fix #684
2024-01-15 11:22:42 +08:00
Carter Li 01de158bba Vulkan: print instance version if no vulkan drivers found 2024-01-15 10:33:55 +08:00
李通洲 5a34b8d01f Vulkan: error out if no results detected 2024-01-15 09:39:03 +08:00
李通洲 afa0a7dac8 Image: silence compiler warnings 2024-01-15 09:13:14 +08:00
李通洲 974ee2ab0d TerminalShell: fix wezterm name pretty printing 2024-01-14 17:26:54 +08:00
李通洲 ab1e3db665 Shell (Linux): detect ash version 2024-01-13 23:39:17 +08:00
李通洲 95b64622c4 Terminal (Linux): fix detection 2024-01-13 23:39:17 +08:00
李通洲 d3c7529c45 Processing (Windows): don't use CreateEventW 2024-01-13 13:38:53 +08:00
李通洲 89db425a03 Gamepad (Windows): use nonblocking read to get battery information 2024-01-13 13:33:29 +08:00
apocelipes 269ad36df5 refactor(TerminalShell): changing recursion into loops 2024-01-12 23:56:04 +08:00
李通洲 22cdb1247f TerminalShell: tidy; use case senstive string comparation where meaningful 2024-01-12 21:21:42 +08:00
李通洲 905ed76ddd TerminalShell: split terminal and shell detection code further 2024-01-12 20:58:45 +08:00
李通洲 6da57d64c3 TerminalShell: split terminal detection and shell detection 2024-01-12 16:44:19 +08:00
李通洲 37e0a7b03f stringUtils: tidy 2024-01-11 16:27:53 +08:00
李通洲 0c65cdc1f5 GPU (macOS): detect memory usage 2024-01-11 10:11:50 +08:00
李通洲 653e689f18 GPU (macOS): tidy 2024-01-11 09:55:13 +08:00
李通洲 a8aaf605b1 Doc: update changelog 2024-01-10 19:04:47 +08:00
李通洲 5f638a67ed Battery: rename manufacturerDate to manufactureDate 2024-01-10 19:03:58 +08:00
李通洲 0645f559af Monitor: detect serial number and manufacture date 2024-01-10 19:01:54 +08:00
李通洲 f5a57ab747 Doc: update changelog 2024-01-10 14:48:47 +08:00
李通洲 92e05f7e38 Chassis: don't print useless version 2024-01-10 14:44:14 +08:00
李通洲 8ba031b761 Brightness (FreeBSD): don't print empty () 2024-01-10 14:22:56 +08:00
李通洲 fdb68669f4 Battery (macOS): support manufacture date detection 2024-01-10 13:26:54 +08:00
李通洲 12155e029b Battery (Linux): support manufacture date detection 2024-01-09 23:08:19 +08:00
李通洲 7926b74917 Battery: detect manufacturer date 2024-01-09 22:58:32 +08:00
Carter Li 61af59fc00 Battery (Linux): fix temperature detection 2024-01-09 16:34:04 +08:00
李通洲 bc52613410 Gamepad: rename identifier to serial number 2024-01-09 15:53:42 +08:00
李通洲 f84bb1ebe2 Smbios: silence compiler warnings 2024-01-09 15:46:19 +08:00
李通洲 a160bc8de5 Gamepad (macOS): detect manufacturer 2024-01-09 15:28:03 +08:00
Carter Li cb599c6f2a Display (FreeBSD): support resolution detection in console 2024-01-08 16:03:07 +08:00
Carter Li 5693700c16 Bios (FreeBSD): fix boot type detection on some weird platforms 2024-01-08 16:02:52 +08:00
Carter Li e8c067ff3d Wifi (Linux): don't print invalid information 2024-01-08 11:32:39 +08:00
Carter Li 80cc4e3f4a Host (Linux): detect serial number for Asahi Linux 2024-01-08 11:19:35 +08:00
李通洲 8e78fadbeb Gamepad: don't provide device names of XBox compatible controllers 2024-01-08 10:38:40 +08:00
李通洲 1215eb06ca Gamepad (Windows): support battery detection of NS Pro 2024-01-07 19:07:15 +08:00
李通洲 2aa899d83c Gamepad (Linux): support battery level detection of NS Pro controller 2024-01-07 17:59:50 +08:00
李通洲 cf096eb101 Gamepad (Windows): detect serial number and battery (PS4 controller) 2024-01-06 23:43:35 +08:00
李通洲 5b4a26393d Gamepad (Linux): detect battery capacity 2024-01-06 20:40:20 +08:00
李通洲 2ba878cbab Monitor (Linux): fix detection with Nvidia drivers
NVIDIA DRM driver reports `enabled` to be `disabled`
2024-01-06 19:12:36 +08:00
李通洲 0af40ab6a3 Settings (FreeBSD): don't append trailing \0 2024-01-06 18:47:16 +08:00
李通洲 b9777bec77 Chassis: detect serial number 2024-01-06 18:35:10 +08:00
李通洲 8801921d02 Smbios: trim spaces 2024-01-06 18:33:57 +08:00
李通洲 c0c32456e8 Board: detect serial number 2024-01-06 18:12:51 +08:00
李通洲 640fa146c1 CPU (Windows): only use smbios to detect maximum speed
Because some virtual machines report invalid information
2024-01-06 18:00:59 +08:00
李通洲 de91429e1a CI: fix build 2024-01-06 17:11:39 +08:00
李通洲 1621484c96 CPU (Windows): don't report 30GHz in VMware 2024-01-06 17:11:26 +08:00
李通洲 d8297d296e CPU (Windows): use ThreadCount if GetLogicalProcessorInformationEx() fails 2024-01-06 17:11:26 +08:00
李通洲 48bb82c8fb Board (Windows): use SMBIOS result 2024-01-06 17:11:26 +08:00
李通洲 c1c7f7b93f Bios (Windows): use SMBIOS result 2024-01-06 17:11:26 +08:00
李通洲 1d35811253 Windows: make SMBIOS data a singleton 2024-01-06 17:11:26 +08:00
李通洲 fe0b43d92d CPU (Windows): detect the actual maximum frequency 2024-01-06 17:11:26 +08:00
李通洲 446fe907d2 Smbios: add comments, tidy 2024-01-06 17:11:26 +08:00
李通洲 d578f1006c Host / Chassis (Windows): remove options --*-use-wmi 2024-01-06 17:11:26 +08:00
李通洲 33f3199383 Host / Chassis (Windows): parse SMBIOS data directly 2024-01-06 17:11:25 +08:00
李通洲 21f3875c4f Host (Windows): detect serial number and UUID 2024-01-06 17:11:25 +08:00
李通洲 6bcd75835e Host: rename properties 2024-01-05 20:38:29 +08:00
李通洲 24cec76251 Host (Linux): detect serial number and uuid 2024-01-05 16:33:52 +08:00
李通洲 f8ac56691f Host (FreeBSD): detect serial number and uuid 2024-01-05 16:32:34 +08:00
李通洲 810112cb26 Host (macOS): detect serial number and uuid 2024-01-05 16:29:38 +08:00
李通洲 2340c2afd7 Board (macOS): print internal name instead of model indentifier
and actually detect the vendor
2024-01-05 16:24:43 +08:00
李通洲 b6c8649cbf macOS: improve IO service related code generally 2024-01-05 15:00:50 +08:00
李通洲 92a6b01133 Brightness (Apple): code optimise and fix mem leaks 2024-01-05 13:20:47 +08:00
李通洲 396112e8ea PowerAdapter: simplify implementation and support serial number detection 2024-01-05 11:01:32 +08:00
李通洲 5eacd0bb8e Battery (Apple): use less hard coded strings 2024-01-05 11:01:32 +08:00
李通洲 ea3ea196aa Battery (Linux): simplify temp detection 2024-01-05 11:01:32 +08:00
李通洲 0e6be69eb8 GPU (Linux): try detect GPU type 2024-01-04 18:50:38 +08:00
李通洲 d69e19377e Doc: update changelog 2024-01-04 16:31:41 +08:00
李通洲 f4f466d4ba Battery: print serial number 2024-01-04 16:21:19 +08:00
李通洲 10b2fe13bd Battery (Windows): detect serial number 2024-01-04 16:20:48 +08:00
李通洲 b5dc4f59f1 Battery (macOS): detect serial number 2024-01-04 16:04:34 +08:00
李通洲 7c0b743c61 Merge remote-tracking branch 'origin/master' into dev 2024-01-04 15:33:16 +08:00
李通洲 6bd909c89d Doc: update changelog 2024-01-04 15:27:31 +08:00
李通洲 1fef41241a Presets: fix formatation 2024-01-04 15:27:31 +08:00
Carter Li 5c75e271ef PowerAdapter (Linux): add support 2024-01-04 15:16:51 +08:00
Carter Li b6b1993f62 Battery (Linux): code refactor, support serial number detection 2024-01-04 15:16:51 +08:00
Carter Li cd0109c382 Battery (Linux): remove option --battery-dir
It was added in c5c3cecb93 but there was no comment or issues linked to indicate why it was necessary.

`/sys/class/power_supply` is standardized in <https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power>. I don't I want to support non-standard platform unless proper reason is given
2024-01-04 14:18:33 +08:00
Carter Li 6698283430 GPU: fix vendor detection for asahi 2024-01-04 10:29:02 +08:00
李通洲 83ce3e4554 Wallpaper (macOS): support Sonoma 2024-01-03 10:15:56 +08:00
李通洲 ff0f91dc3c macOS: fix mem leaks 2024-01-03 10:12:48 +08:00
李通洲 ab028964bf GPU (WSL): add missing FF_USE_PROPRIETARY_GPU_DRIVER_API macro guards 2024-01-02 18:47:06 +08:00
李通洲 21353b8256 CMake (GPU): change ENABLE_NVIDIA_GPU to ENABLE_PROPRIETARY_GPU_DRIVER_API 2024-01-02 10:49:03 +08:00
Viorel 0a1de91a29 Add option for NVIDIA GPU support 2024-01-01 22:18:03 +08:00
272 changed files with 7391 additions and 3027 deletions
+5 -4
View File
@@ -19,7 +19,10 @@ assignees: ''
# Often helpful information:
The content of the configuration file you use (if any)
Screenshot:
<!-- Paste the screenshot here -->
The content of the configuration file you use (if any):
```
//paste here
```
@@ -43,9 +46,7 @@ Output of `fastfetch --list-features`:
Paste the stacktrace here. You may get it with:
```
$ gdb /path/to/fastfetch
$ run
$ bt
$ gdb -q -ex 'set confirm off' -ex run -ex 'bt full' -ex quit --args /path/to/fastfetch
```
If you are able to identify which module crashed, the strace can be helpful too
+201 -58
View File
@@ -10,7 +10,7 @@ jobs:
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install codespell
shell: bash
@@ -26,7 +26,6 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
compiler: [
{ cc: gcc, cxx: "g++" },
{ cc: clang, cxx: "clang++" },
@@ -37,7 +36,7 @@ jobs:
# The feature libraries are all build against glibc, so they can't be used with musl
- compiler: { cc: "musl-gcc", cxx: "musl-g++" }
enableFeatures: ON
runs-on: ${{ matrix.os }}
runs-on: ubuntu-22.04
steps:
- name: checkout repository
uses: actions/checkout@v4
@@ -46,16 +45,16 @@ jobs:
run: uname -a
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev libdrm-dev
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libddcutil-dev libchafa-dev libdrm-dev directx-headers-dev
- name: configure project
env:
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} -DENABLE_DRM=${{ matrix.enableFeatures }} .
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} -DENABLE_DRM=${{ matrix.enableFeatures }} -DENABLE_DDCUTIL=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} .
- name: build project
run: cmake --build .
run: cmake --build . --verbose -j4
- name: run tests
run: ctest
@@ -72,9 +71,68 @@ jobs:
- name: run flashfetch
run: time ./flashfetch
linux:
name: Linux
runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package
Linux-old-amd64:
name: Linux-old-amd64
runs-on: ubuntu-20.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: uname -a
run: uname -a
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: c
- name: configure project
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
- name: build project
run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v3
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-old-amd64
path: ./fastfetch-*.*
linux-amd64:
name: Linux-amd64
runs-on: ubuntu-22.04 # Ubuntu 22.04 uses Glibc 2.35. Should be fine with Debian 12, which uses Glibc 2.36 (https://packages.debian.org/source/bookworm/glibc)
permissions:
security-events: write
contents: read
@@ -88,15 +146,15 @@ jobs:
run: uname -a
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick ddcutil --ignore-dependencies
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: c
@@ -104,10 +162,10 @@ jobs:
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
- name: build project
run: cmake --build . --target package --verbose
run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
- name: list features
run: ./fastfetch --list-features
@@ -134,11 +192,46 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux
name: fastfetch-linux-amd64
path: ./fastfetch-*.*
macos:
name: MacOS
linux-aarch64:
name: Linux-aarch64
runs-on: ubuntu-22.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: run VM
uses: uraimo/run-on-arch-action@v2
id: runcmd
with:
arch: aarch64
distro: ubuntu22.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-aarch64
path: ./fastfetch-*.*
macos-universal:
name: macOS-universal
runs-on: macos-latest
permissions:
security-events: write
@@ -156,7 +249,7 @@ jobs:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: c
@@ -164,10 +257,10 @@ jobs:
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
- name: build project
run: cmake --build . --target package --verbose
run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
- name: list features
run: ./fastfetch --list-features
@@ -190,12 +283,12 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-macos
name: fastfetch-macos-universal
path: ./fastfetch-*.*
freebsd:
name: FreeBSD
runs-on: macos-12
freebsd-amd64:
name: FreeBSD-amd64
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
@@ -207,13 +300,16 @@ jobs:
uses: cross-platform-actions/action@master
with:
operating_system: freebsd
architecture: x86-64
cpu_count: 3
shell: bash
version: '13.2'
run: |
uname -a
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package --verbose
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch
time ./fastfetch --format json
@@ -224,11 +320,48 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-freebsd
name: fastfetch-freebsd-amd64
path: ./fastfetch-*.*
win64:
name: Win64
freebsd-aarch64:
name: FreeBSD-aarch64
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: run VM
uses: cross-platform-actions/action@master
with:
operating_system: freebsd
architecture: arm64
cpu_count: 3
shell: bash
version: '13.2'
run: |
uname -a
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch
time ./fastfetch --format json
time ./flashfetch
ldd fastfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-freebsd-aarch64
path: ./fastfetch-*.*
windows-amd64:
name: Windows-amd64
runs-on: windows-latest
permissions:
security-events: write
@@ -254,7 +387,7 @@ jobs:
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --verbose
run: cmake --build . --verbose -j4
- name: copy necessary dlls
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
@@ -278,19 +411,19 @@ jobs:
run: ctest
- name: create zip archive
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe presets
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.7z *.dll fastfetch.exe flashfetch.exe presets
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-win64
path: ./fastfetch-*-Win64.*
name: fastfetch-windows-amd64
path: ./fastfetch-windows-amd64.*
win32:
name: Win32
windows-i686:
name: Windows-i686
runs-on: windows-latest
permissions:
security-events: write
@@ -313,7 +446,7 @@ jobs:
run: uname -a
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: c, cpp
@@ -321,10 +454,10 @@ jobs:
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --verbose
run: cmake --build . --verbose -j4
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
- name: copy necessary dlls
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
@@ -345,27 +478,29 @@ jobs:
run: ctest
- name: create zip archive
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe presets
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.7z *.dll fastfetch.exe flashfetch.exe presets
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-win32
path: ./fastfetch-*-Win32.*
name: fastfetch-windows-i686
path: ./fastfetch-windows-i686.*
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
name: Release
runs-on: ubuntu-latest
needs:
- linux
- macos
- freebsd
- win64
- win32
- linux-amd64
- linux-aarch64
- macos-universal
- freebsd-amd64
- freebsd-aarch64
- windows-amd64
- windows-i686
permissions:
contents: write
steps:
@@ -376,38 +511,46 @@ jobs:
repository: ${{ github.repository }}
- name: download artifacts
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: actions/download-artifact@v4
- name: rm old artifacts
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
run: |
rm -rf fastfetch-*-old-*
- name: create release
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ needs.linux.outputs.ffversion }}
tag: ${{ needs.linux-amd64.outputs.ffversion }}
commit: ${{ github.sha }}
artifactErrorsFailBuild: true
artifacts: fastfetch-*/fastfetch-*
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details."
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details."
- name: download source tarballs
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
run: |
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-amd64.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
ls fastfetch-*/*
- name: generate release notes
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
run: |
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
- name: update release body
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ needs.linux.outputs.ffversion }}
tag: ${{ needs.linux-amd64.outputs.ffversion }}
commit: ${{ github.sha }}
bodyFile: fastfetch-release-notes.md
allowUpdates: true
+169
View File
@@ -1,3 +1,172 @@
# 2.8.8
Bugfixes:
* Fix old fish version compatibility (#744)
* Fix truncated texts in `--help format` (#745)
* Fix old vulkan-header and libdrm library compatibility (#748, Linux)
* Fix possible segfaults in `--help *-format` (#749)
* Fix invalid resolution detection when using libdrm (Linux, Display)
* Fix segfault when `/sys/devices/system/cpu/cpufreq/` doesn't exist (#750, CPU, Linux)
* Don't detect `SessionLeader` as terminal (Terminal, Linux)
* Fix detection of client IP (Users, Linux)
# 2.8.7
Bugfixes:
* Fix max CPU frequency detection for some cases (CPU, Linux)
* Fix some memory leaks
* Fix ddcutil 2.1 compatibility (Brightness, Linux)
* Workaround `permission denied` error when reading `/proc/uptime` (Uptime, Android)
Features:
* Support zellij version detection (Linux, Terminal)
Logo:
* Fix PostMarketOS
# 2.8.6
Changes:
* Due to newly introduced configs, JSONC option `{ "temperatureUnit": "C" }` has been changed to `{ "temp": { "unit": "C" } }`
Bugfixes:
* Fix incorrect GPU name detection for Intel iGPU on Linux (#736, GPU, Linux)
Features:
* Support additional temperature formatting options (#737)
* `{ "temp": { "ndigits": 1 } }`
* `{ "temp": { "color": { "green": "green", "yellow": "yellow", "red": "red" } } }`
* Support specifying custom `pci.ids` path for Linux (GPU, Linux)
* Support warp-linux terminal version & terminal font detection (Terminal, Linux)
# 2.8.5
Bugfixes:
* Fix uninitialized variables
# 2.8.4
Bugfixes:
* Fix segfault if we fail to find `Vendor ID` in `lscpu` (#718, CPU, Linux)
* Fix multi-device bcachefs filesystem compatibility (#731, Disk, Linux)
Features:
* Support portable Windows Terminal settings (#720, Terminal, Windows)
* Support `--color-block-width` and `--color-block-range` (#721, Colors)
* Support `--diskio-detect-total` to show total bytes read/written (DiskIO)
* Support `--netio-detect-total` to show total bytes received/sent (NetIO)
* Support `--packages-disabled` to disable specified package manager (#729, Packages)
* Support `--display-order` to sort multiple displays in a specific order (Display)
* Support `--display-compact-type original-with-refresh-rate` to show refresh rates in compact (oneline) mode (Display)
# 2.8.3
Bugfixes:
* Fix GPU name detection for AMD graphic cards (GPU, Linux / FreeBSD)
# 2.8.2
Changes:
* The linux binaries are now built with glibc 2.35, which means they no longer support Debian 11 and Ubuntu 20.04. Users using these distros may download the artifacts `fastfetch-linux-old` from GitHub Actions.
Features:
* Rewrite GPU module, drop libpci dependency (GPU, Linux)
* Detect marketing name of Apple Silicon CPUs for asahi linux (CPU, Linux)
* Add new module `Camera`, which prints the name and resolution of connected cameras
Bugfixes:
* Fix compatibility with packages installed by flatpak (Terminal, Linux)
* Don't show an empty battery if no battery is detected (macOS, Battery)
* Don't show `not connected` if no power adapter is found (macOS / Linux, PowerAdapter)
* Make format of battery status be consistent with other platforms (Linux, Battery)
Logo:
* Print Asahi logo in asahi linux (Logo, Linux)
* Add Asahi2, z/OS, Tatra, PikaOS
# 2.7.1
Features:
* Config presets in app folder now work with symlinks
Bugfixes:
* Fix a possible segfault when detecting terminal (Terminal, Linux)
# 2.7.0
Features:
* Add new module `TerminalTheme`, which prints the foreground and background color of the current terminal window. Currently doesn't work on Windows.
* Allow command substitution when expanding paths. For example, now it's possible to use `"source": "$(ls ~/path/to/images/*.png | shuf -n 1)"` in JSONC config file to randomly choose an image to display. (#698)
* Use native methods instead of pciutils to detect GPUs in FreeBSD. (GPU, FreeBSD)
Bugfixes:
* Fix text formatting (Wifi, Linux)
* Fix terminal detection in some cases (Terminal)
* Remove trailing `\0` in JSON results (FreeBSD)
* Fix uninitialized variables (GPU, Linux)
* Fix a possible segfault (OpenCL)
Logo:
* Add ASCII logos for fedora immutable variants (#700)
# 2.6.3
Bugfixes:
* Fix module not working (Bluetooth)
# 2.6.2
Bugfixes:
* Fix building for GCC in Windows (Windows)
# 2.6.1
Features:
* Improve xonsh shell detection (Shell)
* Support colored percentage values (Bluetooth / Gamepad / Sound)
* Add `--<module>-percent-[green|yellow]` options to specify threshold of percentage colors
* eg. `--disk-percent-green 20 --disk-percent-yellow 50` will show green if disk usage is less than 20%, yellow if disk usage is less then 50%, and red otherwise.
* Add `--percent-color-[green|yellow|red]` options to specify color of different percent value states.
* eg. `--percent-color-green blue` will show blue color if percent value falls in green state.
* Improve Intel macbook support (macOS)
Bugfixes:
* Fix segfault in CPU module when running in aarch64 machine without `lscpu` installed (CPU, Linux)
* Don't use `login` as terminal process (Terminal, Linux)
* Silence warnings when building in 32bit machines.
* Create sub folders when writing config file (#690)
* Improve user specific locale detection; fix locale detection in Windows 7 (Locale)
* Fix GPU type detection (GPU, macOS)
# 2.6.0
Changes:
* Remove support of option `--battery-dir`. We detect a lot of things in `/sys/class/*` and only module `Battery` supports specifying a custom directory for some reason, which is weird.
* Remove `--chassis-use-wmi` which is no longer used.
Features:
* Add `ENABLE_PROPRIETARY_GPU_DRIVER_API` cmake option to disable using of proprietary GPU driver APIs (GPU)
* Support wallpaper detection for macOS Sonoma (Wallpaper, macOS)
* Support power adapter detection for Asahi Linux (PowerAdapter, Linux)
* Support battery serial number and manufacturer date detection (Battery)
* Support host serial number and UUID detection (Host)
* Support battery level detection for gamepads where possible (Gamepad)
* Support maximum CPU clock detection. Previously base clock was printed (CPU, Windows)
* Support manufacture date and serial number detection for physical monitors (Monitor)
* Support ash (default shell of BusyBox) version detection (Shell, Linux)
* Sound module in FreeBSD now uses native `ioctl`s. Pulseaudio dependency is no longer used.
* Locale module in Windows now prints the same format as in Linux and other posix systems.
Bugfixes:
* Fix overall memory leaks (macOS)
* Remove trailing `\0` in JSON results (FreeBSD)
* Fix physical monitor detection with Nvidia drivers (Monitor, Linux)
* Don't print llvmpipe in vulkan module (Vulkan)
* Fix system yyjson usage in `fastfetch.c`. Previously embedded `3rdparty/yyjson/yyjson.h` was used in `fastfetch.c` even if `ENABLE_SYSTEM_YYJSON` was set (CMake)
* Fix locale module printing unexpected results in specific environments (Locale)
* Fix battery temperature detection in Windows. Note only smart batteries report temperatures but few laptops uses smart battery (Battery, Windows)
* Print device name if no backlight name is available, so we don't print empty parentheses (Brightness, FreeBSD)
# 2.5.0
Changes:
+79 -32
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.5.0
VERSION 2.8.8
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -42,7 +42,6 @@ include(CheckIncludeFile)
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF)
@@ -66,17 +65,21 @@ cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_PROPRIETARY_GPU_DRIVER_API "Enable proprietary GPU driver API (NVML, IGCL and AGS)" ON)
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
if (LINUX)
set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
endif()
####################
# Compiler options #
####################
@@ -109,12 +112,8 @@ endif()
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
endif()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
elseif(APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc")
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
@@ -123,7 +122,7 @@ if(ENABLE_ASAN)
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -fstack-protector-all -fno-delete-null-pointer-checks")
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
endif()
@@ -234,10 +233,9 @@ 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.txt DATATEXT_HELP)
fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER)
fastfetch_load_text(src/data/help_color.txt DATATEXT_HELP_COLOR)
fastfetch_load_text(src/data/help_format.txt DATATEXT_HELP_FORMAT)
fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG)
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
@@ -268,7 +266,7 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
#######################
set(LIBFASTFETCH_SRC
src/common/bar.c
src/common/percent.c
src/common/commandoption.c
src/common/font.c
src/common/format.c
@@ -282,6 +280,7 @@ set(LIBFASTFETCH_SRC
src/common/printing.c
src/common/properties.c
src/common/settings.c
src/common/temps.c
src/detection/chassis/chassis.c
src/detection/cpu/cpu.c
src/detection/cpuusage/cpuusage.c
@@ -290,13 +289,13 @@ set(LIBFASTFETCH_SRC
src/detection/displayserver/displayserver.c
src/detection/font/font.c
src/detection/gpu/gpu.c
src/detection/locale/locale.c
src/detection/media/media.c
src/detection/netio/netio.c
src/detection/opencl/opencl.c
src/detection/os/os.c
src/detection/packages/packages.c
src/detection/publicip/publicip.c
src/detection/terminaltheme/terminaltheme.c
src/detection/terminalfont/terminalfont.c
src/detection/terminalshell/terminalshell.c
src/detection/version/version.c
@@ -313,6 +312,7 @@ set(LIBFASTFETCH_SRC
src/modules/board/board.c
src/modules/brightness/brightness.c
src/modules/break/break.c
src/modules/camera/camera.c
src/modules/chassis/chassis.c
src/modules/colors/colors.c
src/modules/cpu/cpu.c
@@ -352,6 +352,7 @@ set(LIBFASTFETCH_SRC
src/modules/swap/swap.c
src/modules/media/media.c
src/modules/terminal/terminal.c
src/modules/terminaltheme/terminaltheme.c
src/modules/terminalfont/terminalfont.c
src/modules/terminalsize/terminalsize.c
src/modules/theme/theme.c
@@ -374,7 +375,6 @@ set(LIBFASTFETCH_SRC
src/util/FFlist.c
src/util/FFstrbuf.c
src/util/platform/FFPlatform.c
src/util/stringUtils.c
src/util/smbiosHelper.c
)
@@ -405,12 +405,13 @@ if(LINUX)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gpu/gpu_nvidia.c
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_linux.c
src/detection/icons/icons_linux.c
src/detection/libc/libc_linux.c
src/detection/lm/lm_linux.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_linux.c
src/detection/media/media_linux.c
@@ -420,7 +421,7 @@ if(LINUX)
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/poweradapter/poweradapter_linux.c
src/detection/processes/processes_linux.c
src/detection/gtk_qt/qt.c
src/detection/sound/sound_linux.c
@@ -437,6 +438,7 @@ if(LINUX)
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
)
elseif(ANDROID)
@@ -464,6 +466,7 @@ elseif(ANDROID)
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_android.c
src/detection/lm/lm_nosupport.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
src/detection/media/media_nosupport.c
@@ -489,6 +492,7 @@ elseif(ANDROID)
src/detection/wm/wm_nosupport.c
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c
src/detection/camera/camera_android.c
src/util/platform/FFPlatform_unix.c
)
elseif(BSD)
@@ -518,13 +522,14 @@ elseif(BSD)
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gpu/gpu_nvidia.c
src/detection/gpu/gpu_bsd.c
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_bsd.c
src/detection/lm/lm_linux.c
src/detection/icons/icons_linux.c
src/detection/libc/libc_bsd.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_bsd.c
src/detection/media/media_linux.c
@@ -537,7 +542,7 @@ elseif(BSD)
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_bsd.c
src/detection/gtk_qt/qt.c
src/detection/sound/sound_linux.c
src/detection/sound/sound_bsd.c
src/detection/swap/swap_bsd.c
src/detection/temps/temps_bsd.c
src/detection/terminalfont/terminalfont_linux.c
@@ -551,6 +556,7 @@ elseif(BSD)
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
)
elseif(APPLE)
@@ -580,6 +586,7 @@ elseif(APPLE)
src/detection/lm/lm_nosupport.c
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_apple.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_apple.c
src/detection/media/media_apple.m
@@ -600,11 +607,12 @@ elseif(APPLE)
src/detection/theme/theme_nosupport.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.c
src/detection/wallpaper/wallpaper_apple.m
src/detection/wifi/wifi_apple.m
src/detection/wm/wm_apple.c
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_apple.m
src/detection/camera/camera_apple.m
src/util/apple/cf_helpers.c
src/util/apple/osascript.m
src/util/platform/FFPlatform_unix.c
@@ -620,7 +628,7 @@ elseif(WIN32)
src/detection/bluetooth/bluetooth_windows.c
src/detection/board/board_windows.c
src/detection/brightness/brightness_windows.cpp
src/detection/chassis/chassis_windows.cpp
src/detection/chassis/chassis_windows.c
src/detection/cpu/cpu_windows.c
src/detection/cpuusage/cpuusage_windows.c
src/detection/cursor/cursor_windows.c
@@ -630,13 +638,11 @@ elseif(WIN32)
src/detection/displayserver/displayserver_windows.c
src/detection/font/font_windows.c
src/detection/gpu/gpu_windows.c
src/detection/gpu/gpu_nvidia.c
src/detection/gpu/gpu_intel.c
src/detection/gpu/gpu_amd.c
src/detection/host/host_windows.c
src/detection/icons/icons_windows.c
src/detection/libc/libc_windows.cpp
src/detection/lm/lm_nosupport.c
src/detection/locale/locale_windows.c
src/detection/localip/localip_windows.c
src/detection/gamepad/gamepad_windows.c
src/detection/media/media_nosupport.c
@@ -662,6 +668,7 @@ elseif(WIN32)
src/detection/wm/wm_windows.cpp
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_windows.c
src/detection/camera/camera_windows.cpp
src/util/windows/getline.c
src/util/windows/com.cpp
src/util/windows/registry.c
@@ -676,6 +683,17 @@ if(ENABLE_DIRECTX_HEADERS)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp)
endif()
if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32))
message(STATUS "Enabling proprietary GPU driver API")
if(LINUX OR BSD OR WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
endif()
if(WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c)
endif()
endif()
include(CheckFunctionExists)
check_function_exists(wcwidth HAVE_WCWIDTH)
if(NOT HAVE_WCWIDTH)
@@ -699,9 +717,20 @@ add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32))
target_compile_definitions(libfastfetch PRIVATE FF_USE_PROPRIETARY_GPU_DRIVER_API)
endif()
if(yyjson_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(libfastfetch PRIVATE yyjson)
target_link_libraries(libfastfetch PRIVATE yyjson::yyjson)
# `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
else()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
endif()
endif()
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
@@ -737,6 +766,11 @@ if(HAVE_WCWIDTH)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WCWIDTH)
endif()
if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
endif()
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
if(NOT ENABLE_${VARNAME})
return()
@@ -773,10 +807,6 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
endforeach()
endfunction()
ff_lib_enable(LIBPCI
"libpci"
"Pci"
)
ff_lib_enable(VULKAN
"vulkan"
"Vulkan"
@@ -899,9 +929,11 @@ if(LINUX)
)
elseif(APPLE)
target_link_libraries(libfastfetch
PRIVATE "-framework AVFoundation"
PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreFoundation"
PRIVATE "-framework CoreAudio"
PRIVATE "-framework CoreMedia"
PRIVATE "-framework CoreVideo"
PRIVATE "-framework CoreWLAN"
PRIVATE "-framework IOBluetooth"
@@ -993,6 +1025,13 @@ set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
if(yyjson_FOUND)
target_compile_definitions(fastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(fastfetch PRIVATE yyjson::yyjson)
target_compile_definitions(flashfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(flashfetch PRIVATE yyjson::yyjson)
endif()
if(WIN32)
set(TARGET_NAME fastfetch)
target_sources(fastfetch
@@ -1079,6 +1118,14 @@ install(
##################
set(CPACK_GENERATOR "TGZ;ZIP")
if(APPLE)
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-universal" CPACK_PACKAGE_FILE_NAME)
else() # We don't use this in Windows
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CMAKE_SYSTEM_PROCESSOR "amd64")
endif()
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
endif()
if(LINUX)
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
@@ -1095,7 +1142,7 @@ set(CPACK_SET_DESTDIR ON)
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
set(CPACK_PACKAGE_DESCRIPTION "\
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
It is written in c to achieve much better performance.\
It is written mostly in C to achieve much better performance.\
")
include(CPack)
+14 -3
View File
@@ -27,12 +27,17 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
### Linux
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch-<version>-Linux.deb`
* Arch Linux: `sudo pacman -S fastfetch`
Some distros packaged a outdated fastfetch version. Older version is not supported, please always ensure that the latest version is used.
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or above)
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch-<version>-Linux.deb` (for Ubuntu 22.04 or above and Debian 12 or above).
* Arch Linux: `sudo pacman -S fastfetch`. You can also find fastfetch [on the AUR](https://aur.archlinux.org/packages/fastfetch-git).
* Fedora: `sudo dnf install fastfetch`
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
* NixOS: `sudo nix-shell -p fastfetch`
* Alpine: `apk add --upgrade fastfetch`
* NixOS: `nix-shell -p fastfetch`
* openSUSE: `sudo zypper install fastfetch`
* ALT Linux: `sudo apt-get install fastfetch`
Replace sudo with doas depending on what you use.
@@ -40,8 +45,14 @@ Replace sudo with doas depending on what you use.
### macOS
...via [HomeBrew](https://brew.sh):
`brew install fastfetch`
...via [MacPorts](https://www.macports.org):
`sudo port install fastfetch`
### Windows
`scoop install fastfetch`
-1
View File
@@ -384,7 +384,6 @@ __fastfetch_completion()
"--lib-pulse"
"--lib-ddcutil"
"--lib-nm"
"--battery-dir"
)
local FF_OPTIONS_LOGO=(
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env fish
if not type -q fastfetch
return
exit
end
complete -c fastfetch -f
+30
View File
@@ -0,0 +1,30 @@
fastfetch (2.8.6) jammy; urgency=medium
* Update to 2.8.6
-- Carter Li <zhangsongcui@live.cn> Wed, 28 Feb 2024 10:01:40 +0800
fastfetch (2.8.4) jammy; urgency=medium
* Update to 2.8.4
-- Carter Li <zhangsongcui@live.cn> Fri, 23 Feb 2024 16:14:57 +0800
fastfetch (2.7.1ubuntu2) jammy; urgency=medium
* Ignore .git
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 14:23:23 +0800
fastfetch (2.7.1ubuntu1) jammy; urgency=medium
* Update build scripts
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 13:53:37 +0800
fastfetch (2.7.1) jammy; urgency=medium
* Initial release.
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
+1
View File
@@ -0,0 +1 @@
12
+13
View File
@@ -0,0 +1,13 @@
Source: fastfetch
Section: universe/utils
Priority: optional
Maintainer: Carter Li <zhangsongcui@live.cn>
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Standards-Version: 4.0.0
Homepage: https://github.com/fastfetch-cli/fastfetch
Package: fastfetch
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
It is written mainly in C, with performance and customizability in mind.
+11
View File
@@ -0,0 +1,11 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: fastfetch
Source: https://github.com/fastfetch-cli/fastfetch
Files: *
Copyright: 2024 fastfetch-cli
License: Expat
Files: src/3rdparty/yyjson/*
Copyright: 2020 YaoYuan
License: Expat
+1
View File
@@ -0,0 +1 @@
fastfetch_2.8.6_source.buildinfo universe/utils optional
Vendored Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
debuild -S -i -I
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
Vendored Executable
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/make -f
%:
dh $@ --buildsystem=cmake+ninja
override_dh_ctest_configure:
dh_ctest_configure -- -DSET_TWEAK=OFF -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
+4
View File
@@ -0,0 +1,4 @@
version=4
opts="filenamemangle=s%.*/@ANY_VERSION@%@PACKAGE@-$1.tar.gz%,searchmode=plain" \
https://api.github.com/repos/fastfetch-cli/fastfetch/releases?per_page=100 \
https://api.github.com/repos/fastfetch-cli/fastfetch/tarball/@ANY_VERSION@
+361 -106
View File
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/schema",
"$schema": "https://json-schema.org/draft-07/schema",
"$defs": {
"colors": {
"type": "string",
@@ -26,9 +26,56 @@
"format": {
"description": "Output format of the module",
"type": "string"
},
"percent": {
"description": "Threshold of percentage colors",
"type": "object",
"additionalProperties": false,
"properties": {
"green": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Value less then green will be shown in green"
},
"yellow": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Value greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red"
}
}
},
"temperature": {
"description": "Detect and display temperature if supported",
"oneOf": [
{
"type": "boolean",
"default": false
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"green": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Value (in celsius) less then green will be shown in green"
},
"yellow": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Value (in celsius) greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red"
}
}
}
]
}
},
"type": "object",
"additionalProperties": false,
"title": "JSON config",
"description": "JSON config file for fastfetch. Usually be `~/.config/fastfetch.jsonc`",
"properties": {
@@ -51,6 +98,7 @@
{
"description": "Fastfetch logo configurations",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Set the type of the logo given",
@@ -78,6 +126,7 @@
},
"color": {
"type": "object",
"additionalProperties": false,
"description": "Overwrite a color in the logo",
"properties": {
"1": {
@@ -116,8 +165,7 @@
"description": "Color 9",
"$ref": "#/$defs/colors"
}
},
"additionalProperties": false
}
},
"width": {
"type": "integer",
@@ -131,6 +179,7 @@
},
"padding": {
"type": "object",
"additionalProperties": false,
"description": "Set the padding of the logo",
"properties": {
"top": {
@@ -148,8 +197,7 @@
"description": "Set the right padding of the logo",
"minimum": 0
}
},
"additionalProperties": false
}
},
"printRemaining": {
"type": "boolean",
@@ -173,6 +221,7 @@
},
"chafa": {
"type": "object",
"additionalProperties": false,
"description": "Chafa configuration. See chafa document for details",
"properties": {
"fgOnly": {
@@ -215,17 +264,16 @@
"DIFFUSION"
]
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
}
]
},
"general": {
"description": "Fastfetch general configurations",
"type": "object",
"additionalProperties": false,
"properties": {
"multithreading": {
"type": "boolean",
@@ -254,7 +302,7 @@
"description": "Force display detection to use DRM. Linux only",
"oneOf": [
{
"type": "bool",
"type": "boolean",
"const": false,
"description": "Try `wayland`, then `x11`, then `drm`"
},
@@ -264,7 +312,7 @@
"const": "sysfs-only"
},
{
"type": "bool",
"type": "boolean",
"const": true,
"description": "Try `libdrm` first, then `sysfs` if libdrm failed"
}
@@ -281,12 +329,12 @@
"description": "Set the timeout (ms) when waiting for child processes, `-1` for no timeout",
"default": 1000
}
},
"additionalProperties": false
}
},
"display": {
"description": "Configure how things to be displayed",
"type": "object",
"additionalProperties": false,
"properties": {
"stat": {
"type": "boolean",
@@ -327,6 +375,7 @@
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"keys": {
"description": "Set the color of the keys",
@@ -336,8 +385,7 @@
"description": "Set the color of the title",
"$ref": "#/$defs/colors"
}
},
"additionalProperties": false
}
}
]
},
@@ -372,6 +420,7 @@
},
"size": {
"type": "object",
"additionalProperties": false,
"description": "Set how a size value should be displayed",
"properties": {
"maxPrefix": {
@@ -389,14 +438,48 @@
}
}
},
"temperatureUnit": {
"type": "string",
"description": "Set the unit of the temperature",
"enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"],
"default": "C"
"temp": {
"type": "object",
"additionalProperties": false,
"description": "Set how temperature values should be displayed",
"properties": {
"unit": {
"type": "string",
"description": "Set the unit of the temperature",
"enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"],
"default": "C"
},
"ndigits": {
"type": "integer",
"description": "Set the number of digits to keep after the decimal point when formatting temperature values",
"minimum": 0,
"maximum": 9,
"default": 1
},
"color": {
"type": "object",
"additionalProperties": false,
"description": "Set color used in different states of temperature values",
"properties": {
"green": {
"description": "Color used in green state",
"$ref": "#/$defs/colors"
},
"yellow": {
"description": "Color used in yellow state",
"$ref": "#/$defs/colors"
},
"red": {
"description": "Color used in red state",
"$ref": "#/$defs/colors"
}
}
}
}
},
"bar": {
"type": "object",
"additionalProperties": false,
"description": "Set the bar configuration",
"properties": {
"charElapsed": {
@@ -424,6 +507,7 @@
},
"percent": {
"type": "object",
"additionalProperties": false,
"description": "Set how a percentage value should be displayed",
"properties": {
"type": {
@@ -439,6 +523,25 @@
"minimum": 0,
"maximum": 9,
"default": 0
},
"color": {
"type": "object",
"additionalProperties": false,
"description": "Set color used in different states of percentage bars and numbers",
"properties": {
"green": {
"description": "Color used in green state",
"$ref": "#/$defs/colors"
},
"yellow": {
"description": "Color used in yellow state",
"$ref": "#/$defs/colors"
},
"red": {
"description": "Color used in red state",
"$ref": "#/$defs/colors"
}
}
}
}
},
@@ -447,12 +550,12 @@
"description": "Whether to disable the stdout application buffer",
"default": false
}
},
"additionalProperties": false
}
},
"library": {
"description": "Set the path of a library to load",
"type": "object",
"additionalProperties": false,
"properties": {
"pci": {
"type": "string",
@@ -554,8 +657,7 @@
"description": "Used for brightness detection of external displays (Linux)",
"type": "string"
}
},
"additionalProperties": false
}
},
"modules": {
"description": "Fastfetch modules to run",
@@ -612,6 +714,7 @@
"terminal",
"terminalfont",
"terminalsize",
"terminaltheme",
"title",
"theme",
"uptime",
@@ -627,6 +730,7 @@
},
{
"type": "object",
"additionalProperties": false,
"description": "Run module with custom configurations",
"required": [
"type"
@@ -639,16 +743,20 @@
"oneOf": [
{
"title": "Break",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "break",
"description": "Print a empty line"
}
},
"additionalProperties": false
}
},
{
"title": "module",
"description": "No additional properties",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"anyOf": [
@@ -672,10 +780,6 @@
"const": "font",
"description": "Print system font name"
},
{
"const": "gamepad",
"description": "List connected gamepads"
},
{
"const": "host",
"description": "Print product name of your computer"
@@ -700,10 +804,6 @@
"const": "media",
"description": "Print playing song name"
},
{
"const": "memory",
"description": "Print system memory usage info"
},
{
"const": "monitor",
"description": "Print connected physical monitor information"
@@ -732,10 +832,6 @@
"const": "shell",
"description": "Print current shell name and version"
},
{
"const": "swap",
"description": "Print swap (paging file) space usage"
},
{
"const": "terminal",
"description": "Print current terminal name and version"
@@ -748,6 +844,10 @@
"const": "terminalsize",
"description": "Print current terminal size"
},
{
"const": "terminaltheme",
"description": "Print current terminal theme (foreground and background colors)"
},
{
"const": "theme",
"description": "Print current theme of desktop environment"
@@ -794,29 +894,27 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Battery",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "battery",
"description": "Print battery capacity, status, etc"
},
"dir": {
"description": "The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only",
"type": "string"
},
"useSetupApi": {
"description": "Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only",
"type": "boolean",
"default": false
},
"temp": {
"description": "Detect and display Battery temperature if supported",
"type": "boolean",
"default": false
"$ref": "#/$defs/temperature"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
@@ -830,11 +928,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Bluetooth",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "List bluetooth devices",
@@ -845,6 +944,9 @@
"type": "boolean",
"default": false
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -857,16 +959,20 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Brightness",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "brightness",
"description": "Print current brightness level of your monitors"
},
"percent": {
"$ref": "#/$defs/percent"
},
"ddcciSleep": {
"type": "integer",
"description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail",
@@ -878,16 +984,13 @@
},
{
"title": "Chassis",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "chassis",
"description": "Print chassis type (desktop, laptop, etc)"
},
"useWmi": {
"description": "Set if WMI query should be used on Windows, which detects more information but slower",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
@@ -904,15 +1007,15 @@
},
{
"title": "CPU",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print CPU name, frequency, etc",
"const": "cpu"
},
"temp": {
"description": "Detect and display CPU temperature if supported",
"type": "boolean",
"default": false
"$ref": "#/$defs/temperature"
},
"freqNdigits": {
"description": "Set the number of digits to keep after the decimal point when printing CPU frequency",
@@ -933,16 +1036,20 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "CPU Usage",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "cpuusage",
"description": "Print CPU usage. Costs some time to collect data"
},
"percent": {
"$ref": "#/$defs/percent"
},
"separate": {
"type": "boolean",
"description": "Display CPU usage per CPU logical core, instead of an average result",
@@ -952,6 +1059,8 @@
},
{
"title": "Colors",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print some colored blocks",
@@ -975,11 +1084,37 @@
"type": "integer",
"minimum": 0,
"default": 0
},
"block": {
"description": "Set behavior of block printing",
"type": "object",
"additionalProperties": false,
"properties": {
"width": {
"description": "Set the block width in spaces",
"type": "integer",
"minimum": 1,
"default": 3
},
"range": {
"description": "Set the range of colors in the blocks to print",
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 15
},
"minItems": 2,
"maxItems": 2
}
}
}
}
},
{
"title": "Command",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Running custom shell scripts",
@@ -1005,11 +1140,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Custom",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print a custom string, with or without key",
@@ -1032,11 +1168,12 @@
},
"required": [
"format"
],
"additionalProperties": false
]
},
{
"title": "Display",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print resolutions, refresh rates, etc",
@@ -1046,7 +1183,9 @@
"enum": [
"none",
"original",
"scaled"
"scaled",
"original-with-refresh-rate",
"scaled-with-refresh-rate"
],
"description": "Set if all displays should be printed in one line",
"default": "none"
@@ -1056,6 +1195,15 @@
"type": "boolean",
"default": false
},
"order": {
"description": "Set the order should be used when printing",
"enum": [
"none",
"asc",
"desc"
],
"default": "none"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1068,11 +1216,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Disk",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print partitions, space usage, disk type, etc",
@@ -1112,6 +1261,9 @@
"description": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes",
"default": false
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1124,11 +1276,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "DiskIO",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print physical disk I/O throughput",
@@ -1138,6 +1291,11 @@
"description": "Show disks with given name prefix only",
"type": "string"
},
"detectTotal": {
"description": "Detect total bytes instead of current rate",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1150,11 +1308,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "DE",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "de",
@@ -1179,17 +1338,43 @@
}
}
},
{
"title": "Gamepad",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "gamepad",
"description": "List connected gamepads"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
}
},
{
"title": "GPU",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print GPU names, graphic memory size, type, etc",
"const": "gpu"
},
"temp": {
"description": "Detect and display GPU temperature if supported",
"type": "boolean",
"default": false
"$ref": "#/$defs/temperature"
},
"driverSpecific": {
"description": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)",
@@ -1222,11 +1407,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Local IP",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "List local IP addresses (v4 or v6), MAC addresses, etc",
@@ -1278,11 +1464,38 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Memory",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "memory",
"description": "Print system memory usage info"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
}
},
{
"title": "NetIO",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print network I/O throughput",
@@ -1297,6 +1510,11 @@
"type": "boolean",
"default": true
},
"detectTotal": {
"description": "Detect total bytes instead of current rate",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1309,11 +1527,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "OpenGL",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print highest OpenGL version supported by the GPU",
@@ -1341,20 +1560,21 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Packages",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "packages",
"description": "List installed package managers and count of installed packages"
},
"winget": {
"description": "Set if winget package count should be detected.\nNote this is very slow operation. Please make sure `winget list` works before enable this option\nWindows only",
"type": "boolean",
"default": false
"disabled": {
"description": "A colon separated list of package managers to be disabled when detecting",
"type": "string",
"default": "winget"
},
"key": {
"$ref": "#/$defs/key"
@@ -1372,6 +1592,8 @@
},
{
"title": "Physical Disk",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print physical disk information",
@@ -1382,9 +1604,7 @@
"type": "string"
},
"temp": {
"description": "Detect and display SSD temperature if supported",
"type": "boolean",
"default": false
"$ref": "#/$defs/temperature"
},
"key": {
"$ref": "#/$defs/key"
@@ -1398,11 +1618,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Public IP",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print your public IP address, etc",
@@ -1432,11 +1653,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Separator",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print a separator line",
@@ -1447,11 +1669,12 @@
"type": "string",
"default": "-"
}
},
"additionalProperties": false
}
},
{
"title": "Sound",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print sound devices, volume, etc",
@@ -1467,6 +1690,9 @@
],
"default": "main"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1479,11 +1705,38 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Swap",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "swap",
"description": "Print swap (paging file) space usage"
},
"percent": {
"$ref": "#/$defs/percent"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
}
},
{
"title": "Title",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print title, which contains your user name, hostname",
@@ -1496,6 +1749,8 @@
},
"color": {
"description": "Set colors of the different part of title",
"type": "object",
"additionalProperties": false,
"properties": {
"user": {
"description": "Set color of the user name (left part)",
@@ -1509,8 +1764,7 @@
"description": "Set color of the host name (right part)",
"$ref": "#/$defs/colors"
}
},
"additionalProperties": false
}
},
"key": {
"$ref": "#/$defs/key"
@@ -1524,11 +1778,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "Weather",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Print weather information",
@@ -1561,11 +1816,12 @@
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
}
},
{
"title": "WM",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "wm",
@@ -1595,6 +1851,5 @@
]
}
}
},
"additionalProperties": false
}
}
+2
View File
@@ -28,6 +28,7 @@
"terminal",
"terminalfont",
"terminalsize",
"terminaltheme",
"cpu",
"cpuusage",
"gpu",
@@ -49,6 +50,7 @@
"users",
"bluetooth",
"sound",
"camera",
"gamepad",
"weather",
"netio",
+2
View File
@@ -34,6 +34,7 @@
"terminal",
"terminalfont",
"terminalsize",
"terminaltheme",
"cpu",
"cpuusage",
"gpu",
@@ -55,6 +56,7 @@
"users",
"bluetooth",
"sound",
"camera",
"gamepad",
{
"type": "weather",
-111
View File
@@ -1,111 +0,0 @@
#include "common/bar.h"
#include "common/color.h"
#include "util/textModifier.h"
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red)
{
assert(green <= 100 && yellow <= 100 && red <= 100);
const FFOptionsDisplay* options = &instance.config.display;
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
uint32_t blocksGreen = (uint32_t) (green / 100.0 * options->barWidth + 0.5);
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * options->barWidth + 0.5);
uint32_t blocksRed = (uint32_t) (red / 100.0 * options->barWidth + 0.5);
assert(blocksPercent <= options->barWidth);
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
else
ffStrbufAppendS(buffer, "[ ");
}
for (uint32_t i = 0; i < blocksPercent; ++i)
{
if(!options->pipe)
{
if (i == blocksGreen)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
else if (i == blocksYellow)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
else if (i == blocksRed)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
ffStrbufAppend(buffer, &options->barCharElapsed);
}
if (blocksPercent < options->barWidth)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharTotal);
}
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
else
ffStrbufAppendS(buffer, " ]");
}
if(!options->pipe)
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
// if (green < yellow)
// [0, green]: print green
// (green, yellow]: print yellow
// (yellow, 100]: print red
//
// if (green > yellow)
// [green, 100]: print green
// [yellow, green): print yellow
// [0, yellow): PRINT RED
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses)
{
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
if (colored && !options->pipe)
{
if(percent != percent)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
else if(green < yellow)
{
if (percent <= green)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
else if (percent <= yellow)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
else
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
else
{
if (percent >= green)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
else if (percent >= yellow)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
else
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
}
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
if (colored && !options->pipe)
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
if (parentheses)
ffStrbufAppendC(buffer, ')');
}
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#include "fastfetch.h"
enum
{
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,
};
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red);
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses);
+3 -3
View File
@@ -26,7 +26,7 @@ void ffPrepareCommandOption(FFdata* data)
FFOptionsModules* const options = &instance.config.modules;
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
ffPrepareCPUUsage();
@@ -118,7 +118,7 @@ static void parseStructureCommand(
}
}
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
}
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
@@ -168,7 +168,7 @@ void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
{
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
//Parse the structure and call the modules
uint32_t startIndex = 0;
+1
View File
@@ -211,6 +211,7 @@ void ffFontInitValues(FFfont* font, const char* name, const char* size)
ffFontInit(font);
ffStrbufAppendS(&font->name, name);
ffStrbufTrim(&font->name, '"');
ffStrbufAppendS(&font->size, size);
fontInitPretty(font);
+1 -1
View File
@@ -57,7 +57,7 @@ static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
uint32_t result = UINT32_MAX;
if(placeholderValue->chars[0] != '-')
sscanf(placeholderValue->chars, "%u", &result);
sscanf(placeholderValue->chars, "%" PRIu32, &result);
return result == 0 ? UINT32_MAX : result;
}
+4
View File
@@ -24,3 +24,7 @@ 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)
+12 -3
View File
@@ -163,9 +163,6 @@ void ffListFeatures(void)
#ifdef FF_HAVE_THREADS
"threads\n"
#endif
#ifdef FF_HAVE_LIBPCI
"libpci\n"
#endif
#ifdef FF_HAVE_VULKAN
"vulkan\n"
#endif
@@ -241,9 +238,21 @@ void ffListFeatures(void)
#ifdef FF_HAVE_DDCUTIL
"libddcutil\n"
#endif
#if __has_include(<linux/videodev2.h>)
"videodev2\n"
#endif
#ifdef FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
"Proprietary GPU driver API\n"
#endif
#ifdef FF_USE_SYSTEM_YYJSON
"System yyjson\n"
#endif
#ifdef FF_USE_PCI_MEMORY
"PCI memory\n"
#endif
""
, stdout);
}
+1 -1
View File
@@ -105,7 +105,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
unsigned int mode = fileStat.st_mode & S_IFMT;
if(pathType & FF_PATHTYPE_FILE && mode == S_IFREG)
if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR)
return true;
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
+1 -1
View File
@@ -115,7 +115,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
#if __has_include(<wordexp.h>) // https://github.com/termux/termux-packages/pull/7056
wordexp_t exp;
if(wordexp(in, &exp, WRDE_NOCMD) != 0)
if(wordexp(in, &exp, 0) != 0)
return false;
if (exp.we_wordc == 1)
+1 -1
View File
@@ -235,6 +235,6 @@ void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
yyjson_mut_doc_set_root(jsonDoc, obj);
}
else
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
ffPrintError("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
}
}
+2
View File
@@ -15,6 +15,7 @@ static FFModuleBaseInfo* B[] = {
};
static FFModuleBaseInfo* C[] = {
(void*) &instance.config.modules.camera,
(void*) &instance.config.modules.chassis,
(void*) &instance.config.modules.command,
(void*) &instance.config.modules.colors,
@@ -124,6 +125,7 @@ static FFModuleBaseInfo* T[] = {
(void*) &instance.config.modules.terminal,
(void*) &instance.config.modules.terminalFont,
(void*) &instance.config.modules.terminalSize,
(void*) &instance.config.modules.terminalTheme,
(void*) &instance.config.modules.title,
(void*) &instance.config.modules.theme,
NULL,
+1 -1
View File
@@ -143,7 +143,7 @@ void ffOptionParseColor(const char* value, FFstrbuf* buffer)
while(*value != '\0')
{
#define FF_APPEND_COLOR_CODE_COND(prefix, code) \
if(strncasecmp(value, #prefix, strlen(#prefix)) == 0) { ffStrbufAppendS(buffer, code); value += strlen(#prefix); }
if(ffStrStartsWithIgnCase(value, #prefix)) { ffStrbufAppendS(buffer, code); value += strlen(#prefix); }
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
-16
View File
@@ -96,22 +96,6 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result)
}
}
void ffParseTemperature(double celsius, FFstrbuf* buffer)
{
switch (instance.config.display.temperatureUnit)
{
case FF_TEMPERATURE_UNIT_CELSIUS:
ffStrbufAppendF(buffer, "%.1f°C", celsius);
break;
case FF_TEMPERATURE_UNIT_FAHRENHEIT:
ffStrbufAppendF(buffer, "%.1f°F", celsius * 1.8 + 32);
break;
case FF_TEMPERATURE_UNIT_KELVIN:
ffStrbufAppendF(buffer, "%.1f K", celsius + 273.15);
break;
}
}
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
+7 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#include "fastfetch.h"
#include "util/FFstrbuf.h"
#include <stdint.h>
@@ -11,6 +11,12 @@ typedef struct FFVersion
uint32_t patch;
} FFVersion;
typedef struct FFColorRangeConfig
{
uint8_t green;
uint8_t yellow;
} FFColorRangeConfig;
#define FF_VERSION_INIT ((FFVersion) {0})
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
@@ -20,4 +26,3 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
void ffParseSize(uint64_t bytes, FFstrbuf* result);
void ffParseTemperature(double celsius, FFstrbuf* buffer);
+211
View File
@@ -0,0 +1,211 @@
#include "fastfetch.h"
#include "common/percent.h"
#include "common/color.h"
#include "common/option.h"
#include "common/jsonconfig.h"
#include "util/textModifier.h"
#include "util/stringUtils.h"
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config)
{
uint8_t green = config.green, yellow = config.yellow;
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
assert(blocksPercent <= options->barWidth);
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
else
ffStrbufAppendS(buffer, "[ ");
}
if (percent != percent)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
for (uint32_t i = 0; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharElapsed);
}
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;
for (uint32_t i = 0; i < blocksPercent; ++i)
{
if(!options->pipe)
{
uint32_t section1Begin = (uint32_t) ((green <= yellow ? green : yellow) / 100.0 * options->barWidth + 0.5);
uint32_t section2Begin = (uint32_t) ((green > yellow ? green : yellow) / 100.0 * options->barWidth + 0.5);
if (i == section2Begin)
ffStrbufAppendF(buffer, "\e[%sm", (green > yellow ? colorGreen : colorRed));
else if (i == section1Begin)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else if (i == 0)
ffStrbufAppendF(buffer, "\e[%sm", (green <= yellow ? colorGreen : colorRed));
}
ffStrbufAppend(buffer, &options->barCharElapsed);
}
if (blocksPercent < options->barWidth)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharTotal);
}
}
if(options->barBorder)
{
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
else
ffStrbufAppendS(buffer, " ]");
}
if(!options->pipe)
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses)
{
uint8_t green = config.green, yellow = config.yellow;
assert(green <= 100 && yellow <= 100);
const FFOptionsDisplay* options = &instance.config.display;
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
if (colored && !options->pipe)
{
const char* colorGreen = options->percentColorGreen.chars;
const char* colorYellow = options->percentColorYellow.chars;
const char* colorRed = options->percentColorRed.chars;
if(percent != percent)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
else if(green <= yellow)
{
if (percent > yellow)
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
else if (percent > green)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
else
{
if (percent < yellow)
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
else if (percent < green)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
}
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
if (colored && !options->pipe)
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
if (parentheses)
ffStrbufAppendC(buffer, ')');
}
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config)
{
if (!ffStrStartsWithIgnCase(subkey, "percent-"))
return false;
subkey += strlen("percent-");
if (ffStrEqualsIgnCase(subkey, "green"))
{
uint32_t num = ffOptionParseUInt32(key, value);
if (num > 100)
{
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
exit(480);
}
config->green = (uint8_t) num;
return true;
}
if (ffStrEqualsIgnCase(subkey, "yellow"))
{
uint32_t num = ffOptionParseUInt32(key, value);
if (num > 100)
{
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
exit(480);
}
config->yellow = (uint8_t) num;
return true;
}
return false;
}
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config)
{
if (!ffStrEqualsIgnCase(key, "percent"))
return false;
if (!yyjson_is_obj(value))
{
fprintf(stderr, "Error: usage: %s must be an object\n", key);
exit(480);
}
yyjson_val* greenVal = yyjson_obj_get(value, "green");
if (greenVal)
{
int num = yyjson_get_int(greenVal);
if (num < 0 || num > 100)
{
fputs("Error: usage: percent.green must be between 0 and 100\n", stderr);
exit(480);
}
config->green = (uint8_t) num;
}
yyjson_val* yellowVal = yyjson_obj_get(value, "yellow");
if (yellowVal)
{
int num = yyjson_get_int(yellowVal);
if (num < 0 || num > 100)
{
fputs("Error: usage: percent.yellow must be between 0 and 100\n", stderr);
exit(480);
}
config->yellow = (uint8_t) num;
}
return true;
}
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config)
{
if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow)
return;
yyjson_mut_val* percent = yyjson_mut_obj_add_obj(doc, module, "percent");
if (config.green != defaultConfig.green)
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);
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include "util/FFstrbuf.h"
#include "common/parsing.h"
enum
{
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,
};
// if (green <= yellow)
// [0, green]: print green
// (green, yellow]: print yellow
// (yellow, 100]: print red
//
// if (green > yellow)
// [green, 100]: print green
// [yellow, green): print yellow
// [0, yellow): print red
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config);
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses);
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);
+4 -12
View File
@@ -37,9 +37,9 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
else
{
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
ffParseFormatString(&key, &moduleArgs->key, 1, (FFformatarg[]){
FF_PARSE_FORMAT_STRING_CHECKED(&key, &moduleArgs->key, 1, ((FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
});
}));
ffStrbufWriteTo(&key, stdout);
}
@@ -60,7 +60,7 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
}
}
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments)
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (moduleArgs)
@@ -93,7 +93,7 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
putchar('\n');
}
void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
{
va_list arguments;
va_start(arguments, message);
@@ -101,14 +101,6 @@ void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFMod
va_end(arguments);
}
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...)
{
va_list arguments;
va_start(arguments, message);
printError(moduleName, moduleIndex, moduleArgs, FF_PRINT_TYPE_DEFAULT, message, arguments);
va_end(arguments);
}
void ffPrintColor(const FFstrbuf* colorValue)
{
//If the color is not set, this would reset in \033[m, which resets everything.
+10 -7
View File
@@ -12,14 +12,17 @@ typedef enum FFPrintType {
} FFPrintType;
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType);
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments);
static inline void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments)
{
ffPrintFormatString(moduleName, moduleIndex, moduleArgs, FF_PRINT_TYPE_DEFAULT, numArgs, arguments);
}
FF_C_PRINTF(5, 6) void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...);
FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
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)
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)
+16 -9
View File
@@ -13,13 +13,6 @@
enum { FF_PIPE_BUFSIZ = 8192 };
static inline void waitpid_wrapper(const pid_t* pid)
{
// remove zombie processes
if (*pid > 0)
waitpid(*pid, NULL, 0);
}
static inline int ffPipe2(int *fds, int flags)
{
#ifdef __APPLE__
@@ -41,7 +34,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if(ffPipe2(pipes, O_CLOEXEC) == -1)
return "pipe() failed";
__attribute__((__cleanup__(waitpid_wrapper))) pid_t childPid = fork();
pid_t childPid = fork();
if(childPid == -1)
{
close(pipes[0]);
@@ -74,11 +67,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if (poll(&pollfd, 1, timeout) == 0)
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) timeout";
}
else if (pollfd.revents & POLLERR)
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) error";
}
}
@@ -87,7 +82,19 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if (nRead > 0)
ffStrbufAppendNS(buffer, (uint32_t) nRead, str);
else if (nRead == 0)
return NULL;
{
int stat_loc = 0;
if (waitpid(childPid, &stat_loc, 0) == childPid)
{
if (!WIFEXITED(stat_loc))
return "child process exited abnormally";
if (WEXITSTATUS(stat_loc) == 127)
return "command was not found";
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
return NULL;
}
return "waitpid() failed";
}
else if (nRead < 0)
break;
};
+3 -4
View File
@@ -83,8 +83,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
char str[FF_PIPE_BUFSIZ];
DWORD nRead = 0;
FF_AUTO_CLOSE_FD HANDLE hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
OVERLAPPED overlapped = { .hEvent = hEvent };
OVERLAPPED overlapped = { };
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
do
{
@@ -93,11 +92,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
switch (GetLastError())
{
case ERROR_IO_PENDING:
if (!timeout || WaitForSingleObject(hEvent, (DWORD) timeout) != WAIT_OBJECT_0)
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
{
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "WaitForSingleObject(hEvent) failed or timeout";
return "WaitForSingleObject(hChildPipeRead) failed or timeout";
}
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
+2 -3
View File
@@ -411,9 +411,8 @@ bool ffSettingsGetFreeBSDKenv(const char* propName, FFstrbuf* result)
//https://wiki.ghostbsd.org/index.php/Kenv
ffStrbufEnsureFree(result, KENV_MVALLEN);
int len = kenv(KENV_GET, propName, result->chars + result->length, KENV_MVALLEN);
if (len <= 0) return false;
result->length += (uint32_t) len;
result->chars[result->length] = '\0';
if (len <= 1) return false; // number of bytes copied, including NUL terminator
result->length += (uint32_t) len - 1;
return true;
}
#endif
+171
View File
@@ -0,0 +1,171 @@
#include "fastfetch.h"
#include "common/temps.h"
#include "util/textModifier.h"
#include "util/stringUtils.h"
void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config)
{
if (celsius != celsius) // ignores NaN
return;
const FFOptionsDisplay* options = &instance.config.display;
const char* colorGreen = options->tempColorGreen.chars;
const char* colorYellow = options->tempColorYellow.chars;
const char* colorRed = options->tempColorRed.chars;
uint8_t green = config.green, yellow = config.yellow;
if (!options->pipe)
{
if(green <= yellow)
{
if (celsius > yellow)
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
else if (celsius > green)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
else
{
if (celsius < yellow)
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
else if (celsius < green)
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
else
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
}
}
switch (options->temperatureUnit)
{
case FF_TEMPERATURE_UNIT_CELSIUS:
ffStrbufAppendF(buffer, "%.*f°C", options->tempNdigits, celsius);
break;
case FF_TEMPERATURE_UNIT_FAHRENHEIT:
ffStrbufAppendF(buffer, "%.*f°F", options->tempNdigits, celsius * 1.8 + 32);
break;
case FF_TEMPERATURE_UNIT_KELVIN:
ffStrbufAppendF(buffer, "%.*f K", options->tempNdigits, celsius + 273.15);
break;
}
if (!options->pipe)
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* value, bool* useTemp, FFColorRangeConfig* config)
{
if (!ffStrStartsWithIgnCase(subkey, "temp"))
return false;
if (subkey[strlen("temp")] == '\0')
{
*useTemp = ffOptionParseBoolean(value);
return true;
}
if (subkey[strlen("temp")] != '-')
return false;
subkey += strlen("temp-");
if (ffStrEqualsIgnCase(subkey, "green"))
{
uint32_t num = ffOptionParseUInt32(key, value);
if (num > 100)
{
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
exit(480);
}
config->green = (uint8_t) num;
return true;
}
if (ffStrEqualsIgnCase(subkey, "yellow"))
{
uint32_t num = ffOptionParseUInt32(key, value);
if (num > 100)
{
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
exit(480);
}
config->yellow = (uint8_t) num;
return true;
}
return false;
}
bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config)
{
if (!ffStrEqualsIgnCase(key, "temp"))
return false;
if (yyjson_is_bool(value))
{
*useTemp = yyjson_get_bool(value);
return true;
}
if (yyjson_is_null(value))
{
*useTemp = false;
return true;
}
if (!yyjson_is_obj(value))
{
fprintf(stderr, "Error: usage: %s must be an object or a boolean\n", key);
exit(480);
}
*useTemp = true;
yyjson_val* greenVal = yyjson_obj_get(value, "green");
if (greenVal)
{
int num = yyjson_get_int(greenVal);
if (num < 0 || num > 100)
{
fputs("Error: usage: temp.green must be between 0 and 100\n", stderr);
exit(480);
}
config->green = (uint8_t) num;
}
yyjson_val* yellowVal = yyjson_obj_get(value, "yellow");
if (yellowVal)
{
int num = yyjson_get_int(yellowVal);
if (num < 0 || num > 100)
{
fputs("Error: usage: temp.yellow must be between 0 and 100\n", stderr);
exit(480);
}
config->yellow = (uint8_t) num;
}
return true;
}
void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF_MAYBE_UNUSED bool defaultTemp, FFColorRangeConfig defaultConfig, bool temp, FFColorRangeConfig config)
{
assert(defaultTemp == false); // assume defaultTemp is always false
if (!temp)
return;
if (config.green != defaultConfig.green || config.yellow != defaultConfig.yellow)
{
yyjson_mut_val* temp = yyjson_mut_obj_add_obj(doc, module, "temp");
if (config.green != defaultConfig.green)
yyjson_mut_obj_add_uint(doc, temp, "green", config.green);
if (config.yellow != defaultConfig.yellow)
yyjson_mut_obj_add_uint(doc, temp, "yellow", config.yellow);
}
else
{
yyjson_mut_obj_add_bool(doc, module, "temp", true);
}
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "common/parsing.h"
void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config);
bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* value, bool* useTemp, FFColorRangeConfig* config);
bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config);
void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF_MAYBE_UNUSED bool defaultTemp, FFColorRangeConfig defaultConfig, bool temp, FFColorRangeConfig config);
+1 -1
View File
@@ -42,6 +42,6 @@ static inline void ffTimeSleep(uint32_t msec)
#ifdef _WIN32
SleepEx(msec, TRUE);
#else
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
nanosleep(&(struct timespec){ msec / 1000, (long) (msec % 1000) * 1000000 }, NULL);
#endif
}
+217 -32
View File
@@ -122,7 +122,10 @@
{
"long": "ds-force-drm",
"desc": "Set if only DRM should be used to detect displays",
"remark": "Use this option if you encountered problems with other detection method. Linux only",
"remark": [
"Use this option if you encountered problems with other detection method.",
"Linux only"
],
"arg": {
"type": "enum",
"optional": true,
@@ -198,6 +201,7 @@
{
"long": "logo-color-[1-9]",
"desc": "Overwrite a color in the logo",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color"
},
@@ -432,6 +436,7 @@
{
"long": "color-keys",
"desc": "Set the color of the keys",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color"
}
@@ -439,6 +444,7 @@
{
"long": "color-title",
"desc": "Set the color of the title",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color"
}
@@ -534,7 +540,13 @@
{
"long": "percent-type",
"desc": "Set the percentage output type",
"remark": "1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number",
"remark": [
"1 for percentage number",
"2 for bar",
"3 for both",
"6 for bar only",
"9 for colored number"
],
"arg": {
"type": "num",
"default": 9
@@ -548,6 +560,33 @@
"default": 0
}
},
{
"long": "percent-color-green",
"desc": "Set color used in green state of percentage bars and numbers",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "green"
}
},
{
"long": "percent-color-yellow",
"desc": "Set color used in yellow state of percentage bars and numbers",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "light_yellow"
}
},
{
"long": "percent-color-red",
"desc": "Set color used in red state of percentage bars and numbers",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "light_red"
}
},
{
"long": "bar-char-elapsed",
"desc": "Set the character to use in elapsed part of percentage bars",
@@ -617,7 +656,7 @@
}
},
{
"long": "temperature-unit",
"long": "temp-unit",
"desc": "Set the unit of the temperature",
"arg": {
"type": "enum",
@@ -628,6 +667,41 @@
},
"default": "C"
}
},
{
"long": "temp-ndigits",
"desc": "Set the number of digits to keep after the decimal point when printing temperature",
"arg": {
"type": "num",
"default": 2
}
},
{
"long": "temp-color-green",
"desc": "Set color used in green state of temperature values",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "green"
}
},
{
"long": "temp-color-yellow",
"desc": "Set color used in yellow state of temperature values",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "light_yellow"
}
},
{
"long": "temp-color-red",
"desc": "Set color used in red state of temperature values",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "light_red"
}
}
],
"Library path": [
@@ -821,6 +895,7 @@
{
"long": "title-color-user",
"desc": "Set color of the user name (left part)",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "Use color of \"--color-title\""
@@ -829,6 +904,7 @@
{
"long": "title-color-at",
"desc": "Set color of the @ symbol (middle part)",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "Use color of \"--color-title\""
@@ -837,21 +913,12 @@
{
"long": "title-color-host",
"desc": "Set color of the host name (right part)",
"remark": "See `-h color` for the list of available colors",
"arg": {
"type": "color",
"default": "default"
}
},
{
"long": "chassis-use-wmi",
"desc": "Set if WMI query should be used on Windows",
"remark": "WMI query detects more information but is slower. Windows only",
"arg": {
"type": "bool",
"optional": true,
"default": false
}
},
{
"long": "separator-string",
"desc": "Set the string printed by the separator module",
@@ -940,6 +1007,14 @@
"default": false
}
},
{
"long": "diskio-detect-total",
"desc": "Detect total bytes instead of current rate",
"arg": {
"type": "bool",
"default": false
}
},
{
"long": "diskio-name-prefix",
"desc": "Show disks with given name prefix only",
@@ -973,13 +1048,16 @@
}
},
{
"long": "packages-winget",
"desc": "Set if winget package count should be detected",
"remark": "This option is extremely slow. You may need to increase value of '--processing-timeout' to make it actually work",
"long": "packages-disabled",
"desc": "A colon separated list of package managers to be disabled when detecting",
"remark": [
"Some detection methods can be very slow.",
"You may need to increase value of '--processing-timeout' to make it actually work.",
"Use `--packages-disabled none` to enable all."
],
"arg": {
"type": "bool",
"optional": true,
"default": false
"type": "string",
"default": "winget"
}
},
{
@@ -990,7 +1068,9 @@
"enum": {
"none": "Disable this compact mode",
"original": "Print original resolutions",
"scaled": "Print scaled resolutions"
"scaled": "Print scaled resolutions",
"original-with-refresh-rate": "Print original resolutions with refresh rate",
"scaled-with-refresh-rate": "Print scaled resolutions with refresh rate"
},
"default": "none"
}
@@ -1004,6 +1084,19 @@
"default": false
}
},
{
"long": "display-order",
"desc": "Set the order should be used when printing displays",
"arg": {
"type": "enum",
"enum": {
"none": "Use the detected order",
"asc": "Sort by display name ascendingly",
"desc": "Sort by display name descendingly"
},
"default": "none"
}
},
{
"long": "brightness-ddcci-sleep",
"desc": "Set the sleep times (in ms) when sending DDC/CI requests",
@@ -1026,19 +1119,13 @@
"default": "main"
}
},
{
"long": "battery-dir",
"desc": "The directory where the battery folders are",
"remark": "Linux only",
"arg": {
"type": "path",
"default": "/sys/class/power_supply/"
}
},
{
"long": "battery-use-setup-api",
"desc": "Set if \"SetupAPI\" should be used on Windows to detect battery info",
"remark": "SetupAPI supports multi batteries, but slower. Windows only",
"remark": [
"SetupAPI supports multi batteries, but slower.",
"Windows only"
],
"arg": {
"type": "bool",
"optional": true,
@@ -1074,7 +1161,10 @@
{
"long": "de-slow-version-detection",
"desc": "Set if DE version should be detected with slow operations",
"remark": "Usually is not necessary. Linux only",
"remark": [
"It's only used as a fallback method. Please file a bug report if you encounter any issues.",
"Linux only"
],
"arg": {
"type": "bool",
"optional": true,
@@ -1093,7 +1183,10 @@
{
"long": "gpu-driver-specific",
"desc": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)",
"remark": "Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported. Both require the latest proprietary driver to be installed",
"remark": [
"Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported.",
"Both require the latest proprietary driver to be installed."
],
"arg": {
"type": "bool",
"optional": true,
@@ -1211,6 +1304,14 @@
"default": true
}
},
{
"long": "netio-detect-total",
"desc": "Detect total bytes instead of current rate",
"arg": {
"type": "bool",
"default": false
}
},
{
"long": "publicip-timeout",
"desc": "Time in milliseconds to wait for the public ip server to respond",
@@ -1328,6 +1429,44 @@
"type": "num",
"default": 0
}
},
{
"long": "colors-block-width",
"desc": "Set the block width in spaces",
"arg": {
"type": "num",
"default": 3
}
},
{
"long": "colors-block-range-start",
"desc": "Set the start range of colors in the blocks to print",
"remark": [
"Display colors 0-15 in the blocks. (16 colors)",
"Display colors 0-7 in the blocks. (8 colors)",
"Only works for `--colors-symbol block`.",
"Must be in range 0-15",
"See also `--colors-range-end`"
],
"arg": {
"type": "num",
"default": 0
}
},
{
"long": "colors-block-range-end",
"desc": "Set the end range of colors in the blocks to print",
"remark": [
"Display colors 0-15 in the blocks. (16 colors)",
"Display colors 0-7 in the blocks. (8 colors)",
"Only works for `--colors-symbol block`.",
"Must be in range 0-15",
"See also `--colors-range-start`"
],
"arg": {
"type": "num",
"default": 15
}
}
],
"General module": [
@@ -1370,6 +1509,52 @@
"type": "num"
},
"pseudo": true
},
{
"long": "<module>-percent-green",
"desc": [
"Threshold of percentage colors",
"Value less then percent-green will be shown in green"
],
"arg": {
"type": "num"
},
"pseudo": true
},
{
"long": "<module>-percent-yellow",
"desc": [
"Threshold of percentage colors",
"Value greater than percent-green and less then yellow will be shown in yellow",
"Value greater than percent-yellow will be shown in red"
],
"arg": {
"type": "num"
},
"pseudo": true
},
{
"long": "<module>-temp-green",
"desc": [
"Threshold of temperature colors",
"Value less then temp-green will be shown in green"
],
"arg": {
"type": "num"
},
"pseudo": true
},
{
"long": "<module>-temp-yellow",
"desc": [
"Threshold of temperature colors",
"Value greater than temp-green and less then yellow will be shown in yellow",
"Value greater than temp-yellow will be shown in red"
],
"arg": {
"type": "num"
},
"pseudo": true
}
]
}
-8
View File
@@ -1,8 +0,0 @@
Usage: fastfetch -c <file>
Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.
If the file is relative it looks in the following order:
- relative to the current working directory
- relative to ~/.local/share/fastfetch/presets/
- relative to /usr/share/fastfetch/presets/
Fastfetch provides some default presets. List them with "fastfetch --list-presets".
+6 -6
View File
@@ -1,15 +1,15 @@
A format string is a string that contains placeholders for values.
These placeholders begin with a '{', containing the index of the value, and end with a '}'.
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce "Values: First (My second val)".
The format string can contain placeholders in any order and have multiple occurrences.
To include spaces when setting from the command line, surround the whole string with double quotes (").
If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second v
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again.
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces aro
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not counted as the beginning of a placeholder.
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces around it.
If the last placeholder isn't closed, it will be treated like it was at the end of the format string.
To only print something if a variable is set, use "{?<index>} ... {?}".
@@ -17,7 +17,7 @@ For example, to only print a second value if it is set, use "{?2} Second value:
If a "{?}" is found without an opener, it is printed as is.
To only print something if a variable is not set, do the same as with if, just replace every '?' with a '!'.
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}"
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}".
To stop formatting at any point in the format string, use "{-}".
@@ -25,7 +25,7 @@ To print something with color, start a placeholder with a '#' and then the linux
"\033[" at the start, and an 'm' at the end is automatically added, so don't do that.
A "{#}" is equivalent to a "{#0}" and resets everything to normal.
For example to print something pink and underline, use "{#4;35}...{#}".
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Sele
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
Which escape codes are supported and how they look is defined by your terminal.
If a format string evaluates to an empty value, the whole line in the output will be discarded.
+3 -1
View File
@@ -7,10 +7,12 @@
typedef struct FFBatteryResult
{
FFstrbuf manufacturer;
FFstrbuf manufactureDate;
FFstrbuf modelName;
FFstrbuf technology;
double capacity;
FFstrbuf status;
FFstrbuf serial;
double capacity;
double temperature;
uint32_t cycleCount;
} FFBatteryResult;
+1
View File
@@ -40,6 +40,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->manufactureDate);
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
ffStrbufAppendS(&battery->status, yyjson_get_str(yyjson_obj_get(root, "status")));
+51 -33
View File
@@ -4,86 +4,104 @@
#include "detection/temps/temps_apple.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPM.h>
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryBattery = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
continue;
int currentCapacity, maxCapacity;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
continue;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0)
continue;
}
bool boolValue;
const char* error;
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
return error;
if (maxCapacity <= 0)
return "Querying MaxCapacity failed";
if ((error = ffCfDictGetInt(properties, CFSTR("CurrentCapacity"), &currentCapacity)))
return error;
if(currentCapacity <= 0)
return "Querying CurrentCapacity failed";
ffStrbufInit(&battery->manufactureDate);
battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffCfDictGetString(properties, CFSTR("DeviceName"), &battery->modelName);
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial);
ffCfDictGetString(properties, CFSTR(kIOPMPSManufacturerKey), &battery->manufacturer);
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
{
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
if (!battery->manufacturer.length)
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
ffStrbufAppendS(&battery->technology, "Lithium");
if (!battery->modelName.length)
ffStrbufAppendS(&battery->modelName, "Built-in");
}
int32_t cycleCount = 0;
ffCfDictGetInt(properties, CFSTR("CycleCount"), &cycleCount);
ffCfDictGetInt(properties, CFSTR(kIOPMPSCycleCountKey), &cycleCount);
battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount;
if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue)
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "AC connected, ");
else
ffStrbufAppendS(&battery->status, "Discharging, ");
if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Charging, ");
if (!ffCfDictGetBool(properties, CFSTR("AtCriticalLevel"), &boolValue) && boolValue)
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
int sbdsManufactureDate = 0;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSManufactureDateKey), &sbdsManufactureDate) == NULL)
{
int day = sbdsManufactureDate & 0b11111;
int month = (sbdsManufactureDate >> 5) & 0b1111;
int year = (sbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
else
{
CFDictionaryRef batteryData;
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL)
{
char manufactureDate[sizeof(uint64_t)];
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL)
{
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
}
if (options->temp)
{
int64_t temp;
if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp))
if (!ffCfDictGetInt64(properties, CFSTR(kIOPMPSBatteryTemperatureKey), &temp))
battery->temperature = (double) temp / 10 - 273.15;
else
ffDetectSmcTemps(FF_TEMP_BATTERY, &battery->temperature);
}
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
return NULL;
}
+4 -2
View File
@@ -39,6 +39,8 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->capacity = battio.battinfo.cap;
if(battio.battinfo.state == ACPI_BATT_STAT_INVALID)
@@ -52,13 +54,13 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
ffStrbufAppendS(&battery->status, "Charging, ");
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
ffStrbufAppendS(&battery->status, "Ctritical, ");
ffStrbufAppendS(&battery->status, "Critical, ");
}
int acadStatus;
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus)
{
ffStrbufAppendS(&battery->status, "AC connected");
ffStrbufAppendS(&battery->status, "AC Connected");
}
else
{
+93 -44
View File
@@ -5,110 +5,159 @@
#include <dirent.h>
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
{
uint32_t dirLength = dir->length;
FF_STRBUF_AUTO_DESTROY testBatteryBuffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
//type must exist and be "Battery"
ffStrbufAppendS(dir, "/type");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufTrimRightSpace(&testBatteryBuffer);
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
ffStrbufTrimRightSpace(&tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0)
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery"))
return;
//scope may not exist or must not be "Device"
ffStrbufAppendS(dir, "/scope");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufTrimRightSpace(&testBatteryBuffer);
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
ffStrbufTrimRightSpace(&tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
return;
FFBatteryResult* result = ffListAdd(results);
//capacity must exist and be not empty
ffStrbufAppendS(dir, "/capacity");
bool available = ffReadFileBuffer(dir->chars, &testBatteryBuffer);
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(available)
result->capacity = ffStrbufToDouble(&testBatteryBuffer);
if(!available)
{
result->capacity = 0.0/0.0;
--results->length;
if (!available)
return;
}
FFBatteryResult* result = ffListAdd(results);
result->capacity = ffStrbufToDouble(&tmpBuffer);
//At this point, we have a battery. Try to get as much values as possible.
ffStrbufInit(&result->manufacturer);
ffStrbufAppendS(dir, "/manufacturer");
ffReadFileBuffer(dir->chars, &result->manufacturer);
ffStrbufTrimRightSpace(&result->manufacturer);
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
ffStrbufTrimRightSpace(&result->manufacturer);
else if (ffStrEquals(id, "macsmc-battery")) // asahi
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->modelName);
ffStrbufAppendS(dir, "/model_name");
ffReadFileBuffer(dir->chars, &result->modelName);
ffStrbufTrimRightSpace(&result->modelName);
if (ffReadFileBuffer(dir->chars, &result->modelName))
ffStrbufTrimRightSpace(&result->modelName);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->technology);
ffStrbufAppendS(dir, "/technology");
ffReadFileBuffer(dir->chars, &result->technology);
ffStrbufTrimRightSpace(&result->technology);
if (ffReadFileBuffer(dir->chars, &result->technology))
ffStrbufTrimRightSpace(&result->technology);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->status);
ffStrbufAppendS(dir, "/status");
ffReadFileBuffer(dir->chars, &result->status);
ffStrbufTrimRightSpace(&result->status);
if (ffReadFileBuffer(dir->chars, &result->status))
ffStrbufTrimRightSpace(&result->status);
ffStrbufSubstrBefore(dir, dirLength);
// Unknown, Charging, Discharging, Not charging, Full
if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
ffStrbufSetStatic(&result->status, "AC Connected");
else if (ffStrbufEqualS(&result->status, "Unknown"))
ffStrbufClear(&result->status);
ffStrbufAppendS(dir, "/capacity_level");
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
{
ffStrbufTrimRightSpace(&result->manufacturer);
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
{
if (result->status.length)
ffStrbufAppendS(&result->status, ", Critical");
else
ffStrbufSetStatic(&result->status, "Critical");
}
}
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/serial_number");
if (ffReadFileBuffer(dir->chars, &result->serial))
ffStrbufTrimRightSpace(&result->serial);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufAppendS(dir, "/cycle_count");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufTrimRightSpace(&testBatteryBuffer);
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (dir->length)
if (available)
{
int64_t cycleCount = 0;
cycleCount = (int64_t) strtoll(testBatteryBuffer.chars, NULL, 10);
int64_t cycleCount = ffStrbufToSInt(&tmpBuffer, 0);
result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount;
}
ffStrbufInit(&result->manufactureDate);
ffStrbufAppendS(dir, "/manufacture_year");
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (available)
{
int year = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (year > 0)
{
ffStrbufAppendS(dir, "/manufacture_month");
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (available)
{
int month = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (month > 0)
{
ffStrbufAppendS(dir, "/manufacture_day");
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (available)
{
int day = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (day > 0)
{
ffStrbufSetF(&result->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
}
}
}
}
result->temperature = FF_BATTERY_TEMP_UNSET;
if (options->temp)
{
const FFlist* tempsResult = ffDetectTemps();
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
{
if (ffStrbufEqualS(&value->deviceName, id))
{
result->temperature = value->value;
break;
}
}
ffStrbufAppendS(dir, "/temp");
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
result->temperature = ffStrbufToDouble(&tmpBuffer) / 10;
ffStrbufSubstrBefore(dir, dirLength);
}
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
ffStrbufAppend(&baseDir, &options->dir);
ffStrbufEnsureEndsWithC(&baseDir, '/');
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
uint32_t baseDirLength = baseDir.length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
return "opendir(batteryDir) == NULL";
return "opendir(\"/sys/class/power_supply/\") == NULL";
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
@@ -122,7 +171,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
}
if(results->length == 0)
return "batteryDir doesn't contain any battery folder";
return "\"/sys/class/power_supply/\" doesn't contain any battery folder";
return NULL;
}
+108 -9
View File
@@ -1,6 +1,7 @@
#include "battery.h"
#include "util/windows/unicode.h"
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -75,19 +76,19 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
ffStrbufInitStatic(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
ffStrbufInitS(&battery->technology, "Lithium Ion");
ffStrbufInitStatic(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
ffStrbufInitStatic(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
ffStrbufInitStatic(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Zinc");
ffStrbufInitStatic(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
ffStrbufInitStatic(&battery->technology, "Rechargeable Alkaline-Manganese");
else
ffStrbufInitS(&battery->technology, "Unknown");
ffStrbufInitStatic(&battery->technology, "Unknown");
{
ffStrbufInit(&battery->modelName);
@@ -105,6 +106,22 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
ffStrbufSetWS(&battery->manufacturer, name);
}
{
ffStrbufInit(&battery->manufactureDate);
bqi.InformationLevel = BatteryManufactureDate;
BATTERY_MANUFACTURE_DATE date;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year + 1900, date.Month, date.Day);
}
{
ffStrbufInit(&battery->serial);
bqi.InformationLevel = BatterySerialNumber;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->serial, name);
}
battery->cycleCount = bi.CycleCount;
battery->temperature = 0.0/0.0;
@@ -113,7 +130,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
battery->temperature = temp;
battery->temperature = temp / 10.0 - 273.15;
}
{
@@ -140,6 +157,83 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
return NULL;
}
typedef struct FFSmbiosPortableBattery
{
FFSmbiosHeader Header;
// 2.1+
uint8_t Location; // string
uint8_t Manufacturer; // string
uint8_t ManufactureDate; // string
uint8_t SerialNumber; // string
uint8_t DeviceName; // string
uint8_t DeviceChemistry; // enum
uint16_t DesignCapacity; // varies
uint16_t DesignVoltage; // varies
uint8_t SbdsVersionNumber; // string
uint8_t MaximumErrorInBatteryData; // varies
// 2.2+
uint16_t SbdsSerialNumber; // varies
uint16_t SbdsManufactureDate; // varies
uint8_t SbdsDeviceChemistry; // string
uint8_t DesignCapacityMultiplier; // varies
uint16_t OEMSpecific; // varies
} FFSmbiosPortableBattery;
const char* detectBySmbios(FFBatteryResult* battery)
{
const FFSmbiosPortableBattery* data = (const FFSmbiosPortableBattery*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PORTABLE_BATTERY];
if (!data)
return "Portable battery section is not found in SMBIOS data";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&battery->modelName, ffSmbiosLocateString(strings, data->DeviceName));
ffCleanUpSmbiosValue(&battery->modelName);
ffStrbufSetStatic(&battery->manufacturer, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&battery->manufacturer);
if (data->ManufactureDate)
{
ffStrbufSetStatic(&battery->manufactureDate, ffSmbiosLocateString(strings, data->ManufactureDate));
ffCleanUpSmbiosValue(&battery->manufactureDate);
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsManufactureDate))
{
int day = data->SbdsManufactureDate & 0b11111;
int month = (data->SbdsManufactureDate >> 5) & 0b1111;
int year = (data->SbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
switch (data->DeviceChemistry)
{
case 0x01: ffStrbufSetStatic(&battery->technology, "Other"); break;
case 0x02: ffStrbufSetStatic(&battery->technology, "Unknown"); break;
case 0x03: ffStrbufSetStatic(&battery->technology, "Lead Acid"); break;
case 0x04: ffStrbufSetStatic(&battery->technology, "Nickel Cadmium"); break;
case 0x05: ffStrbufSetStatic(&battery->technology, "Nickel metal hydride"); break;
case 0x06: ffStrbufSetStatic(&battery->technology, "Lithium-ion"); break;
case 0x07: ffStrbufSetStatic(&battery->technology, "Zinc air"); break;
case 0x08: ffStrbufSetStatic(&battery->technology, "Lithium Polymer"); break;
}
if (data->SerialNumber)
{
ffStrbufSetStatic(&battery->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&battery->serial);
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsSerialNumber))
{
ffStrbufSetF(&battery->serial, "%4X", data->SbdsSerialNumber);
}
return NULL;
}
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
SYSTEM_BATTERY_STATE info;
@@ -148,8 +242,10 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->manufactureDate);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->serial);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
@@ -162,6 +258,9 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
}
else if(info.Discharging)
ffStrbufAppendS(&battery->status, "Discharging");
detectBySmbios(battery);
return NULL;
}
return "NtPowerInformation(SystemBatteryState) failed";
@@ -169,7 +268,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
return true
return options->useSetupApi
? detectWithSetupApi(options, results)
: detectWithNtApi(options, results);
}
+14
View File
@@ -2,6 +2,7 @@
#include "common/settings.h"
#include "common/sysctl.h"
#include "common/io/io.h"
#include "util/smbiosHelper.h"
const char* ffDetectBios(FFBiosResult* result)
@@ -15,5 +16,18 @@ const char* ffDetectBios(FFBiosResult* result)
ffSettingsGetFreeBSDKenv("smbios.bios.version", &result->version);
ffCleanUpSmbiosValue(&result->version);
ffSysctlGetString("machdep.bootmethod", &result->type);
if (result->type.length == 0)
{
if (ffSettingsGetFreeBSDKenv("loader.efi", &result->type))
ffStrbufSetStatic(&result->type, ffStrbufEqualS(&result->type, "1") ? "UEFI" : "BIOS");
else
{
ffStrbufSetStatic(&result->type,
ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) ||
ffPathExists("/boot/efi/efi" /*efi partition*/, FF_PATHTYPE_DIRECTORY)
? "UEFI" : "BIOS");
}
}
return NULL;
}
+32 -14
View File
@@ -1,5 +1,4 @@
#include "bios.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
#include <ntstatus.h>
@@ -26,27 +25,46 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
};
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
typedef struct FFSmbiosBios
{
FFSmbiosHeader Header;
uint8_t Vendor; // string
uint8_t BiosVersion; // string
uint16_t BiosStartingAddressSegment; // varies
uint8_t BiosReleaseDate; // string
uint8_t BiosRomSize; // string
uint32_t BiosCharacteristics; // bit field
// 2.4+
uint8_t BiosCharacteristicsExtensionBytes[2]; // bit field
uint8_t SystemBiosMajorRelease; // varies
uint8_t SystemBiosMinorRelease; // varies
uint8_t EmbeddedControllerFirmwareMajorRelease; // varies
uint8_t EmbeddedControllerFirmwareMinorRelease; // varies
// 3.1+
uint16_t ExtendedBiosRomSize; // bit field
} FFSmbiosBios;
const char* ffDetectBios(FFBiosResult* bios)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
const FFSmbiosBios* data = (const FFSmbiosBios*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_BIOS];
if (!data)
return "BIOS section is not found in SMBIOS data";
if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->version, NULL))
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSVersion\" doesn't exist";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&bios->version, ffSmbiosLocateString(strings, data->BiosVersion));
ffCleanUpSmbiosValue(&bios->version);
ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->vendor, NULL);
ffStrbufSetStatic(&bios->vendor, ffSmbiosLocateString(strings, data->Vendor));
ffCleanUpSmbiosValue(&bios->vendor);
ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->date, NULL);
ffStrbufSetStatic(&bios->date, ffSmbiosLocateString(strings, data->BiosReleaseDate));
ffCleanUpSmbiosValue(&bios->date);
uint32_t major, minor;
if(
ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) &&
ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL)
)
ffStrbufAppendF(&bios->release, "%u.%u", (unsigned)major, (unsigned)minor);
if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease))
ffStrbufSetF(&bios->release, "%u.%u", data->SystemBiosMajorRelease, data->SystemBiosMinorRelease);
// Same as GetFirmwareType, but support (?) Windows 7
// https://ntdoc.m417z.com/system_information_class
+1
View File
@@ -7,6 +7,7 @@ typedef struct FFBoardResult
FFstrbuf name;
FFstrbuf vendor;
FFstrbuf version;
FFstrbuf serial;
} FFBoardResult;
const char* ffDetectBoard(FFBoardResult* board);
+12 -4
View File
@@ -1,13 +1,21 @@
#include "board.h"
#include "common/sysctl.h"
#include "util/apple/cf_helpers.h"
const char* ffDetectBoard(FFBoardResult* result)
{
const char* error = ffSysctlGetString("hw.model", &result->name);
if (error)
return error;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice"));
if (!service)
return "No IOPlatformExpertDevice found";
io_name_t name;
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
ffStrbufSetS(&result->name, name);
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
if (manufacturer)
ffCfStrGetString(manufacturer, &result->vendor);
ffStrbufSetStatic(&result->vendor, "Apple");
return NULL;
}
+2
View File
@@ -6,6 +6,8 @@ const char* ffDetectBoard(FFBoardResult* result)
{
ffSettingsGetFreeBSDKenv("smbios.planar.product", &result->name);
ffCleanUpSmbiosValue(&result->name);
ffSettingsGetFreeBSDKenv("smbios.planar.serial", &result->serial);
ffCleanUpSmbiosValue(&result->serial);
ffSettingsGetFreeBSDKenv("smbios.planar.maker", &result->vendor);
ffCleanUpSmbiosValue(&result->vendor);
ffSettingsGetFreeBSDKenv("smbios.planar.version", &result->version);
+1
View File
@@ -7,6 +7,7 @@
const char* ffDetectBoard(FFBoardResult* board)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_serial", "/sys/class/dmi/id/board_serial", &board->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
return NULL;
+26 -9
View File
@@ -1,21 +1,38 @@
#include "board.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
typedef struct FFSmbiosBaseboard
{
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t Product; // string
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTag; // string
uint8_t FeatureFlags; // bit field
uint8_t LocationInChassis; // string
uint16_t ChassisHandle; // varies
uint8_t BoardType; // enum
uint8_t NumberOfContainedObjectHandle; // varies
uint16_t ContainedObjectHandle[]; // varies
} FFSmbiosBaseboard;
const char* ffDetectBoard(FFBoardResult* board)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
const FFSmbiosBaseboard* data = (const FFSmbiosBaseboard*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_BASEBOARD_INFO];
if (!data)
return "Baseboard information section is not found in SMBIOS data";
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\") failed";
if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->name, NULL))
return "ffRegReadStrbuf(hKey, L\"BaseBoardProduct\") failed";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&board->name, ffSmbiosLocateString(strings, data->Product));
ffCleanUpSmbiosValue(&board->name);
ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->vendor, NULL);
ffStrbufSetStatic(&board->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&board->serial);
ffStrbufSetStatic(&board->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&board->vendor);
ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->version, NULL);
ffStrbufSetStatic(&board->version, ffSmbiosLocateString(strings, data->Version));
ffCleanUpSmbiosValue(&board->version);
return NULL;
+22 -22
View File
@@ -57,35 +57,35 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
return "IOAVService is not available";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = NULL;
{
IOObjectRelease(registryEntry);
continue;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryAv = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFBooleanRef IOAVServiceUserInterfaceSupported = IORegistryEntryCreateCFProperty(entryAv, CFSTR("IOAVServiceUserInterfaceSupported"), kCFAllocatorDefault, kNilOptions);
if (IOAVServiceUserInterfaceSupported && !CFBooleanGetValue(IOAVServiceUserInterfaceSupported))
{
// IOAVServiceCreateWithService won't work
continue;
}
FF_CFTYPE_AUTO_RELEASE CFStringRef location = IORegistryEntryCreateCFProperty(entryAv, CFSTR("Location"), kCFAllocatorDefault, kNilOptions);
if (location && CFStringCompare(location, CFSTR("Embedded"), 0) == 0)
{
// Builtin display should be handled by DisplayServices
continue;
}
service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
if (!service) continue;
}
ffStrbufClear(&location);
if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded"))
{
// Builtin display should be handled by DisplayServices
IOObjectRelease(registryEntry);
continue;
}
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
IOObjectRelease(registryEntry);
if (!service) continue;
{
uint8_t i2cIn[4] = { 0x82, 0x01, 0x10 /* luminance */ };
i2cIn[3] = 0x6e ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2];
@@ -36,6 +36,8 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
struct backlight_info info;
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
ffStrbufAppendS(&brightness->name, info.name);
else
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
}
return NULL;
}
+1 -1
View File
@@ -114,7 +114,7 @@ static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
{
FF_SUPPRESS_IO();
// Ref: https://github.com/rockowitz/ddcutil/issues/344
if (ffddca_init("--disable-watch-displays", -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0)
if (ffddca_init(NULL, -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0)
return "ddca_init() failed";
}
else
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "fastfetch.h"
typedef struct FFCameraResult
{
FFstrbuf name;
FFstrbuf vendor;
FFstrbuf id;
FFstrbuf colorspace;
uint32_t width;
uint32_t height;
} FFCameraResult;
const char* ffDetectCamera(FFlist* result /* list of FFCameraResult */);
+61
View File
@@ -0,0 +1,61 @@
#include "camera.h"
#include "common/processing.h"
#include "common/properties.h"
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
#define FF_TERMUX_API_PARAM "CameraInfo"
static inline void wrapYyjsonFree(yyjson_doc** doc)
{
assert(doc);
if (*doc)
yyjson_doc_free(*doc);
}
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FF_TERMUX_API_PATH,
FF_TERMUX_API_PARAM,
NULL
}))
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
if (!doc)
return "Failed to parse camera info";
yyjson_val* root = yyjson_doc_get_root(doc);
if (!yyjson_is_arr(root))
return "Camera info result is not a JSON array";
yyjson_val* device;
size_t idx, max;
yyjson_arr_foreach(root, idx, max, device)
{
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
{
const char* facing = yyjson_get_str(yyjson_obj_get(device, "facing"));
if (facing)
ffStrbufInitF(&camera->name, "builtin-%s", facing);
else
ffStrbufInitStatic(&camera->name, "Unknown");
}
ffStrbufInit(&camera->vendor);
ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id")));
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
if (yyjson_is_obj(sizes))
{
camera->width = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "width"));
camera->height = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "height"));
}
else
camera->width = camera->height = 0;
ffStrbufInit(&camera->colorspace);
}
return NULL;
}
+31
View File
@@ -0,0 +1,31 @@
#include "camera.h"
#import <AVFoundation/AVCaptureDevice.h>
const char* ffDetectCamera(FFlist* result)
{
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
if (!session)
return "Failed to create AVCaptureDeviceDiscoverySession";
for (AVCaptureDevice* device in session.devices)
{
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitS(&camera->name, device.localizedName.UTF8String);
ffStrbufInitS(&camera->vendor, device.manufacturer.UTF8String);
ffStrbufInitS(&camera->id, device.uniqueID.UTF8String);
switch (device.activeColorSpace)
{
case AVCaptureColorSpace_sRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
case AVCaptureColorSpace_P3_D65: ffStrbufInitStatic(&camera->colorspace, "P3-D65"); break;
case 2 /*AVCaptureColorSpace_HLG_BT2020*/: ffStrbufInitStatic(&camera->colorspace, "BT2020-HLG"); break;
case 3 /*AVCaptureColorSpace_AppleLog*/: ffStrbufInitStatic(&camera->colorspace, "AppleLog"); break;
}
CMVideoDimensions size = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription);
camera->width = size.width < 0 ? 0 : (uint32_t) size.width;
camera->height = size.height < 0 ? 0 : (uint32_t) size.height;
}
return NULL;
}
+61
View File
@@ -0,0 +1,61 @@
#include "camera.h"
#include "common/io/io.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#if __has_include(<linux/videodev2.h>)
#include <linux/videodev2.h>
#endif
const char* ffDetectCamera(FFlist* result)
{
#if __has_include(<linux/videodev2.h>)
char path[] = "/dev/videoN";
for (uint32_t i = 0; i <= 9; ++i)
{
path[sizeof(path) - 2] = (char) (i + '0');
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
if (fd < 0)
break;
struct v4l2_capability cap = {};
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
continue;
struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
continue;
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitS(&camera->name, (const char*) cap.card);
ffStrbufInit(&camera->vendor);
ffStrbufInitS(&camera->id, (const char*) cap.bus_info);
switch (fmt.fmt.pix.colorspace)
{
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.808"); break;
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
case V4L2_COLORSPACE_OPRGB: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
case V4L2_COLORSPACE_BT2020: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
case V4L2_COLORSPACE_RAW: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
case V4L2_COLORSPACE_DCI_P3: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
default: ffStrbufInit(&camera->colorspace); break;
}
camera->width = fmt.fmt.pix.width;
camera->height = fmt.fmt.pix.height;
}
return NULL;
#else
FF_UNUSED(result);
return "Fastfetch was compiled without <linux/videodev2.h>";
#endif
}
+129
View File
@@ -0,0 +1,129 @@
extern "C" {
#include "camera.h"
#include "common/library.h"
}
#include "util/windows/com.hpp"
#include "util/windows/unicode.hpp"
#include <initguid.h>
#include <mfapi.h>
#include <mfidl.h>
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* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
FF_LIBRARY_LOAD(mfplat, NULL, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
FF_LIBRARY_LOAD(mf, NULL, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
const char* error = ffInitCom();
if (error)
return error;
IMFAttributes* FF_AUTO_RELEASE_COM_OBJECT attrs = nullptr;
if (FAILED(ffMFCreateAttributes(&attrs, 1)))
return "MFCreateAttributes() failed";
if (FAILED(attrs->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
)))
return "SetGUID(MF_*) failed";
IMFActivate** devices = NULL;
uint32_t count;
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count)))
return "MFEnumDeviceSources() failed";
for (uint32_t i = 0; i < count; i++)
{
IMFActivate* device = devices[i];
wchar_t buffer[256];
uint32_t length = 0;
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0)
continue;
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitNWS(&camera->name, length, buffer);
ffStrbufInit(&camera->colorspace);
ffStrbufInit(&camera->vendor);
ffStrbufInit(&camera->id);
camera->width = 0;
camera->height = 0;
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0)
ffStrbufSetNWS(&camera->id, length, buffer);
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source))))
continue;
on_scope_exit destroySource([&] { source->Shutdown(); });
IMFPresentationDescriptor* FF_AUTO_RELEASE_COM_OBJECT pd = nullptr;
if (FAILED(source->CreatePresentationDescriptor(&pd)))
continue;
IMFStreamDescriptor* FF_AUTO_RELEASE_COM_OBJECT sd = NULL;
BOOL selected;
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd)))
continue;
IMFMediaTypeHandler* FF_AUTO_RELEASE_COM_OBJECT handler = NULL;
if (FAILED(sd->GetMediaTypeHandler(&handler)))
continue;
DWORD mediaTypeCount;
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount)))
continue;
// Assume first type is the maximum resolution
IMFMediaType* FF_AUTO_RELEASE_COM_OBJECT type = NULL;
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
{
GUID majorType;
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
continue;
MFVideoPrimaries primaries;
static_assert(sizeof(primaries) == sizeof(uint32_t), "");
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries)))
{
switch (primaries)
{
case MFVideoPrimaries_BT709: ffStrbufSetStatic(&camera->colorspace, "sRGB"); break;
case MFVideoPrimaries_BT470_2_SysM:
case MFVideoPrimaries_BT470_2_SysBG: ffStrbufSetStatic(&camera->colorspace, "NTSC"); break;
case MFVideoPrimaries_SMPTE170M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M"); break;
case MFVideoPrimaries_SMPTE240M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M"); break;
case MFVideoPrimaries_EBU3213: ffStrbufSetStatic(&camera->colorspace, "EBU 3213"); break;
case MFVideoPrimaries_SMPTE_C: ffStrbufSetStatic(&camera->colorspace, "SMPTE C"); break;
case MFVideoPrimaries_BT2020: ffStrbufSetStatic(&camera->colorspace, "BT.2020"); break;
case MFVideoPrimaries_XYZ: ffStrbufSetStatic(&camera->colorspace, "XYZ"); break;
case MFVideoPrimaries_DCI_P3: ffStrbufSetStatic(&camera->colorspace, "DCI-P3"); break;
case MFVideoPrimaries_ACES: ffStrbufSetStatic(&camera->colorspace, "ACES"); break;
default: break;
}
}
MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &camera->width, &camera->height);
break;
}
}
CoTaskMemFree(devices);
return nullptr;
}
+2 -2
View File
@@ -2,9 +2,9 @@
const char* ffChassisTypeToString(uint32_t type)
{
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.0.pdf
// 7.4.1 System Enclosure or Chassis Types
switch (type)
switch (type & 0b01111111)
{
case 0x01: return "Other";
case 0x02: return "Unknown";
+2 -1
View File
@@ -5,9 +5,10 @@
typedef struct FFChassisResult
{
FFstrbuf type;
FFstrbuf serial;
FFstrbuf vendor;
FFstrbuf version;
} FFChassisResult;
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options);
const char* ffDetectChassis(FFChassisResult* result);
const char* ffChassisTypeToString(uint32_t type);
+3 -1
View File
@@ -2,13 +2,15 @@
#include "common/settings.h"
#include "util/smbiosHelper.h"
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
const char* ffDetectChassis(FFChassisResult* result)
{
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
ffCleanUpSmbiosValue(&result->type);
ffSettingsGetFreeBSDKenv("smbios.chassis.maker", &result->vendor);
ffCleanUpSmbiosValue(&result->vendor);
ffSettingsGetFreeBSDKenv("smbios.chassis.serial", &result->serial);
ffCleanUpSmbiosValue(&result->serial);
ffSettingsGetFreeBSDKenv("smbios.chassis.version", &result->version);
ffCleanUpSmbiosValue(&result->version);
return NULL;
+2 -1
View File
@@ -4,9 +4,10 @@
#include <stdlib.h>
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
const char* ffDetectChassis(FFChassisResult* result)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version);
+1 -1
View File
@@ -1,6 +1,6 @@
#include "chassis.h"
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
{
return "Not supported on this platform";
}
+47
View File
@@ -0,0 +1,47 @@
#include "chassis.h"
#include "util/smbiosHelper.h"
// 7.4
typedef struct FFSmbiosSystemEnclosure
{
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t Type; // varies
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTagNumber; // string
// 2.1+
uint8_t BootupState; // enum
uint8_t PowerSupplyState; // enum
uint8_t ThermalState; // enum
uint8_t SecurityStatus; // enum
// 2.3+
uint32_t OEMDefined; // varies
uint8_t Height; // varies
uint8_t NumberOfPowerCords; // varies
uint8_t ContainedElementCount; // varies
uint8_t ContainedRecordLength; // varies
uint8_t ContainedElements[]; // varies
} FFSmbiosSystemEnclosure;
const char* ffDetectChassis(FFChassisResult* result)
{
const FFSmbiosSystemEnclosure* data = (const FFSmbiosSystemEnclosure*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE];
if (!data)
return "System enclosure is not found in SMBIOS data";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&result->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&result->vendor);
ffStrbufSetStatic(&result->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&result->serial);
ffStrbufSetStatic(&result->version, ffSmbiosLocateString(strings, data->Version));
ffCleanUpSmbiosValue(&result->version);
ffStrbufSetStatic(&result->type, ffChassisTypeToString(data->Type));
return NULL;
}
-73
View File
@@ -1,73 +0,0 @@
extern "C" {
#include "chassis.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
}
#include "util/windows/unicode.hpp"
#include "util/windows/wmi.hpp"
static const char* detectWithRegistry(FFChassisResult* result)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL)) // SMBIOS
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
uint32_t type = 0;
if(!ffRegReadUint(hKey, L"EnclosureType", &type, NULL))
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\EnclosureType\" doesn't exist";
const char* typeStr = ffChassisTypeToString(type);
if(!typeStr)
return "Unknown chassis type";
ffStrbufAppendS(&result->type, typeStr);
return NULL;
}
FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
{
FFWmiQuery query(L"SELECT Version, ChassisTypes, Manufacturer FROM Win32_SystemEnclosure");
if (!query)
return "Query WMI service failed";
if (FFWmiRecord record = query.next())
{
if (auto vtProp = record.get(L"ChassisTypes"))
{
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
if(len == 0)
return "ChassisTypes contain no data";
for (uint32_t i = 0; i < len; ++i)
{
if (i > 0)
ffStrbufAppendS(&result->type, ", ");
ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) arr[i]));
}
}
else
return "Get ChassisTypes failed";
if (auto vtProp = record.get(L"Version"))
{
ffStrbufSetWSV(&result->version, vtProp.get<std::wstring_view>());
ffCleanUpSmbiosValue(&result->version);
}
if (auto vtProp = record.get(L"Manufacturer"))
{
ffStrbufSetWSV(&result->vendor, vtProp.get<std::wstring_view>());
ffCleanUpSmbiosValue(&result->vendor);
}
return NULL;
}
return "No WMI result returned";
}
extern "C"
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
{
if (options->useWmi)
return detectWithWmi(result);
return detectWithRegistry(result);
}
+23 -33
View File
@@ -1,6 +1,7 @@
#include "cpu.h"
#include "common/sysctl.h"
#include "detection/temps/temps_apple.h"
#include "util/stringUtils.h"
static double detectCpuTemp(const FFstrbuf* cpuName)
{
@@ -35,44 +36,33 @@ static const char* detectFrequency(FFCPUResult* cpu)
{
// https://github.com/giampaolo/psutil/pull/2222/files
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
if (!entryDevice)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if (IORegistryEntryCreateCFProperties(entryDevice, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
return "IORegistryEntryCreateCFProperties() failed";
uint32_t pMin, eMin, aMax, pCoreLength;
if (ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength) != NULL) // pCore
return "\"voltage-states5-sram\" in \"pmgr\" is not found";
if (ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL) != NULL) // eCore
return "\"voltage-states1-sram\" in \"pmgr\" is not found";
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
io_name_t name;
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
continue;
if (strcmp(name, "pmgr") != 0)
continue;
uint32_t pMin, eMin, aMax, pCoreLength;
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
CFRelease(properties);
IOObjectRelease(registryEntry);
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
IOObjectRelease(iterator);
return NULL;
}
#else
+131 -27
View File
@@ -4,6 +4,7 @@
#include "common/properties.h"
#include "detection/temps/temps_linux.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include <sys/sysinfo.h>
#include <stdlib.h>
@@ -34,6 +35,10 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
#ifdef __aarch64__
FF_STRBUF_AUTO_DESTROY implementer = ffStrbufCreate();
#endif
while(getline(&line, &len, cpuinfo) != -1)
{
//Stop after the first CPU
@@ -47,39 +52,93 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
ffParsePropLine(line, "isa :", cpuIsa) ||
ffParsePropLine(line, "uarch :", cpuUarch) ||
#ifdef __aarch64__
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", &implementer)) ||
#endif
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
);
}
#ifdef __aarch64__
// https://github.com/util-linux/util-linux/blob/2cd89de14549d2b2c079a4f8b73f75500d229fee/sys-utils/lscpu-arm.c#L286
if (cpu->vendor.length == 0 && implementer.length > 2 /* 0xX */)
{
uint32_t implId = (uint32_t) strtoul(implementer.chars, NULL, 16);
switch (implId)
{
case 0x41: ffStrbufSetStatic(&cpu->vendor, "ARM"); break;
case 0x42: ffStrbufSetStatic(&cpu->vendor, "Broadcom"); break;
case 0x48: ffStrbufSetStatic(&cpu->vendor, "HiSilicon"); break;
case 0x4e: ffStrbufSetStatic(&cpu->vendor, "Nvidia"); break;
case 0x51: ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); break;
case 0x53: ffStrbufSetStatic(&cpu->vendor, "Samsung"); break;
case 0x61: ffStrbufSetStatic(&cpu->vendor, "Apple"); break;
case 0x69: ffStrbufSetStatic(&cpu->vendor, "Intel"); break;
}
}
#endif
return NULL;
}
static double getGHz(const char* file)
static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer)
{
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
if(ffAppendFileBuffer(file, &content))
{
double herz = ffStrbufToDouble(&content);
uint32_t baseLen = basePath->length;
ffStrbufAppendS(basePath, cpuinfoFileName);
bool ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return ffStrbufToDouble(buffer) / 1e6;
//ffStrbufToDouble failed
if(herz != herz)
return 0;
ffStrbufAppendS(basePath, scalingFileName);
ok = ffReadFileBuffer(basePath->chars, buffer);
ffStrbufSubstrBefore(basePath, baseLen);
if (ok)
return ffStrbufToDouble(buffer) / 1e6;
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
}
return 0;
return 0.0/0.0;
}
static double getFrequency(const char* info, const char* scaling)
static bool detectFrequency(FFCPUResult* cpu)
{
double frequency = getGHz(info);
if(frequency > 0.0)
return frequency;
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/cpufreq/");
FF_AUTO_CLOSE_DIR DIR* dir = opendir(path.chars);
if (!dir) return false;
return getGHz(scaling);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
uint32_t baseLen = path.length;
bool flag = false;
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if (ffStrStartsWith(entry->d_name, "policy") && isdigit(entry->d_name[strlen("policy")]))
{
ffStrbufAppendS(&path, entry->d_name);
double fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
if (fmin != fmin) continue;
double fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
if (fmax != fmax) continue;
if (flag)
{
cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin;
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
}
else
{
cpu->frequencyMin = fmin;
cpu->frequencyMax = fmax;
flag = true;
}
ffStrbufSubstrBefore(&path, baseLen);
}
}
return flag;
}
static double detectCPUTemp(void)
@@ -121,6 +180,44 @@ static void parseIsa(FFstrbuf* cpuIsa)
}
}
void detectAsahi(FFCPUResult* cpu)
{
// In Asahi Linux, reading /proc/device-tree/compatible gives
// information on the device model. It consists of 3 NUL terminated
// strings, the second of which gives the actual SoC model. But it
// is not the marketing name, i.e. for M2 there is "apple,t8112" in
// the compatible string.
if (cpu->name.length == 0 && ffStrbufEqualS(&cpu->vendor, "Apple"))
{
char content[32];
ssize_t length = ffReadFileData("/proc/device-tree/compatible", sizeof(content), content);
if (length <= 0) return;
// get the second NUL terminated string
char* modelName = memchr(content, '\0', (size_t) length) + 1;
if (modelName - content < length && ffStrStartsWith(modelName, "apple,t"))
{
// https://github.com/AsahiLinux/docs/wiki/Codenames
switch (strtoul(modelName + strlen("apple,t"), NULL, 10))
{
case 8103: ffStrbufSetStatic(&cpu->name, "Apple M1"); break;
case 6000: ffStrbufSetStatic(&cpu->name, "Apple M1 Pro"); break;
case 6001: ffStrbufSetStatic(&cpu->name, "Apple M1 Max"); break;
case 6002: ffStrbufSetStatic(&cpu->name, "Apple M1 Ultra"); break;
case 8112: ffStrbufSetStatic(&cpu->name, "Apple M2"); break;
case 6020: ffStrbufSetStatic(&cpu->name, "Apple M2 Pro"); break;
case 6021: ffStrbufSetStatic(&cpu->name, "Apple M2 Max"); break;
case 6022: ffStrbufSetStatic(&cpu->name, "Apple M2 Ultra"); break;
case 8122: ffStrbufSetStatic(&cpu->name, "Apple M3"); break;
case 6030: ffStrbufSetStatic(&cpu->name, "Apple M3 Pro"); break;
case 6031:
case 6034: ffStrbufSetStatic(&cpu->name, "Apple M3 Max"); break;
default: ffStrbufSetStatic(&cpu->name, "Apple Silicon"); break;
}
}
}
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
@@ -137,16 +234,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->coresOnline = (uint16_t) get_nprocs();
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY))
{
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
}
else
{
if (!detectFrequency(cpu))
cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000;
}
if(cpuUarch.length > 0)
{
@@ -167,6 +256,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectAndroid(cpu);
#endif
#if defined(__linux__) && defined(__aarch64__)
detectAsahi(cpu);
#endif
if (cpu->name.length == 0)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
@@ -191,8 +284,14 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffStrbufAppendS(&cpu->vendor, pstart);
}
pstart = pend + 1;
if (pstart >= buffer.chars + buffer.length)
return NULL;
}
}
else
{
pstart = buffer.chars;
}
}
while ((pstart = strstr(pstart, "Model name:")))
@@ -207,7 +306,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (*pstart == '-')
{
ffStrbufAppendS(&cpu->name, "Unknown");
if (cpu->vendor.length > 0)
ffStrbufAppend(&cpu->name, &cpu->vendor);
else
ffStrbufAppendS(&cpu->name, "Unknown");
++pstart;
continue;
}
@@ -222,6 +324,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
}
pstart = pend + 1;
if (pstart >= buffer.chars + buffer.length)
return NULL;
}
}
}
+85 -2
View File
@@ -2,8 +2,81 @@
#include "detection/temps/temps_windows.h"
#include "util/windows/registry.h"
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
// 7.5
typedef struct FFSmbiosProcessorInfo
{
FFSmbiosHeader Header;
uint8_t SocketDesignation; // string
uint8_t ProcessorType; // enum
uint8_t ProcessorFamily; // enum
uint8_t ProcessorManufacturer; // string
uint64_t ProcessorID; // varies
uint8_t ProcessorVersion; // string
uint8_t Voltage; // varies
uint16_t ExternalClock; // varies
uint16_t MaxSpeed; // varies
uint16_t CurrentSpeed; // varies
uint8_t Status; // varies
uint8_t ProcessorUpgrade; // enum
// 2.1+
uint16_t L1CacheHandle; // varies
uint16_t L2CacheHandle; // varies
uint16_t L3CacheHandle; // varies
// 2.3+
uint8_t SerialNumber; // string
uint8_t AssertTag; // string
uint8_t PartNumber; // string
// 2.5+
uint8_t CoreCount; // varies
uint8_t CoreEnabled; // varies
uint8_t ThreadCount; // varies
uint16_t ProcessorCharacteristics; // bit field
// 2.6+
uint16_t ProcessorFamily2; // enum
// 3.0+
uint16_t CoreCount2; // varies
uint16_t CoreEnabled2; // varies
uint16_t ThreadCount2; // varies
// 3.6+
uint16_t ThreadEnabled; // varies
} FFSmbiosProcessorInfo;
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
{
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO];
if (!data)
return "Processor information is not found in SMBIOS data";
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
{
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
return "No active CPU is found in SMBIOS data";
}
double speed;
if (data->MaxSpeed > 0 && data->MaxSpeed < 30000) // VMware reports weird values
speed = data->MaxSpeed / 1000.0;
else
speed = data->CurrentSpeed / 1000.0;
if (cpu->frequencyMax < speed)
cpu->frequencyMax = speed;
return NULL;
}
static const char* detectByOS(FFCPUResult* cpu)
{
{
DWORD length = 0;
@@ -42,14 +115,24 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
cpu->frequencyMax = mhz / 1000.0;
cpu->frequencyMin = cpu->frequencyMax = mhz / 1000.0;
}
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* error = detectByOS(cpu);
if (error)
return error;
if(options->temp)
ffDetectSmbiosTemp(&cpu->temperature, NULL);
detectMaxSpeedBySmbios(cpu);
return NULL;
}
+2 -2
View File
@@ -12,7 +12,7 @@
static void getKDE(FFstrbuf* result, FFDEOptions* options)
{
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
{"X-KDE-PluginInfo-Version =", result}
});
if(result->length == 0)
@@ -21,7 +21,7 @@ static void getKDE(FFstrbuf* result, FFDEOptions* options)
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", result);
if(result->length == 0)
{
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
{"X-KDE-PluginInfo-Version =", result}
});
}
+3 -3
View File
@@ -2,9 +2,9 @@
const char* ffDetectDisksImpl(FFlist* disks);
static int compareDisks(const void* disk1, const void* disk2)
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
{
return ffStrbufCompAlphabetically(&((const FFDisk*) disk1)->mountpoint, &((const FFDisk*) disk2)->mountpoint);
return ffStrbufComp(&disk1->mountpoint, &disk2->mountpoint);
}
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
@@ -18,7 +18,7 @@ const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
//Note that we sort alphabetically here for a better ordering when printing the list,
// so the check must be done in reverse order
ffListSort(disks, compareDisks);
ffListSort(disks, (void*) compareDisks);
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
{
if(disk->bytesTotal == 0)
+4
View File
@@ -41,6 +41,10 @@ static bool isPhysicalDevice(const struct mntent* device)
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
return false;
//#731
if(ffStrEquals(device->mnt_type, "bcachefs"))
return true;
if(
ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices
ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices
+11
View File
@@ -9,6 +9,8 @@ static uint64_t time1;
void ffPrepareDiskIO(FFDiskIOOptions* options)
{
if (options->detectTotal) return;
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
ffDiskIOGetIoCounters(&ioCounters1, options);
time1 = ffTimeGetNow();
@@ -17,6 +19,15 @@ void ffPrepareDiskIO(FFDiskIOOptions* options)
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options)
{
const char* error = NULL;
if (options->detectTotal)
{
error = ffDiskIOGetIoCounters(result, options);
if (error)
return error;
return NULL;
}
if (time1 == 0)
{
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
+2 -10
View File
@@ -8,22 +8,14 @@
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
+2 -1
View File
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <limits.h>
#include <inttypes.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
@@ -89,7 +90,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(sysBlockStat) - 1, sysBlockStat);
if (fileSize <= 0) continue;
sysBlockStat[fileSize] = '\0';
if (sscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) <= 0)
if (sscanf(sysBlockStat, "%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) <= 0)
continue;
}
@@ -129,8 +129,9 @@ static void detectDisplays(FFDisplayServerResult* ds)
(uint32_t) (monitorInfo->info.rcMonitor.bottom - monitorInfo->info.rcMonitor.top),
rotation,
&name,
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER ? FF_DISPLAY_TYPE_UNKNOWN :
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED
? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL,
!!(monitorInfo->info.dwFlags & MONITORINFOF_PRIMARY),
@@ -1,5 +1,8 @@
#include "displayserver_linux.h"
#include "common/io/io.h"
#ifdef __FreeBSD__
#include "common/settings.h"
#endif
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
@@ -31,6 +34,26 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
if(ds->displays.length == 0)
ffdsConnectDrm(ds);
#ifdef __FreeBSD__
if(ds->displays.length == 0)
{
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if (ffSettingsGetFreeBSDKenv("screen.width", &buf))
{
uint32_t width = (uint32_t) ffStrbufToUInt(&buf, 0);
if (width)
{
ffStrbufClear(&buf);
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);
}
}
}
}
#endif
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(ds);
}
+4 -4
View File
@@ -46,7 +46,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
continue;
}
uint32_t width = 0, height = 0;
unsigned width = 0, height = 0;
int scanned = sscanf(modes, "%ux%u", &width, &height);
if(scanned == 2 && width > 0 && height > 0)
@@ -143,7 +143,7 @@ static inline const char* drmType2Name(uint32_t connector_type)
return "DPI";
case DRM_MODE_CONNECTOR_WRITEBACK:
return "Writeback";
case DRM_MODE_CONNECTOR_SPI:
case 19 /*DRM_MODE_CONNECTOR_SPI*/:
return "SPI";
case 20 /*DRM_MODE_CONNECTOR_USB*/:
return "USB";
@@ -250,8 +250,8 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
drmModeCrtc* crtc = ffdrmModeGetCrtc(fd, encoder->crtc_id);
if (crtc)
{
width = crtc->mode.vdisplay;
height = crtc->mode.hdisplay;
width = crtc->mode.hdisplay;
height = crtc->mode.vdisplay;
refreshRate = crtc->mode.vrefresh;
if (refreshRate == 0)
{
+2 -1
View File
@@ -4,8 +4,9 @@
typedef struct FFGamepadDevice
{
FFstrbuf identifier;
FFstrbuf serial;
FFstrbuf name;
uint8_t battery; // 0-100%
} FFGamepadDevice;
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */);
+39 -15
View File
@@ -1,18 +1,34 @@
#include "gamepad.h"
#include "util/apple/cf_helpers.h"
#include "util/mallocHelper.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
static void enumSet(const void* value, void *context)
static void enumSet(IOHIDDeviceRef value, FFlist* results)
{
CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey));
CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey));
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context);
ffStrbufInit(&device->identifier);
ffCfStrGetString(serialNumber, &device->identifier);
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(results);
ffStrbufInit(&device->serial);
ffStrbufInit(&device->name);
ffCfStrGetString(product, &device->name);
device->battery = 0;
CFStringRef manufacturer = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDManufacturerKey));
ffCfStrGetString(manufacturer, &device->name);
CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey));
if (device->name.length)
{
ffCfStrGetString(product, &device->serial);
ffStrbufAppendC(&device->name, ' ');
ffStrbufAppend(&device->name, &device->serial);
}
else
{
ffCfStrGetString(product, &device->name);
}
CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey));
ffCfStrGetString(serialNumber, &device->serial);
}
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
@@ -21,21 +37,29 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
return "IOHIDManagerOpen() failed";
CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop);
CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFSTR(kIOHIDDeviceUsagePageKey),
CFSTR(kIOHIDDeviceUsageKey)
}, (const void **)(CFNumberRef[]){
genericDesktop,
gamePad
ffCfCreateInt(kHIDPage_GenericDesktop),
ffCfCreateInt(kHIDUsage_GD_Joystick)
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
IOHIDManagerSetDeviceMatching(manager, matching);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching2 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFSTR(kIOHIDDeviceUsagePageKey),
CFSTR(kIOHIDDeviceUsageKey)
}, (const void **)(CFNumberRef[]){
ffCfCreateInt(kHIDPage_GenericDesktop),
ffCfCreateInt(kHIDUsage_GD_GamePad)
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFArrayRef FF_CFTYPE_AUTO_RELEASE matchings = CFArrayCreate(kCFAllocatorDefault, (const void **)(CFTypeRef[]){
matching1, matching2
}, 2, &kCFTypeArrayCallBacks);
IOHIDManagerSetDeviceMatchingMultiple(manager, matchings);
CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
if (set)
CFSetApplyFunction(set, &enumSet, devices);
IOHIDManagerClose(manager, 0);
CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices);
IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
return NULL;
}
+2 -1
View File
@@ -42,8 +42,9 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1)
{
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, di.udi_serial);
ffStrbufInitS(&device->serial, di.udi_serial);
ffStrbufInitF(&device->name, "%s %s", di.udi_vendor, di.udi_product);
device->battery = 0;
}
}
}
+62 -13
View File
@@ -5,39 +5,88 @@
#include <dirent.h>
#include <ctype.h>
static void detectGamepad(FFlist* devices, FFstrbuf* name, FFstrbuf* path)
{
uint32_t baseLen = path->length;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInit(&device->serial);
ffStrbufInitMove(&device->name, name);
device->battery = 0;
ffStrbufAppendS(path, "uniq");
if (ffAppendFileBuffer(path->chars, &device->serial))
ffStrbufTrimRightSpace(&device->serial);
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "device/power_supply/"); // /sys/class/input/jsX/device/device/power_supply
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path->chars);
if (dirp)
{
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.' || (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN))
continue;
ffStrbufAppendS(path, entry->d_name);
ffStrbufAppendS(path, "/capacity"); // /sys/class/input/jsX/device/device/power_supply/XXX/capacity
char capacity[32];
ssize_t nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
if (nRead > 0) // Tested with a PS4 controller
{
capacity[nRead] = '\0';
device->battery = (uint8_t) strtoul(capacity, NULL, 10);
break;
}
ffStrbufAppendS(path, "_level");
nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
if (nRead > 0) // Tested with a NS Pro controller
{
// https://github.com/torvalds/linux/blob/52b1853b080a082ec3749c3a9577f6c71b1d4a90/drivers/power/supply/power_supply_sysfs.c#L124
switch (capacity[0])
{
case 'C': device->battery = 1; break; // Critical
case 'L': device->battery = 25; break; // Low
case 'N': device->battery = 50; break; // Normal
case 'H': device->battery = 75; break; // High
case 'F': device->battery = 100; break; // Full
}
}
}
}
}
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
{
DIR* dirp = opendir("/sys/class/input/");
if(dirp == NULL)
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/");
if (dirp == NULL)
return "opendir(\"/sys/class/input/\") == NULL";
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/");
uint32_t baseLen = path.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
while ((entry = readdir(dirp)) != NULL)
{
if(!ffStrStartsWith(entry->d_name, "js"))
if (!ffStrStartsWith(entry->d_name, "js"))
continue;
if(!isdigit(entry->d_name[2]))
if (!isdigit(entry->d_name[2]))
continue;
ffStrbufAppendS(&path, entry->d_name);
ffStrbufAppendS(&path, "/device/name");
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
if (ffAppendFileBuffer(path.chars, &name))
{
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, entry->d_name);
ffStrbufInit(&device->name);
if (ffAppendFileBuffer(path.chars, &device->name))
ffStrbufTrimRightSpace(&device->name);
ffStrbufTrimRightSpace(&name);
ffStrbufSubstrBefore(&path, path.length - 4);
detectGamepad(devices, &name, &path);
}
ffStrbufSubstrBefore(&path, baseLen);
}
closedir(dirp);
return NULL;
}
+90 -37
View File
@@ -3,10 +3,11 @@
#include "util/mallocHelper.h"
#include "util/windows/unicode.h"
#include <winternl.h>
#include <windows.h>
#include <hidsdi.h>
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
static const char* detectKnownDeviceName(uint32_t vendorId, uint32_t productId)
{
switch (vendorId)
{
@@ -30,38 +31,14 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
{
switch (productId)
{
case 0x0268: return "Sony Playstation 3 Controller";
case 0x0268: return "Sony DualShock 3 / Six Axis";
case 0x05C4: return "Sony DualShock 4 Gen1";
case 0x09CC: return "Sony DualShock 4 Gen2";
case 0x0BA0: return "Sony PS4 Controller USB receiver";
case 0x0BA0: return "Sony DualShock 4 USB receiver";
case 0x0CE6: return "Sony DualSense";
default: return NULL;
}
}
// Microsoft
case 0x045E:
{
switch (productId)
{
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
case 0x028E: return "Microsoft XBox 360";
case 0x028F: return "Microsoft XBox 360 v2";
case 0x02A1: return "Microsoft XBox 360";
case 0x0291: return "Microsoft XBox 360 USB receiver";
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
case 0x02DD: return "Microsoft XBox One";
case 0xB326: return "Microsoft XBox One Firmware 2015";
case 0x02E3: return "Microsoft XBox One Elite";
case 0x02FF: return "Microsoft XBox One Elite";
case 0x02EA: return "Microsoft XBox One S";
case 0x0DF2: return "Sony DualSense Edge";
default: return NULL;
}
@@ -83,6 +60,7 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
}
}
case 0x045E: // Microsoft Xbox compatible controllers should be handled by Windows without problems
default: return NULL;
}
}
@@ -98,7 +76,8 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
for (UINT i = 0; i < nDevices; ++i) {
for (UINT i = 0; i < nDevices; ++i)
{
if (pRawInputDeviceList[i].dwType != 2) continue;
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
@@ -117,20 +96,94 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
continue;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitWS(&device->identifier, devName);
ffStrbufInit(&device->serial);
ffStrbufInit(&device->name);
device->battery = 0;
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
const char* knownGamepad = detectKnownDeviceName(rdi.hid.dwVendorId, rdi.hid.dwProductId);
if (knownGamepad)
ffStrbufSetS(&device->name, knownGamepad);
else
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (!hHidFile)
{
if (!knownGamepad)
ffStrbufSetF(&device->name, "Unknown gamepad %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
continue;
}
if (!knownGamepad)
{
wchar_t displayName[126];
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
ffStrbufSetWS(&device->name, displayName);
else
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
if (HidD_GetProductString(hHidFile, displayName, sizeof(displayName)))
{
wchar_t manufacturer[126];
if (HidD_GetManufacturerString(hHidFile, manufacturer, sizeof(manufacturer)))
{
ffStrbufSetWS(&device->name, manufacturer);
FF_STRBUF_AUTO_DESTROY displayNameStr = ffStrbufCreateWS(displayName);
ffStrbufAppendC(&device->name, ' ');
ffStrbufAppend(&device->name, &displayNameStr);
}
else
{
ffStrbufSetWS(&device->name, displayName);
}
}
}
PHIDP_PREPARSED_DATA preparsedData = NULL;
if (HidD_GetPreparsedData(hHidFile, &preparsedData))
{
HIDP_CAPS caps;
NTSTATUS capsResult = HidP_GetCaps(preparsedData, &caps);
HidD_FreePreparsedData(preparsedData);
if (!NT_SUCCESS(capsResult))
continue;
wchar_t serialNumber[127] = L"";
if (HidD_GetSerialNumberString(hHidFile, serialNumber, sizeof(serialNumber)))
ffStrbufSetWS(&device->serial, serialNumber);
if (
(rdi.hid.dwVendorId == 0x054C && (
rdi.hid.dwProductId == 0x05C4 || // PS4 Gen1
rdi.hid.dwProductId == 0x09CC // PS4 Gen2
)) ||
(rdi.hid.dwVendorId == 0x057E && (
rdi.hid.dwProductId == 0x2009 // NS Pro
))
)
{
// Controller must be connected by other programs
FF_AUTO_FREE uint8_t* reportBuffer = malloc(caps.InputReportByteLength);
OVERLAPPED overlapped = { };
DWORD nBytes;
if (ReadFile(hHidFile, reportBuffer, caps.InputReportByteLength, &nBytes, &overlapped) ||
(WaitForSingleObject(hHidFile, FF_IO_TERM_RESP_WAIT_MS) == WAIT_OBJECT_0 && GetOverlappedResult(hHidFile, &overlapped, &nBytes, FALSE)))
{
if (rdi.hid.dwVendorId == 0x054C)
{
if (nBytes > 31)
{
uint8_t batteryInfo = reportBuffer[caps.InputReportByteLength == 64 /*USB?*/ ? 30 : 32];
device->battery = (uint8_t) ((batteryInfo & 0x0f) * 100 / (batteryInfo & 0x10 /*charging?*/ ? 11 /*BATTERY_MAX_USB*/ : 8 /*BATTERY_MAX*/));
if (device->battery > 100) device->battery = 100;
}
}
else
{
if (nBytes > 3 && reportBuffer[0] == 0x30)
{
uint8_t batteryInfo = reportBuffer[2];
device->battery = (uint8_t) (((batteryInfo & 0xE0) >> 4) * 100 / 8);
if (device->battery == 0) device->battery = 1;
else if (device->battery > 100) device->battery = 100;
}
}
}
else
CancelIo(hHidFile);
}
}
}
+12 -4
View File
@@ -6,6 +6,8 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
const char* FF_GPU_VENDOR_NAME_QUALCOMM = "Qualcomm";
const char* FF_GPU_VENDOR_NAME_MTK = "MTK";
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
@@ -33,6 +35,10 @@ const char* ffGetGPUVendorString(unsigned vendorId)
return FF_GPU_VENDOR_NAME_INTEL;
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
return FF_GPU_VENDOR_NAME_NVIDIA;
else if(arrayContains((const unsigned[]) {0x5143}, vendorId, 1))
return FF_GPU_VENDOR_NAME_QUALCOMM;
else if(arrayContains((const unsigned[]) {0x14c3}, vendorId, 1))
return FF_GPU_VENDOR_NAME_MTK;
else if(arrayContains((const unsigned[]) {0x15ad}, vendorId, 1))
return FF_GPU_VENDOR_NAME_VMWARE;
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
@@ -73,15 +79,17 @@ const char* detectByOpenGL(FFlist* gpus)
if (!gpu->vendor.length)
{
if (ffStrbufContainS(&result.renderer, "Apple"))
if (ffStrbufContainS(&gpu->name, "Apple"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
else if (ffStrbufContainS(&result.renderer, "Intel"))
else if (ffStrbufContainS(&gpu->name, "Intel"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if (ffStrbufContainS(&result.renderer, "AMD") || ffStrbufContainS(&result.renderer, "ATI"))
else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if (ffStrbufContainS(&result.renderer, "NVIDIA"))
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
}
if (ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE))
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
ffStrbufDestroy(&result.version);
+4
View File
@@ -42,3 +42,7 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGetGPUVendorString(unsigned vendorId);
#if defined(__linux__) || defined(__FreeBSD__)
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
#endif
+3 -5
View File
@@ -38,12 +38,12 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
@@ -106,8 +106,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
ffGpuDetectMetal(gpus);
return NULL;
}
+15 -4
View File
@@ -15,7 +15,7 @@ const char* ffGpuDetectMetal(FFlist* gpus)
FFGPUResult* gpu = NULL;
FF_LIST_FOR_EACH(FFGPUResult, x, *gpus)
{
if (x->deviceId == device.registryID || ffStrbufEqualS(&x->name, device.name.UTF8String))
if (x->deviceId == device.registryID)
{
gpu = x;
break;
@@ -32,9 +32,20 @@ const char* ffGpuDetectMetal(FFlist* gpus)
else if ([device supportsFamily:MTLGPUFamilyCommon1])
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
if (device.hasUnifiedMemory)
{
gpu->type = FF_GPU_TYPE_INTEGRATED;
gpu->shared.total = device.recommendedMaxWorkingSetSize;
gpu->shared.used = device.currentAllocatedSize;
}
else
{
gpu->type = FF_GPU_TYPE_DISCRETE;
gpu->dedicated.total = device.recommendedMaxWorkingSetSize;
gpu->dedicated.used = device.currentAllocatedSize;
}
}
return NULL;
}
return NULL;
return "Metal API is not supported by this macOS version";
}
+106
View File
@@ -0,0 +1,106 @@
#include "gpu_driver_specific.h"
#include "common/io/io.h"
#include "common/properties.h"
#include "3rdparty/nvml/nvml.h"
#include "util/mallocHelper.h"
#include <dev/pci/pcireg.h>
#include <sys/pciio.h>
#include <fcntl.h>
#include <paths.h>
static bool loadPciIds(FFstrbuf* pciids)
{
// https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids);
if (pciids->length > 0) return true;
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids);
if (pciids->length > 0) return true;
return false;
}
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
struct pci_conf confs[128];
struct pci_match_conf match = {
.pc_class = PCIC_DISPLAY,
.flags = PCI_GETCONF_MATCH_CLASS,
};
struct pci_conf_io pcio = {
.pat_buf_len = sizeof(match),
.num_patterns = 1,
.patterns = &match,
.match_buf_len = sizeof(confs),
.matches = confs,
};
if (ioctl(fd, PCIOCGETCONF, &pcio) < 0)
return "ioctl(fd, PCIOCGETCONF, &pc) failed";
if (pcio.status == PCI_GETCONF_ERROR)
return "ioctl(fd, PCIOCGETCONF, &pc) returned error";
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
for (uint32_t i = 0; i < pcio.num_matches; ++i)
{
struct pci_conf* pc = &confs[i];
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(pc->pc_vendor));
ffStrbufInit(&gpu->name);
ffStrbufInitS(&gpu->driver, pc->pd_name);
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
char query[32];
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid);
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
}
if (gpu->name.length == 0)
{
if (pciids.length == 0)
loadPciIds(&pciids);
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = (uint32_t) pc->pc_sel.pc_domain,
.bus = pc->pc_sel.pc_bus,
.device = pc->pc_sel.pc_dev,
.func = pc->pc_sel.pc_func,
},
}, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
}, "libnvidia-ml.so");
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
}
return NULL;
}
+145 -300
View File
@@ -1,151 +1,28 @@
#include "detection/gpu/gpu.h"
#include "detection/gpu/gpu_driver_specific.h"
#include "detection/vulkan/vulkan.h"
#ifdef FF_HAVE_LIBPCI
#include "common/io/io.h"
#include "common/library.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "detection/temps/temps_linux.h"
#include "common/io/io.h"
#include "common/properties.h"
#include "util/stringUtils.h"
#include <string.h>
#include <unistd.h>
#include <pci/pci.h>
#include <setjmp.h>
// Fix building on Ubuntu 20.04
#ifndef PCI_IORESOURCE_MEM
#define PCI_IORESOURCE_MEM 0x00000200
#endif
#ifndef PCI_IORESOURCE_PREFETCH
#define PCI_IORESOURCE_PREFETCH 0x00002000
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
#include "detection/gpu/gpu_driver_specific.h"
#endif
typedef struct PCIData
{
struct pci_access* access;
FF_LIBRARY_SYMBOL(pci_fill_info)
FF_LIBRARY_SYMBOL(pci_read_byte)
FF_LIBRARY_SYMBOL(pci_lookup_name)
FF_LIBRARY_SYMBOL(pci_get_param)
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#if PCI_LIB_VERSION >= 0x030800
FF_LIBRARY_SYMBOL(pci_get_string_property)
#endif
} PCIData;
#include <inttypes.h>
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
if(gpu->vendor.length > 0)
return;
ffStrbufEnsureFree(&gpu->vendor, 255);
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id);
ffStrbufRecalculateLength(&gpu->vendor);
if(ffStrbufContainIgnCaseS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Intel"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Apple"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
}
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
u8 revId = 0;
bool revIdSet = false;
#if PCI_LIB_VERSION >= 0x030800
revIdSet = pci->ffpci_fill_info(device, PCI_FILL_CLASS_EXT) & PCI_FILL_CLASS_EXT;
if(revIdSet)
revId = device->rev_id;
#endif
if(!revIdSet)
{
#ifdef __FreeBSD__
return;
#else
revId = pci->ffpci_read_byte(device, PCI_REVISION_ID);
#endif
}
FF_STRBUF_AUTO_DESTROY query = ffStrbufCreateF("%X, %X,", device->device_id, revId);
ffParsePropFileData("libdrm/amdgpu.ids", query.chars, &gpu->name);
const char* removeStrings[] = {
"AMD ", "ATI ",
" (TM)", "(TM)",
" Graphics Adapter", " Graphics", " Series", " Edition"
};
ffStrbufRemoveStrings(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
}
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD))
{
drmDetectDeviceName(gpu, pci, device);
if(gpu->name.length > 0)
return;
}
ffStrbufEnsureFree(&gpu->name, 255);
pci->ffpci_lookup_name(pci->access, gpu->name.chars, (int) gpu->name.allocated, PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
ffStrbufRecalculateLength(&gpu->name);
uint32_t openingBracket = ffStrbufFirstIndexC(&gpu->name, '[');
uint32_t closingBracket = ffStrbufNextIndexC(&gpu->name, openingBracket, ']');
if(closingBracket < gpu->name.length)
{
ffStrbufSubstrBefore(&gpu->name, closingBracket);
ffStrbufSubstrAfter(&gpu->name, openingBracket);
}
}
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
#if PCI_LIB_VERSION >= 0x030800
pci->ffpci_fill_info(device, PCI_FILL_DRIVER);
ffStrbufAppendS(&gpu->driver, pci->ffpci_get_string_property(device, PCI_FILL_DRIVER));
#endif
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
if(!ffStrSet(base))
return;
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
if (gpu->driver.length == 0)
{
ffStrbufEnsureFree(&gpu->driver, 1023);
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
if(resultLength > 0)
{
gpu->driver.length = (uint32_t) resultLength;
gpu->driver.chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
}
}
ffStrbufAppendC(&gpu->driver, ' ');
ffStrbufAppendS(&path, "/module/version");
ffAppendFileBuffer(path.chars, &gpu->driver);
ffStrbufTrimRightSpace(&gpu->driver);
}
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device)
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
{
const FFlist* tempsResult = ffDetectTemps();
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
{
// FIXME: this code doesn't take multiGPUs into count
//The kernel exposes the device class multiplied by 256 for some reason
if(tempValue->deviceClass == device->device_class * 256)
if(tempValue->deviceClass == deviceClass * 256)
{
gpu->temperature = tempValue->value;
return;
@@ -153,193 +30,166 @@ FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* devi
}
}
FF_MAYBE_UNUSED static bool pciDetectMemory(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* device)
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
gpu->dedicated.used = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
uint32_t flags = (uint32_t) pci->ffpci_fill_info(device, PCI_FILL_IO_FLAGS | PCI_FILL_SIZES);
if (!(flags & PCI_FILL_IO_FLAGS) || !(flags & PCI_FILL_SIZES))
ffStrbufAppendS(pciDir, "/driver");
char pathBuf[PATH_MAX];
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
if(resultLength > 0)
{
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
return false;
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
if (slash)
{
slash++;
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
}
ffStrbufAppendS(pciDir, "/module/version");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
ffStrbufTrimRightSpace(buffer);
ffStrbufAppendC(&gpu->driver, ' ');
ffStrbufAppend(&gpu->driver, buffer);
}
}
gpu->dedicated.total = gpu->shared.total = 0;
for (uint32_t i = 0; i < sizeof(device->size) / sizeof(device->size[0]); i++)
{
if (!(device->flags[i] & PCI_IORESOURCE_MEM)) continue;
// Assume dedicated memories are prefetchable
// At least it's true for my laptop
if (device->flags[i] & PCI_IORESOURCE_PREFETCH)
gpu->dedicated.total += device->size[i];
else
gpu->shared.total += device->size[i];
}
if (gpu->dedicated.total == 0 && gpu->shared.total == 0)
{
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
return false;
}
return true;
}
FF_MAYBE_UNUSED static void pciDetectType(FFGPUResult* gpu)
static bool loadPciIds(FFstrbuf* pciids)
{
//There is no straightforward way to detect the type of a GPU.
//The approach taken here is to look at the memory sizes of the device.
//Since integrated GPUs usually use the system ram, they don't have expansive ROMs
//and their memory sizes are usually smaller than 1GB.
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
{
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 // 1GB
? FF_GPU_TYPE_DISCRETE
: FF_GPU_TYPE_INTEGRATED;
}
else
gpu->type = FF_GPU_TYPE_UNKNOWN;
}
static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* results, PCIData* pci, struct pci_dev* device)
{
pci->ffpci_fill_info(device, PCI_FILL_CLASS);
char class[1024];
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
if(
//https://pci-ids.ucw.cz/read/PD/03
strcasecmp("VGA compatible controller", class) != 0 &&
strcasecmp("XGA compatible controller", class) != 0 &&
strcasecmp("3D controller", class) != 0 &&
strcasecmp("Display controller", class) != 0
) return;
pci->ffpci_fill_info(device, PCI_FILL_IDENT);
FFGPUResult* gpu = ffListAdd(results);
ffStrbufInit(&gpu->platformApi);
ffStrbufInit(&gpu->vendor);
pciDetectVendorName(gpu, pci, device);
ffStrbufInit(&gpu->name);
pciDetectDeviceName(gpu, pci, device);
ffStrbufInit(&gpu->driver);
pciDetectDriverName(gpu, pci, device);
#if FF_USE_PCI_MEMORY
// Libpci reports at least 2 false results (#495, #497)
pciDetectMemory(gpu, pci, device);
pciDetectType(gpu);
#else
gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
#ifdef FF_CUSTOM_PCI_IDS_PATH
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids);
if (pciids->length > 0) return true;
#endif
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = (uint32_t) device->domain,
.bus = device->bus,
.device = device->dev,
.func = device->func,
},
}, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
}, "libnvidia-ml.so");
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian?
if (pciids->length > 0) return true;
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
#ifdef __linux__
if(options->temp && gpu->temperature != gpu->temperature)
pciDetectTemp(gpu, device);
#endif
}
jmp_buf pciInitJmpBuf;
static void __attribute__((__noreturn__))
handlePciInitError(FF_MAYBE_UNUSED char *msg, ...)
{
longjmp(pciInitJmpBuf, 1);
}
// https://github.com/pciutils/pciutils/blob/bca0412843fa650c749128ade03f35ab3e8fe2b9/lib/init.c#L186
static void __attribute__((__noreturn__))
handlePciGenericError(char *msg, ...)
{
va_list args;
va_start(args, msg);
fputs("pcilib: ", stderr);
vfprintf(stderr, msg, args);
va_end(args);
fputc('\n', stderr);
exit(1);
}
static void handlePciWarning(FF_MAYBE_UNUSED char *msg, ...)
{
// noop
return false;
}
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
PCIData pci;
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
const char* pciDirPath = "/sys/bus/pci/devices/";
FF_LIBRARY_LOAD(libpci, &instance.config.library.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_alloc);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_init);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_scan_bus);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_cleanup);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDirPath);
if(dirp == NULL)
return "Failed to open `/sys/bus/pci/devices/`";
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_fill_info);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_lookup_name);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_read_byte);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_param);
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
ffStrbufAppendS(&pciDir, pciDirPath);
#if PCI_LIB_VERSION >= 0x030800
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_string_property);
#endif
const uint32_t pciBaseDirLength = pciDir.length;
pci.access = ffpci_alloc();
pci.access->warning = handlePciWarning;
pci.access->error = handlePciInitError;
if(setjmp(pciInitJmpBuf) == 0) // https://github.com/pciutils/pciutils/issues/136
ffpci_init(pci.access);
else
return "pcilib: Cannot find any working access method.";
pci.access->error = handlePciGenericError; // set back to generic error so we don't mess up error handling in other places
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
ffpci_scan_bus(pci.access);
struct pci_dev* device = pci.access->devices;
while(device != NULL)
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
pciHandleDevice(options, gpus, &pci, device);
device = device->next;
if(entry->d_name[0] == '.')
continue;
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
ffStrbufAppendS(&pciDir, entry->d_name);
const uint32_t pciDevDirLength = pciDir.length;
ffStrbufAppendS(&pciDir, "/modalias");
if (!ffReadFileBuffer(pciDir.chars, &buffer))
continue;
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
uint8_t classId, subclassId;
if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6)
continue;
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
continue;
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
if (sscanf(entry->d_name, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
ffStrbufAppendS(&pciDir, "/revision");
if (ffReadFileBuffer(pciDir.chars, &buffer))
{
char* pend;
uint64_t revision = strtoul(buffer.chars, &pend, 16);
if (pend != buffer.chars)
{
char query[32];
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
}
}
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
}
if (gpu->name.length == 0)
{
if (!pciids.length)
loadPciIds(&pciids);
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
}
pciDetectDriver(gpu, &pciDir, &buffer);
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = pciDomain,
.bus = pciBus,
.device = pciDevice,
.func = pciFunc,
},
}, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
}, "libnvidia-ml.so");
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
#ifdef __linux__
if(options->temp && gpu->temperature != gpu->temperature)
pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
#endif
}
ffpci_cleanup(pci.access);
return NULL;
}
#endif
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
#ifdef FF_HAVE_DIRECTX_HEADERS
@@ -348,10 +198,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
return NULL;
#endif
#ifdef FF_HAVE_LIBPCI
return pciDetectGPUs(options, gpus);
#else
FF_UNUSED(options, gpus);
return "fastfetch is built without libpci support";
#endif
return pciDetectGPUs(options, gpus);
}
+20
View File
@@ -12,6 +12,7 @@ struct FFNvmlData {
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
FF_LIBRARY_SYMBOL(nvmlDeviceGetClockInfo)
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
bool inited;
} nvmlData;
@@ -32,6 +33,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetClockInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
if (ffnvmlInit_v2() != NVML_SUCCESS)
{
@@ -79,6 +81,24 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
if (!device) return "Device not found";
}
nvmlBrandType_t brand;
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
{
switch (brand)
{
case NVML_BRAND_NVIDIA_RTX:
case NVML_BRAND_QUADRO_RTX:
case NVML_BRAND_GEFORCE:
case NVML_BRAND_TITAN:
case NVML_BRAND_TESLA:
case NVML_BRAND_QUADRO:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
}
}
if (result.temp)
{
uint32_t value;
+74
View File
@@ -0,0 +1,74 @@
#include "gpu.h"
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
{
if (content->length)
{
char buffer[32];
// Search for vendor
uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor);
char* start = (char*) memmem(content->chars, content->length, buffer, len);
char* end = content->chars + content->length;
if (start)
{
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
end = content->chars + content->length;
if (!gpu->vendor.length)
ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start);
start = end; // point to '\n' of vendor
end = start + 1; // point to start of devices
// find the start of next vendor
while (end[0] == '\t' || end[0] == '#')
{
end = strchr(end, '\n');
if (!end)
{
end = content->chars + content->length;
break;
}
else
end++;
}
// Search for device
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device);
start = memmem(start, (size_t) (end - start), buffer, len);
if (start)
{
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
end = content->chars + content->length;
char* openingBracket = memchr(start, '[', (uint32_t) (end - start));
if (openingBracket)
{
openingBracket++;
char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket));
if (closingBracket)
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
}
if (!gpu->name.length)
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
}
}
}
if (!gpu->name.length)
{
const char* subclassStr;
switch (subclass)
{
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
default: subclassStr = ""; break;
}
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
}
}
+9 -2
View File
@@ -1,8 +1,11 @@
#include "gpu.h"
#include "detection/gpu/gpu_driver_specific.h"
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
#include "detection/gpu/gpu_driver_specific.h"
#endif
#include <inttypes.h>
static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
@@ -10,6 +13,7 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
return ffStrbufEqual(&gpu->name, name);
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
@@ -44,6 +48,7 @@ static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&
return true;
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
@@ -72,7 +77,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
// See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html
// displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1"
uint32_t vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
@@ -139,6 +144,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
}
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* dllName;
@@ -168,6 +174,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
);
}
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
}
return NULL;

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