Compare commits

...

219 Commits

Author SHA1 Message Date
Carter Li 18374467e6 Merge pull request #615 from fastfetch-cli/dev
Release v2.2.2
2023-11-07 10:02:19 +08:00
李通洲 499e6c85a0 Battery (Windows): slilence compiler warnings 2023-11-07 09:59:00 +08:00
李通洲 0610faf1be Release v2.2.2 2023-11-07 09:47:37 +08:00
李通洲 778c6f0513 Doc: update changelog 2023-11-07 09:03:01 +08:00
李通洲 c55ba2685f Battery (macOS): add status Discharging to be consistant with other platforms 2023-11-07 08:56:07 +08:00
李通洲 aae66aa966 Logo (Image): fix spelling of --preserve-aspect-ratio
Fix #614
2023-11-07 08:49:22 +08:00
李通洲 a95b60167c Doc: fix typo in README
Fix #613
2023-11-07 08:37:29 +08:00
李通洲 f5b987dba9 Battery (Windows): detect cycle count 2023-11-06 19:40:40 +08:00
李通洲 f8eabdd8a6 Battry (Linux): try detecting cycle count and temperature 2023-11-06 19:08:17 +08:00
李通洲 5ab2c3456d Battery (Apple): better detection 2023-11-06 16:42:16 +08:00
李通洲 97d9ffd193 Bios: detect firmware type 2023-11-06 15:29:55 +08:00
李通洲 fa86bb1f0b CI (FreeBSD): update action version 2023-11-06 10:24:06 +08:00
李通洲 5b9c5ebb5a CI (Win64): improve speed 2023-11-06 10:11:51 +08:00
李通洲 56b03a93c5 CI (Linux): build with imagemagick7 2023-11-06 10:05:01 +08:00
李通洲 3b319f0a1e Global: add missing changes 2023-11-05 13:25:54 +08:00
李通洲 c3352d6d28 CI: always update dependencies explicitly
Fix macOS build
2023-11-05 13:25:13 +08:00
李通洲 f8426384d8 CI: print verbose logs when building 2023-11-05 13:02:48 +08:00
李通洲 8791281b48 CI: try fixing macOS build 2023-11-05 10:38:43 +08:00
李通洲 76ec8aff2e Doc: update changelog 2023-11-05 10:16:48 +08:00
李通洲 7660b0a091 Global: defaults percentType to 9 ( colored number ) 2023-11-05 10:11:53 +08:00
李通洲 7a8e484634 Global: prints LocalIp by default
Fix #611
2023-11-05 10:11:40 +08:00
李通洲 ed01272b91 LocalIP: detect netmask 2023-11-05 09:42:28 +08:00
Viorel 1c660caa85 Fix unitialized variables (#609)
Compiling with gcc 13 and -O3 -flto -Werror=uninitialized found two
possibly unitialized variables.

See also: https://bugs.gentoo.org/916722
2023-11-03 23:03:14 +08:00
李通洲 c241ead1d5 Logo (Builtin): update nixos_small, add nixos_old_small
Fix #608
2023-11-02 23:22:48 +08:00
Carter Li 168d96a182 Merge pull request #607 from fastfetch-cli/dev
Release v2.2.1
2023-11-02 15:34:16 +08:00
李通洲 2075761282 fastfetch: --help honors --pipe 2023-11-02 14:44:18 +08:00
李通洲 d59de1f158 Release v2.2.1 2023-11-02 14:35:16 +08:00
李通洲 d64716ab74 fastfetch: pretty printing --help 2023-11-02 14:11:06 +08:00
李通洲 0ffbb8c364 Doc: update help messages 2023-11-02 14:11:06 +08:00
李通洲 c29960abf2 Presets: fix regression #606 2023-11-02 09:32:58 +08:00
Carter Li 315cb24046 Merge pull request #604 from fastfetch-cli/dev
Fix CI of FreeBSD
2023-11-01 16:06:10 +08:00
李通洲 4cabc5684b CPUUsage: don't count NaN values 2023-11-01 15:55:13 +08:00
李通洲 256c9be19b CPUUsage: skip NaN when summarizing values 2023-11-01 15:49:51 +08:00
李通洲 1b3d713e50 CPUUsage: always print something 2023-11-01 15:36:13 +08:00
李通洲 6e816fca6e CPUUsage: don't hang on weird host
Try fixing CI of FreeBSD
2023-11-01 15:26:24 +08:00
李通洲 5a699af610 OS (macOS): improve performance 2023-11-01 15:24:52 +08:00
Carter Li 390119c592 Merge pull request #603 from fastfetch-cli/dev
Release v2.2.0
2023-11-01 14:04:08 +08:00
李通洲 11d7eec4db Revert "FreeBSD: debug"
This reverts commit 6508ccfc0d.
2023-11-01 12:22:28 +08:00
李通洲 f59be1faf2 Release v2.2.0 2023-11-01 11:29:03 +08:00
李通洲 7bc4c63eb4 Migration: don't overwrite existing files 2023-11-01 11:28:08 +08:00
李通洲 4bf9f524d9 Logo (Builtin): add Interix 2023-11-01 11:16:16 +08:00
李通洲 6508ccfc0d FreeBSD: debug 2023-11-01 09:52:15 +08:00
李通洲 d0a8d3cdc4 TerminalFont (Linux): early return 2023-11-01 09:42:52 +08:00
李通洲 494cc1493e TerminalFont (Linux): support xfce4-terminal 1.1.0+
Fixes #602
2023-11-01 09:40:49 +08:00
李通洲 761c649817 TerminalShell: better support for environment running with su 2023-11-01 08:55:00 +08:00
李通洲 a2f576f3e5 GPU (WSL): support nvml too 2023-11-01 00:10:24 +08:00
李通洲 3b9b03a086 FreeBSD: fix build 2023-10-31 23:45:38 +08:00
李通洲 ab51a209d7 CI: try fixing FreeBSD build 2023-10-31 22:53:06 +08:00
李通洲 38ac339011 WM: support WindowBlinds detection 2023-10-31 22:40:44 +08:00
李通洲 b4777fe73a Windows: silence compiler warnings 2023-10-31 22:40:44 +08:00
李通洲 b6e759f3a2 LocalIP / NetIO: make defaultRouteOnly defaults to true 2023-10-31 19:53:25 +08:00
李通洲 9ddefbc1a2 Doc: update README 2023-10-31 16:32:57 +08:00
李通洲 a16851f5de JsonConfig: update json schema; change most title to description 2023-10-31 15:47:55 +08:00
李通洲 8fe291d161 Doc: remove information of flag based configuration 2023-10-31 15:47:23 +08:00
李通洲 9ac50fc42f GPU: add more vendors 2023-10-31 15:11:22 +08:00
李通洲 c6e5221826 CMake: build with ASAN conditionally 2023-10-31 14:57:32 +08:00
李通洲 5b2006cd06 Global: get rid of locks
Psychological burden NO MORE
2023-10-31 14:42:45 +08:00
李通洲 d3f673dc6f Init: remove separate thread of displayserver and qt/gtk stuff detection
These threads are detached. If the main thread exits before the sub threads end, fastfetch may crash in various ways.

It barely benefits performance. `hyperfine` shows completely no difference between `--thread` enabled and disabled. Let's get rid of it.
2023-10-31 14:32:30 +08:00
李通洲 b99f444234 Global: remove --allow-slow-operations 2023-10-31 14:10:21 +08:00
李通洲 c504096181 Processing (Linux): fix hanging if a child process prints to both stdout and stderr 2023-10-31 14:06:08 +08:00
李通洲 c9ef47271a Brightness: fix flag --brightness-ddcci-sleep 2023-10-31 10:09:31 +08:00
李通洲 fc3891c913 DE: implement --de-slow-version-detection 2023-10-31 10:07:41 +08:00
李通洲 cd07354b6f Doc: update changelog and other docs 2023-10-31 09:50:54 +08:00
kojq fd5aeb2052 Update structure.txt (#600)
add swap information as default
2023-10-30 20:27:10 -05:00
李通洲 b1b583721a Logo (Builtin): add MainsailOS
Ref: https://github.com/dylanaraps/neofetch/pull/2407
2023-10-31 09:15:15 +08:00
李通洲 4c3372a886 Logo (Builtin): fix phyOS 2023-10-31 08:51:56 +08:00
李通洲 cf66679323 DE: move version detection code to separate files 2023-10-30 22:46:38 +08:00
李通洲 55b41144db WM: add flag --wm-detect-plugin 2023-10-30 16:34:35 +08:00
李通洲 ae34208247 Battery (Windows): add flag --battery-use-setup-api 2023-10-30 14:49:00 +08:00
李通洲 b462006280 Chassis (Windows): add flag --chassis-use-wmi 2023-10-30 14:31:19 +08:00
李通洲 485bcbf054 GPU: add flag --gpu-use-nvml 2023-10-30 13:46:51 +08:00
李通洲 2e30a57889 TerminalFont: always use kitten to detect kitty term fonts 2023-10-30 11:05:43 +08:00
李通洲 b439d9c203 Doc: we use Apple80211 instead of IO80211 2023-10-30 09:21:01 +08:00
李通洲 08a717f5f7 JsonConfig: more friendly error message 2023-10-30 09:14:13 +08:00
李通洲 3a84a1a5fa Packages (Windows): add option --packages-winget 2023-10-29 19:37:31 +08:00
李通洲 627d5fc659 JsonConfig: restructure some keys 2023-10-29 00:17:24 +08:00
李通洲 25849dc4bb Migration (Logo): fix --logo-color-num (v2) 2023-10-28 23:39:15 +08:00
李通洲 63032cd840 Doc: update help.txt 2023-10-28 23:02:28 +08:00
李通洲 2414246de9 Migration (Logo): fix --logo-color-num 2023-10-28 21:52:28 +08:00
李通洲 c52353b4b8 Vulkan: remove used GPU memory detection, which is unreliable
Ref: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_memory_budget.html#_description
2023-10-28 20:25:39 +08:00
李通洲 799628c083 GPU: guard nvml related code behind --allow-slow-operations 2023-10-28 17:23:49 +08:00
李通洲 38d5791d57 GPU: support memory, core count detection 2023-10-28 13:56:43 +08:00
李通洲 9d664e2b61 GPU (Linux): support driver version detection 2023-10-28 13:11:04 +08:00
李通洲 2eb21e3521 TerminalFont: fix memleaks 2023-10-28 13:00:45 +08:00
李通洲 bfe1265c44 Logo (Builtin): add azos
Ref: https://github.com/dylanaraps/neofetch/pull/2339
2023-10-27 22:57:16 +08:00
李通洲 dd3109cd89 GPU: better nvidia GPU temp detection 2023-10-27 21:16:03 +08:00
Carter Li 130d5a5202 Sound (macOS): fix no sound devices detected error on old macOS version 2023-10-27 17:35:28 +08:00
Carter Li cda4c62e9e macOS: fix building on old macOS version 2023-10-27 16:59:10 +08:00
李通洲 df245f32ec FFlist: add FF_LIST_GET
this macro can be safer to use than `ffListGet` because it detects wrong type convertion
2023-10-27 12:02:01 +08:00
李通洲 04409f4381 Wifi (macOS): better (or worse) support of security detection 2023-10-27 12:02:01 +08:00
李通洲 155e4a5b80 Doc: update doc for --migrate-config 2023-10-27 00:00:48 +08:00
李通洲 59a9209621 GPU: support Nvidia GPU temp detection 2023-10-27 00:00:19 +08:00
李通洲 cd5e14a834 LM (Linux): tidy 2023-10-26 23:27:40 +08:00
李通洲 e707cf8464 Migration: deprecate --gen-config conf 2023-10-26 16:34:38 +08:00
李通洲 8bdd410e97 Migration: support specifying config file path 2023-10-26 16:22:05 +08:00
李通洲 f45654620f Global: code refactor 2023-10-26 15:39:28 +08:00
李通洲 72d138f8c4 Migration (Modules): only generate objects when necessary 2023-10-26 14:28:47 +08:00
李通洲 6a0df7ae49 Migration: simplify json result 2023-10-26 14:06:47 +08:00
李通洲 23def0a1c7 Options (Library): add definitions only when used on the platform 2023-10-26 13:55:26 +08:00
李通洲 3236ef075d Migration (Library): support library options 2023-10-26 13:55:26 +08:00
李通洲 d00b301904 Migration (General): support general options 2023-10-26 13:55:26 +08:00
李通洲 6c82686283 Migration (Display): support display options 2023-10-26 13:55:21 +08:00
李通洲 399e2235d4 Options (Display): split code 2023-10-26 10:26:15 +08:00
李通洲 bd898e4006 Wifi (macOS): additional fix of Sonoma compatibility 2023-10-26 09:50:51 +08:00
李通洲 2c49dcceaf Options (Library): split code 2023-10-25 16:24:24 +08:00
李通洲 3c5b002414 Options (Modules): split code 2023-10-25 15:38:46 +08:00
李通洲 ca37206a49 Options (Logo): renaming symbols 2023-10-25 15:31:13 +08:00
李通洲 8a939e981c Options (General): symbol renaming to prevent from possible naming conflicts 2023-10-25 14:43:15 +08:00
李通洲 bed1b4cf0f Global: move general options to a new separate folder 2023-10-25 13:39:13 +08:00
李通洲 04c3a4ccf7 Logo: move logo options related code to a new folder 2023-10-25 10:44:34 +08:00
李通洲 f50368a949 Migration: support logo 2023-10-25 10:18:07 +08:00
李通洲 4e018dbf26 JsonConfig: code refactor 2023-10-25 09:13:04 +08:00
李通洲 fa02217ff4 Doc: update changelog 2023-10-25 09:03:44 +08:00
Martin Valba 22080d36b0 Add Evolinx distro banner (#596)
* Add Evolinx banner

* Removed accidental local bad save
2023-10-24 22:23:33 +08:00
westpain 3303f4e1ce Add cycledream logo (#595) 2023-10-24 21:15:56 +08:00
李通洲 11d03ad59e TerminalFont: support st 2023-10-24 16:48:22 +08:00
李通洲 504f1533c2 Terminal: support st version detection 2023-10-24 15:57:40 +08:00
李通洲 bf1d1cbac5 Terminal: support urxvt version detection 2023-10-24 15:56:43 +08:00
李通洲 94119d1674 OpenGL (Linux): fix build 2023-10-24 15:17:27 +08:00
李通洲 f4a263df01 Migration: finish modules support 2023-10-24 14:41:29 +08:00
李通洲 533231825c Terminal (Linux): detect tmux: server as tmux 2023-10-24 10:20:41 +08:00
李通洲 40e2787d94 Revert "Terminal (Linux): better support for tmux"
This reverts commit 281af9c86f.
2023-10-24 10:09:43 +08:00
李通洲 281af9c86f Terminal (Linux): better support for tmux 2023-10-23 23:38:18 +08:00
matoro fc0db8c291 Host (Linux): devicetree path for OBP hosts (#591)
At least SPARC devices have their model name in this devicetree node
and do not have a "model" node.  Possibly also POWER Macs, do not have
one to test though.
2023-10-23 23:37:37 +08:00
李通洲 48d2dbad34 Battery (Linux): fix build 2023-10-23 18:42:40 +08:00
李通洲 be2af8aeaf Migration: support bluetooth and board 2023-10-23 16:34:33 +08:00
李通洲 a7621a7301 Break: remove redundant code 2023-10-23 16:33:25 +08:00
李通洲 ec87790e4f Global: init support for JSON config file migration (WIP) 2023-10-23 16:17:07 +08:00
李通洲 44632e9bf6 Global: don't expose internal functions 2023-10-23 13:32:40 +08:00
李通洲 824ada49b6 Global: :%s/generateJson/generateJsonResult/g 2023-10-23 13:32:39 +08:00
李通洲 e7938216ba Global: :%s/ffGenerate\w+Json/$0Result/g 2023-10-23 13:32:39 +08:00
matoro 40d6d0b7b5 CPU (Linux): quirks for MIPS platforms (#590)
CPU name is in "cpu model" field on MIPS.  Also, /proc/cpuinfo contains
an "isa" field, but rather than being a single string like RISC-V it is
instead a space-separated list of every ISA flavor that the chip is
compatible with.  Since these are mostly incremental, just make the
cpuISA value set to the last one.

Before:
```
$ fastfetch --structure "cpu" --logo none
CPU: mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2 (16)
```

After:
```
$ fastfetch --structure "cpu" --logo none
CPU: Cavium Octeon II V0.10 mips64r2 (16)
```
2023-10-22 22:09:43 -05:00
李通洲 3f4d4c8eea GPU: add more vendors 2023-10-21 17:36:13 +08:00
李通洲 e2fe94d4e4 DisplayServer (Android): tidy 2023-10-21 15:44:38 +08:00
李通洲 debb5d8ad1 Display: don't print display type twice 2023-10-21 15:44:08 +08:00
李通洲 f61794ea70 GPU (Windows): better GPU memory and type detection 2023-10-18 10:52:29 +08:00
李通洲 d15a977431 Logo (Builtin): add Black Mesa
Fix #586
2023-10-17 23:46:38 +08:00
Carter Li ef5268f78d Merge pull request #584 from fastfetch-cli/dev
Release v2.1.2
2023-10-15 04:09:03 -05:00
李通洲 7362808d5d Brightness (Linux): fix compatibility for ddcutil 2.0
3rd try
2023-10-15 13:46:58 +08:00
李通洲 27cfec68ed Brightness (Linux): fix compatibility for ddcutil 2.0 2023-10-15 12:27:38 +08:00
李通洲 ea85f40682 Release v2.1.2 2023-10-15 10:52:05 +08:00
李通洲 0cc38c20be CPUUsage (FreeBSD): silence compiler warnings 2023-10-15 10:52:05 +08:00
李通洲 d29931a91a Brightness (Linux): fix compatibility for ddcutil 2.0
Ref: https://github.com/fastfetch-cli/fastfetch/issues/576#issuecomment-1763184172
2023-10-15 10:52:05 +08:00
李通洲 17c007348b Icons (Windows): fix detection 2023-10-14 21:55:55 +08:00
Carter Li 33953a0d18 Merge pull request #583 from fastfetch-cli/dev
Release v2.1.1
2023-10-14 06:08:00 -05:00
李通洲 98e8e599a6 Release v2.1.1 2023-10-14 18:24:58 +08:00
李通洲 5e19838713 Doc: update changelog 2023-10-14 18:19:10 +08:00
李通洲 501803c873 Logo (Builtin): add Xenia
https://github.com/hykilpikonna/hyfetch/issues/197
2023-10-14 18:15:04 +08:00
李通洲 e9c2a43de1 Brightness: add --brightness-ddcci-sleep to set the sleep times (in ms) when sending DDC/CI requests
Fix #580
2023-10-14 10:04:08 +08:00
李通洲 af94596202 Revert "Brightness (Linux): allow specifying busno for ddcutil"
This doesn't seem to improve much performance, but increase code
complexity a lot

This reverts commit 42e87b498c.
2023-10-14 09:35:40 +08:00
李通洲 42e87b498c Brightness (Linux): allow specifying busno for ddcutil
Ref: #580
2023-10-14 01:38:02 +08:00
李通洲 839ff311de Wifi (macOS): work around #581 2023-10-13 16:47:45 +08:00
李通洲 ebab281471 Processes (Linux): fix implementation
`sysinfo.procs` reports number of all running threads, instead of processes
2023-10-11 21:10:47 +08:00
李通洲 582788645d Doc: add information about how to make Termux API actually work 2023-10-11 16:32:20 +08:00
李通洲 643fed7d1c Doc: metion bug #581 2023-10-11 16:31:47 +08:00
李通洲 076324e60e Wifi (macOS): remove undesired code 2023-10-11 15:23:21 +08:00
李通洲 1fe92738d8 macOS: embed Info.plist 2023-10-11 15:17:14 +08:00
李通洲 e319be19de Wifi (macOS): print <unknown ssid> when we can't get SSID
SSID is not available after Sonoma. According to the doc: SSID information is not available unless Location Services is enabled and the user has authorized the calling app to use location services.
2023-10-11 14:48:48 +08:00
李通洲 ab8448ee47 DiskIO (Windows): fix device name detection 2023-10-10 21:51:15 +08:00
李通洲 5493f418ed Users: fix crashing on Windows; rename tty to more common name sessionName 2023-10-10 20:21:11 +08:00
李通洲 4e75fa958d Logo (Builtin): add EndeavourSmall
Ref: https://github.com/dylanaraps/neofetch/pull/2391
2023-10-10 19:21:05 +08:00
李通洲 0847432dd9 CPUUsage: rename cpuusage-display-type to separate 2023-10-10 19:02:42 +08:00
李通洲 e297144fe2 CPUUsage: fix multi core data detection 2023-10-10 18:46:59 +08:00
李通洲 42cf88be9d CPUUsage: support display value per core 2023-10-10 16:24:44 +08:00
李通洲 6b008ed93b CPUUsage (FreeBSD): count cpu cores separately 2023-10-10 13:56:19 +08:00
李通洲 c96d21c7c0 CPUUsage (Linux): count cpu cores separately 2023-10-10 13:41:08 +08:00
李通洲 2feb53149a Revert "CpuUsage (apple): simplify implementation"
This reverts commit cabd36d078.
2023-10-10 13:41:08 +08:00
李通洲 e7df94495c Temp (FreeBSD): improve CPU temp detection 2023-10-10 13:41:08 +08:00
李通洲 42f6d029b0 Doc: update JSON schema; make it more IDE friendly 2023-10-09 20:27:40 +08:00
李通洲 ccbb252466 DiskIO: update doc and json schema 2023-10-09 19:24:25 +08:00
李通洲 d16bdb30b9 DiskIO: update formatting help messages; update json keys 2023-10-09 16:40:47 +08:00
李通洲 8fa6aee571 Disk: move physicalType to module DiskIO
Physical type applies to physical disks, not partitions
2023-10-09 16:32:31 +08:00
李通洲 4194e56912 DiskIO (Windows): better name detection for Github Action 2023-10-09 15:39:34 +08:00
李通洲 a0343d6bf7 CI: run --format json 2023-10-09 14:56:28 +08:00
李通洲 44b417deca DiskIO (FreeBSD): skip /dev/pass* 2023-10-09 14:26:51 +08:00
李通洲 5ccd196ae4 DiskIO: print devPath 2023-10-09 14:24:29 +08:00
李通洲 b76d6e9faa DiskIO (FreeBSD): add support 2023-10-09 14:20:40 +08:00
李通洲 2d2e0ddc6d Libc (FreeBSD): detect FBSD version 2023-10-09 13:28:30 +08:00
李通洲 430da1578d Libc (macOS): detect libSystem version 2023-10-09 10:43:58 +08:00
李通洲 1188db9475 CMake: simplify musl version detection 2023-10-09 10:43:40 +08:00
李通洲 685676bd0f CMake: don't hardcode system arch 2023-10-09 09:05:11 +08:00
李通洲 fa46dce0e1 CMake: detect uclibc and musl version 2023-10-08 21:03:10 +08:00
李通洲 2e60f34cd8 DiskIO: add to presets/all 2023-10-08 21:02:48 +08:00
李通洲 dc50e24a29 Doc: update changelog and readme 2023-10-08 21:02:31 +08:00
Jami Kettunen 1f23e93951 Logo: add Chimera Linux
Ref: https://github.com/chimera-linux/cports/blob/master/contrib/neofetch/patches/chimera.patch
2023-10-08 19:26:11 +08:00
李通洲 8df6409cb1 DiskIO (Windows): better device name detection 2023-10-08 16:46:53 +08:00
李通洲 5c5c66d960 DiskIO: fix segfault... 2023-10-08 16:38:50 +08:00
李通洲 0b0e286b9c DiskIO: support --diskio-name-prefix 2023-10-08 16:30:09 +08:00
李通洲 b2130477ae DiskIO (macOS): add support 2023-10-08 16:29:53 +08:00
李通洲 085d0924db Brightness (Linux): try improving compatibility of ddcutil 2.0
ddcutil 2.0 increases SONAME version to `libddcutil.so.5`. More testing needed

Ref: #576
2023-10-08 10:34:01 +08:00
李通洲 78249bf4f7 CPU: add new option --cpu-freq-ndigits
Fix #578
2023-10-08 10:10:06 +08:00
李通洲 4c9d9f6223 TerminalFont (Linux): fix typo 2023-10-08 09:56:45 +08:00
李通洲 d7649d9f8f DiskIO: fix building 2023-10-08 09:51:51 +08:00
李通洲 49e2acd15e Printing: fix --help *-format 2023-10-08 09:51:51 +08:00
李通洲 e4a6bf17e4 Terminal: support kgx (gnome console)
Fix #577
2023-10-08 09:51:32 +08:00
李通洲 276e22f6b0 DiskIO: init module 2023-10-07 23:56:15 +08:00
李通洲 b1d63e03d8 NetIO: fix --help netio-format 2023-10-07 22:58:50 +08:00
李通洲 55f0f75c95 Packages (Linux): print opkg in JSON format 2023-10-07 17:26:57 +08:00
李通洲 fe4eb564e1 NetIO: add missing #pragma once 2023-10-07 16:12:37 +08:00
李通洲 90ea096ca3 macOS: don't keep variable matchDict 2023-10-07 15:51:05 +08:00
李通洲 3077f885d8 Sound (macOS): ignore input devices 2023-10-07 15:45:14 +08:00
李通洲 41551ef200 Sound: fix typo 2023-10-07 15:15:39 +08:00
李通洲 4c96d0453e TerminalShell (Linux): add ash as a known shell 2023-10-07 15:15:24 +08:00
李通洲 d7ef7bc078 Doc: update changelog 2023-10-07 15:14:16 +08:00
李通洲 c77a758741 Packages (Linux): support opkg
Fix #574
2023-10-07 14:02:16 +08:00
李通洲 12208b2c7c Global: improve support of --help *-format
Also fix some bugs found when refactoring
2023-10-07 13:40:40 +08:00
李通洲 23d2cc3fdc Version: print libc version used when compiling 2023-10-05 22:23:22 +08:00
Md Rasel Hossain 1dfa0315db Fix several --help command related issues (#572)
* Help: fix wrong output for irrelevant commands

* Help: fix `module-format` related issues

* Help: remove unnecessary code
2023-10-05 19:59:24 +08:00
李通洲 f78f97a726 Revert "DisplayServer (Linux): add debug log for #568"
This reverts commit 1a4eb25194.
2023-10-04 16:28:54 +08:00
Carter Li 9972c61bbe Sound (macOS): support non-controllable devices 2023-10-04 14:59:13 +08:00
Carter Li 8795d99f79 Brightness: add DDC/CI support for Intel
Doesn't work for me. Need more testing
2023-10-04 14:41:06 +08:00
Carter Li f8aafb7ce4 Monitor (macOS): better intel platform support 2023-10-04 00:30:35 +08:00
Carter Li 27581d92b5 Disk (macOS): detect physical type 2023-10-04 00:30:35 +08:00
Carter Li 4a89b92185 Disk: allow custiomize disk key with mountFrom 2023-10-04 00:30:35 +08:00
李通洲 1a4eb25194 DisplayServer (Linux): add debug log for #568 2023-10-04 00:30:35 +08:00
李通洲 3eb9acea2e Doc: update changelog 2023-10-03 17:04:08 +08:00
李通洲 be860064c5 Users (Windows): fix crashing caused by uninitialized strings 2023-10-03 17:01:57 +08:00
李通洲 1985552636 Disk (Windows): fix crashing on Windows 7 VM 2023-10-03 16:50:57 +08:00
李通洲 985264d485 Fastfetch: add Directx Headers to --list-features 2023-10-02 23:19:44 +08:00
312 changed files with 18969 additions and 4217 deletions
+51 -21
View File
@@ -28,6 +28,9 @@ jobs:
- 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 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 rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
@@ -35,7 +38,7 @@ jobs:
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_JSONC=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} .
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 }} .
- name: build project
run: cmake --build .
@@ -43,11 +46,17 @@ jobs:
- name: run tests
run: ctest
- name: run fastfetch --list-features
run: ./fastfetch --list-features
- name: run fastfetch
run: ./fastfetch --stat --show-errors --no-buffer --load-config presets/all
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: ./flashfetch
run: time ./flashfetch
linux:
name: Linux
@@ -61,19 +70,27 @@ jobs:
- 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 libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-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 --ignore-dependencies
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
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
run: cmake --build . --target package --verbose
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
@@ -84,6 +101,9 @@ jobs:
- name: run fastfetch
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
@@ -113,8 +133,13 @@ jobs:
- name: checkout repository
uses: actions/checkout@v4
- name: uname -a
run: uname -a
- name: install required packages
run: brew install vulkan-loader molten-vk imagemagick chafa
run: |
brew update
brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -125,7 +150,7 @@ jobs:
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
- name: build project
run: cmake --build . --target package
run: cmake --build . --target package --verbose
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
@@ -136,6 +161,9 @@ jobs:
- name: run fastfetch
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
@@ -162,15 +190,19 @@ jobs:
uses: actions/checkout@v4
- name: run VM
uses: vmactions/freebsd-vm@v0
uses: cross-platform-actions/action@v0.21.1
with:
prepare: |
pkg install -y cmake git pkgconf pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
operating_system: freebsd
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 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package
cmake --build . --target package --verbose
./fastfetch --list-features
time ./fastfetch -c presets/ci
time ./fastfetch -c presets/ci --format json
time ./flashfetch
ldd fastfetch
ctest
@@ -204,19 +236,11 @@ jobs:
- name: print msys version
run: uname -a
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c, cpp
- name: configure project
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build .
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
run: cmake --build . --verbose
- name: copy necessary dlls
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
@@ -227,6 +251,9 @@ jobs:
- name: run fastfetch
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
@@ -280,7 +307,7 @@ 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 .
run: cmake --build . --verbose
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
@@ -291,6 +318,9 @@ jobs:
- name: run fastfetch
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
+109
View File
@@ -1,3 +1,112 @@
# 2.2.2
Changes:
* `--percent-type` now defaults to 9 (colored percentage numbers)
* `fastfetch` now prints LocalIp module by default
Features:
* LocalIP module now prints netmask in CIDR format for IPv4 (LocalIP)
* Bios module now detects system firmware type (Bios)
* Improve detection of `Battery`
* Detect cycle count on supported platforms
* Detect temperature on Linux when supported
* Status detection on macOS has been adjusted to be consistant with other platforms
* Linux binaries are built with imagemagick7 support
Bugfixes:
* Fix unitialized variables (#609)
* Fix spelling of `--preserve-aspect-ratio` (#614)
Logos:
* Update NixOS_small
# 2.2.1
Hotfix release for #606
Bugfixes:
* Fix broken presets due to the breaking changes introduced in 2.2.0
Features:
* Pretty print `fastfetch --help`
# 2.2.0
This release introduces a new option `--migrate-config`, which migrates old flag based config file to new JSONC format
Changes:
* `--pipe` and `--stat` are moved from `general` options to `display` options. This affects cjson configuration.
* Display keys `percent*` and `size*` in JSON config are restructured. e.g. `{ "sizeNdigits": 1 }` is now `{ "size": { "ndigits": 1 } }`
* With the introduction of `--migrate-config`, the old flag based config file is deprecated, and will be removed in 3.0.0 (next major version)
* Support of `--gen-config conf` is deprecated accordingly, and will be removed in 2.3.0 (next minor version)
* The global flag `--allow-slow-operations` is splitted into some explicit flags in differnet modules
* `--packages-winget`: control whether `winget` packages count should be detected. Note it's a very slow operation, please enable it with caution.
* `--chassis-use-wmi`: control whether `WMI` query should be used to detect chassis type, which detects more information, but slower. This flag only affects `--chassis-format` and `--format json`.
* `--battery-use-setup-api`: control whether `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower.
* `--wm-detect-plugin`: control whether WM plugins should be detected. Note it's implemented with global processes enumeration and can report false results.
* `--de-slow-version-detection`: control DE version should be detected with slow operations. It's usually not necessary and only provided as a backup.
* `--localip-default-route-only` and `--netio-default-route-only` defaults to true to avoid large number of results
Features:
* Quirks for MIPS platforms (CPU, Linux)
* Use devicetree path for OBP hosts (Host, Linux)
* Detect `tmux: server` as tmux (Terminal, Linux)
* Support urxvt version detection (Terminal, Linux)
* Support st version detection (Terminal, Linux)
* Support st terminal font detection (TerminalFont, Linux)
* Support xfce4-terminal 1.1.0+ terminal font detection (TerminalFont, Linux)
* Add option `--migrate-config <?target-file-path>`
* Support Nvidia GPU temp and cuda core count detection via nvml. Use `--gpu-use-nvml` to enable it (GPU)
* Try supporting Wifi authentication type detection in macOS Sonoma. Please file a feature request if you get `to be supported (num)` with result of `/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | grep auth` (Wifi, macOS)
Bugfixes:
* Better GPU memory and type detection (GPU, Windows)
* Don't print display type twice (Display)
* Detect BSSID instead of Wifi MAC address to align with other platforms (Wifi, macOS)
* Remove support of used GPU memory detection, which is not reliable and only supported with `--gpu-force-vulkan`. (GPU)
* Fix flag `--brightness-ddcci-sleep` (Brightness, Linux)
* Fix hanging if a child process prints to both stdout and stderr (Linux)
Logos:
* Add Black Mesa
* Add cycledream
* Add Evolinx
* Add azos
* Add Interix
# 2.1.2
Bugfixes:
* Fix icon detection on Windows. It shows enabled system icons in desktop (`This PC`, `Recycle Bin`, etc) (Icon, Windows)
* Fix compatibility with ddcutil 2.0 (Brightness, Linux)
* Fix a compile warning (CPUUsage, FreeBSD)
# 2.1.1
Features:
* Support opkg (Packages, Linux)
* Support GNOME Console terminal version and font detection (Terminal, Linux)
* Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU)
* New module to detect physical disk I/O usage (DiskIO)
* Add `--cpuusage-separate` to display CPU usage per CPU logical core
* Add `--brightness-ddcci-sleep` to set the sleep times (in ms) when sending DDC/CI requests (Brightness, #580)
Bugfixes:
* Fix possible crashes on Windows 7 (Disk, Windows)
* Fix possible crashes caused by uninitialized strings (Users, Windows)
* Improve support of `--help *-format` and several bugs are found and fixed
* Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS)
* Fix implementation processes counting (Processes, Linux)
* Work around a issue that SSID cannot be detected on macOS Sonoma (Wifi, macOS)
Logo:
* Add Chimera Linux
* Add EndeavourSmall
* Add Xenia
* Add MainsailOS
* Fix phyOS
# 2.1.0
This release introduces a new output format: JSON result
+80 -16
View File
@@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.1.0
VERSION 2.2.2
LANGUAGES C
DESCRIPTION "Fast system information tool"
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
)
@@ -70,8 +70,9 @@ 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)
cmake_dependent_option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
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
@@ -97,7 +98,7 @@ endif()
set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=return-type")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion")
if(WIN32 OR ENABLE_DIRECTX_HEADERS)
enable_language(CXX)
@@ -116,7 +117,8 @@ if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
if(NOT WIN32 AND NOT APPLE)
if(ENABLE_ASAN)
message(STATUS "Address sanitizer enabled (DEBUG only)")
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
@@ -222,6 +224,9 @@ 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)
if(APPLE)
configure_file(src/util/apple/Info.plist.in Info.plist @ONLY)
endif()
####################
# Ascii image data #
@@ -229,14 +234,11 @@ configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
function(fastfetch_load_raw_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
string(JSON TEMP SET "{}" "${TEMP}" "0") # Encode raw strings using JSON_SET
string(REGEX REPLACE "^\\{[ \t\r\n]*" "" TEMP "${TEMP}") # Remove JSON braces
string(REGEX REPLACE "[ \t\r\n]*:[ \t\r\n]*0[ \t\r\n]*\\}$" "" TEMP "${TEMP}") # Remove trailing ` : 0 }`
if(NOT "${TEMP}" MATCHES "^\"[^\n]*\"")
message(FATAL_ERROR "Internal error: unexpected output: '${TEMP}'")
endif()
set(${OUTVAR} "${TEMP}" PARENT_SCOPE)
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
string(REPLACE "\\" "\\\\" TEMP "${TEMP}") # Escape backslashes
string(REPLACE "\n" "\\n" TEMP "${TEMP}") # Replace newlines with \n
string(REPLACE "\"" "\\\"" TEMP "${TEMP}") # Replace quotes with \"
set(${OUTVAR} "\"${TEMP}\"" PARENT_SCOPE)
endfunction(fastfetch_load_raw_text)
file(GLOB LOGO_FILES "src/logo/ascii/*.txt")
@@ -273,6 +275,7 @@ set(LIBFASTFETCH_SRC
src/detection/cpu/cpu.c
src/detection/cpuusage/cpuusage.c
src/detection/disk/disk.c
src/detection/diskio/diskio.c
src/detection/displayserver/displayserver.c
src/detection/font/font.c
src/detection/gpu/gpu.c
@@ -293,7 +296,6 @@ set(LIBFASTFETCH_SRC
src/logo/image/im7.c
src/logo/image/image.c
src/logo/logo.c
src/logo/option.c
src/modules/battery/battery.c
src/modules/bios/bios.c
src/modules/bluetooth/bluetooth.c
@@ -310,6 +312,7 @@ set(LIBFASTFETCH_SRC
src/modules/datetime/datetime.c
src/modules/de/de.c
src/modules/disk/disk.c
src/modules/diskio/diskio.c
src/modules/font/font.c
src/modules/gpu/gpu.c
src/modules/host/host.c
@@ -350,6 +353,11 @@ set(LIBFASTFETCH_SRC
src/modules/wifi/wifi.c
src/modules/wm/wm.c
src/modules/wmtheme/wmtheme.c
src/options/display.c
src/options/modules.c
src/options/logo.c
src/options/general.c
src/options/library.c
src/util/edidHelper.c
src/util/FFlist.c
src/util/FFstrbuf.c
@@ -375,6 +383,7 @@ if(LINUX)
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/disk/disk_linux.c
src/detection/diskio/diskio_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
@@ -382,9 +391,11 @@ 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/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/localip/localip_linux.c
src/detection/gamepad/gamepad_linux.c
@@ -409,6 +420,8 @@ if(LINUX)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_linux.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/util/platform/FFPlatform_unix.c
)
@@ -428,11 +441,13 @@ elseif(ANDROID)
src/detection/cursor/cursor_nosupport.c
src/detection/cpuusage/cpuusage_linux.c
src/detection/disk/disk_linux.c
src/detection/diskio/diskio_linux.c
src/detection/displayserver/displayserver_android.c
src/detection/font/font_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/host/host_android.c
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_android.c
src/detection/lm/lm_nosupport.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
@@ -456,6 +471,8 @@ elseif(ANDROID)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_nosupport.c
src/detection/wifi/wifi_android.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c
src/util/platform/FFPlatform_unix.c
)
@@ -477,6 +494,7 @@ elseif(BSD)
src/detection/cpuusage/cpuusage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/disk/disk_bsd.c
src/detection/diskio/diskio_bsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
@@ -484,10 +502,12 @@ elseif(BSD)
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/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/localip/localip_linux.c
src/detection/gamepad/gamepad_bsd.c
src/detection/media/media_linux.c
@@ -511,6 +531,8 @@ elseif(BSD)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_bsd.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/util/platform/FFPlatform_unix.c
)
@@ -531,12 +553,14 @@ elseif(APPLE)
src/detection/cpuusage/cpuusage_apple.c
src/detection/cursor/cursor_apple.m
src/detection/disk/disk_bsd.c
src/detection/diskio/diskio_apple.c
src/detection/displayserver/displayserver_apple.c
src/detection/font/font_apple.m
src/detection/gpu/gpu_apple.c
src/detection/host/host_apple.c
src/detection/lm/lm_nosupport.c
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_apple.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_apple.c
src/detection/media/media_apple.m
@@ -559,6 +583,8 @@ elseif(APPLE)
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.c
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/util/apple/cf_helpers.c
src/util/apple/osascript.m
@@ -580,11 +606,14 @@ elseif(WIN32)
src/detection/cpuusage/cpuusage_windows.c
src/detection/cursor/cursor_windows.c
src/detection/disk/disk_windows.c
src/detection/diskio/diskio_windows.c
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/host/host_windows.c
src/detection/icons/icons_windows.c
src/detection/libc/libc_windows.cpp
src/detection/lm/lm_nosupport.c
src/detection/localip/localip_windows.c
src/detection/gamepad/gamepad_windows.c
@@ -608,6 +637,8 @@ elseif(WIN32)
src/detection/users/users_windows.c
src/detection/wallpaper/wallpaper_windows.c
src/detection/wifi/wifi_windows.c
src/detection/wm/wm_windows.cpp
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_windows.c
src/util/windows/getline.c
src/util/windows/com.cpp
@@ -651,6 +682,28 @@ if(yyjson_FOUND)
target_link_libraries(libfastfetch PRIVATE yyjson)
endif()
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
ERROR_VARIABLE LD_MUSL_RESULT)
if("${LD_MUSL_RESULT}" MATCHES "Version ([0-9]+\\.[0-9]+\\.[0-9]+)")
target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(APPLE AND EXISTS "/usr/bin/otool")
execute_process(COMMAND /usr/bin/otool -L /usr/bin/otool
OUTPUT_VARIABLE OTOOL_OTOOL_RESULT)
if("${OTOOL_OTOOL_RESULT}" MATCHES "libSystem\\.B\\.dylib \\(.*current version ([0-9]+\\.[0-9]+\\.[0-9]+)\\)")
target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(BSD AND EXISTS "/usr/local/bin/objdump")
execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[^ )]*' -o | sort -Vru | head -1"
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1)
if(WIN32)
target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1)
@@ -831,8 +884,11 @@ elseif(APPLE)
PRIVATE "-framework OpenCL"
PRIVATE "-framework SystemConfiguration"
PRIVATE "-weak_framework CoreDisplay"
PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks"
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
PRIVATE "-F /System/Library/PrivateFrameworks"
PRIVATE "-weak_framework DisplayServices"
PRIVATE "-weak_framework MediaRemote"
PRIVATE "-weak_framework Apple80211"
)
elseif(WIN32)
target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601)
@@ -856,6 +912,7 @@ elseif(BSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "usbhid"
PRIVATE "devstat"
)
elseif(ANDROID)
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
@@ -922,6 +979,13 @@ if(WIN32)
target_sources(flashfetch
PRIVATE src/util/windows/version.rc
)
elseif(APPLE)
target_link_options(fastfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
target_link_options(flashfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
endif()
###################
+25 -119
View File
@@ -23,147 +23,53 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for
There are [screenshots on different platforms](https://github.com/fastfetch-cli/fastfetch/wiki)
## Customization
## Installation
With customization and speed being two competing goals, this project actually builds two executables:
### Linux
* The main one is `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent by modifying `$XDG_CONFIG_HOME/fastfetch/config.conf`. Use `fastfetch --gen-config conf` to generate one. To view the available options, run `fastfetch --help`.
* The second executable is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `sudo apt install fastfetch-<version>-Linux.deb`
* Arch Linux: `sudo pacman -S fastfetch`
* Fedora: `sudo dnf install fastfetch`
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
Currently, the performance difference is measurable, but too small to be recognizable by humans. But with more options planned, the leap will get bigger over time and on slow machines this might actually make a difference.
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
### Customization with new JSONC format
A new, structure based, and user-friendly config file format was introduced in v2.0.0. This format is based on [JSONC](https://jsonc.org/). [See more details in Wiki](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration)
## Dependencies
Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl`, `libm` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most Linux distributions.
The following libraries are used if present at runtime:
### Linux and FreeBSD
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
* [`libxcb-randr`](https://xcb.freedesktop.org/),
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
[`libxcb`](https://xcb.freedesktop.org/),
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better display detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
* [`libwayland-client`](https://wayland.freedesktop.org/): Better display performance and output in wayland sessions. Supports different refresh rates per monitor.
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Bluetooth, Player & Media detection.
* [`libEGL`](https://www.khronos.org/registry/EGL/),
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection.
* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection.
* [`libddcutil`](https://github.com/rockowitz/ddcutil): Used for brightness detection of external displays
* [`DirectX-Headers`](https://github.com/microsoft/DirectX-Headers): Used for GPU detection in WSL
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging)
### macOS
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
* [`DisplayServices`](https://developer.apple.com/forums/thread/666383#663154022): Need for screen brightness detection. It's a private framework provided by newer macOS system.
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
* [`libsqlite3`](https://www.sqlite.org/index.html): Used for fast wallpaper detection ( fallback to AppleScript )
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
`brew install fastfetch`
### Windows
* [`wlanapi`](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/): A system dll which isn't supported by Windows Server by default. Used for Wifi info detection.
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers)
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd)
`scoop install fastfetch`
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later.
You may also download it directly from [GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and extract the archive.
For the image logo, WezTerm with iterm image protocol is known to work, surprisingly.
### FreeBSD
### Android
`pkg install fastfetch`
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api)
* [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android.
### Android (Termux)
For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol.
`pkg install fastfetch`
## Support status
All categories not listed here should work without needing a specific implementation.
## Build from source
##### Available Modules
```
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme
```
See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
##### Builtin logos
## Usage
<!-- `Content of src/logo/builtin.c`.split('\n').map(x => x.trim()).filter(x => x.startsWith('// ')).map(x => x.slice(3)).filter(x => x != 'LAST').sort((a, b)=>a.toUpperCase().localeCompare(b.toUpperCase())).join(', ') -->
```
AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin
```
* Run it with default configuration: `fastfetch`
* Run it with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) and find what you interest: `fastfetch -c all.jsonc`
* Find all data that fastfetch detects: `fastfetch -s <module> --format json`
* Display help messages: `fastfetch --help`
* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --migrate-config`
Run `fastfetch --print-logos` to print them
## Customization
##### Package managers
```
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps
```
Fastfetch uses the JSONC (or JSON with comments) for configuration. [See Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration). There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `-c <filename>`. They may also serve as a good example for format arguments.
##### WM themes
```
DWM (Windows), KWin, Marco, Muffin, Mutter, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), XFWM
```
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
##### DE versions
```
Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
```
##### Terminal fonts
```
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake
```
## Building
fastfetch uses [`cmake`](https://cmake.org/) for building. [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is recommended for better library detection. The simplest steps to build the fastfetch and flashfetch binaries are:
```bash
mkdir -p build
cd build
cmake ..
cmake --build . --target fastfetch --target flashfetch
```
If the build process fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
### Building on Windows
Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested.
1. Install [MSYS2](https://www.msys2.org/#installation)
1. Open `MSYS2 / CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
1. Install dependencies
```bash
pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
```
Follow the building instructions of Linux next.
## Packaging
+528 -229
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:Version:Break:Colors
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:DiskIO:Version:Break:Colors
+1
View File
@@ -52,6 +52,7 @@
"gamepad",
"weather",
"netio",
"diskio",
"version",
"break",
"colors"
-1
View File
@@ -4,7 +4,6 @@
"type": "small"
},
"display": {
"percentType": 9,
"separator": "\u001b[31m-> "
},
"modules": [
+4 -3
View File
@@ -8,9 +8,10 @@
"color": {
"keys": "magenta"
},
"sizeNdigits": 0,
"sizeMaxPrefix": "MB",
"percentType": 9
"size": {
"ndigits": 0,
"maxPrefix": "MB"
}
},
"modules": [
{
-1
View File
@@ -4,7 +4,6 @@
"type": "small"
},
"display": {
"percentType": 6,
"keyWidth": 11,
"bar": {
"charElapsed": "=",
+10359
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
{
"home": "https://github.com/NVIDIA/nvidia-settings/blob/main/src/nvml.h",
"license": "Embed in source",
"version": "545.23.06",
"author": "NVIDIA Corporation"
}
+27 -21
View File
@@ -6,15 +6,17 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
{
assert(green <= 100 && yellow <= 100 && red <= 100);
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * instance.config.barWidth + 0.5);
uint32_t blocksGreen = (uint32_t) (green / 100.0 * instance.config.barWidth + 0.5);
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * instance.config.barWidth + 0.5);
uint32_t blocksRed = (uint32_t) (red / 100.0 * instance.config.barWidth + 0.5);
assert(blocksPercent <= instance.config.barWidth);
const FFOptionsDisplay* options = &instance.config.display;
if(instance.config.barBorder)
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(!instance.config.pipe)
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
else
ffStrbufAppendS(buffer, "[ ");
@@ -22,7 +24,7 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
for (uint32_t i = 0; i < blocksPercent; ++i)
{
if(!instance.config.pipe)
if(!options->pipe)
{
if (i == blocksGreen)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
@@ -31,26 +33,26 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
else if (i == blocksRed)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
ffStrbufAppend(buffer, &instance.config.barCharElapsed);
ffStrbufAppend(buffer, &options->barCharElapsed);
}
if (blocksPercent < instance.config.barWidth)
if (blocksPercent < options->barWidth)
{
if(!instance.config.pipe)
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
for (uint32_t i = blocksPercent; i < instance.config.barWidth; ++i)
ffStrbufAppend(buffer, &instance.config.barCharTotal);
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
ffStrbufAppend(buffer, &options->barCharTotal);
}
if(instance.config.barBorder)
if(options->barBorder)
{
if(!instance.config.pipe)
if(!options->pipe)
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
else
ffStrbufAppendS(buffer, " ]");
}
if(!instance.config.pipe)
if(!options->pipe)
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
@@ -67,14 +69,18 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
{
assert(green <= 100 && yellow <= 100);
bool colored = !!(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
const FFOptionsDisplay* options = &instance.config.display;
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
if (colored && !instance.config.pipe)
if (colored && !options->pipe)
{
if(green < yellow)
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");
@@ -93,9 +99,9 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
}
}
ffStrbufAppendF(buffer, "%.*f%%", instance.config.percentNdigits, percent);
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
if (colored && !instance.config.pipe)
if (colored && !options->pipe)
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
+95 -51
View File
@@ -1,6 +1,7 @@
#include "commandoption.h"
#include "common/printing.h"
#include "common/time.h"
#include "common/jsonconfig.h"
#include "fastfetch_datatext.h"
#include "modules/modules.h"
#include "util/stringUtils.h"
@@ -8,37 +9,6 @@
#include <ctype.h>
#include <inttypes.h>
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
{
yyjson_mut_doc* doc = instance.state.resultDoc;
if (__builtin_expect(!doc, true)) return NULL;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJson)
baseInfo->generateJson(baseInfo, doc, module);
else
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
return module;
}
bool ffParseModuleCommand(const char* type)
{
if(!isalpha(type[0])) return false;
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules)
{
FFModuleBaseInfo* baseInfo = *modules;
if (ffStrEqualsIgnCase(type, baseInfo->name))
{
if (!genJson(baseInfo))
baseInfo->printModule(baseInfo);
return true;
}
}
return false;
}
bool ffParseModuleOptions(const char* key, const char* value)
{
if (!ffStrStartsWith(key, "--") || !isalpha(key[2])) return false;
@@ -53,6 +23,7 @@ bool ffParseModuleOptions(const char* key, const char* value)
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);
@@ -60,20 +31,58 @@ void ffPrepareCommandOption(FFdata* data)
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
ffPrepareCPUUsage();
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
ffPrepareNetIO(&instance.config.netIo);
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
ffPrepareDiskIO(&options->diskIo);
if(instance.config.multithreading)
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
ffPrepareNetIO(&options->netIo);
if(instance.config.general.multithreading)
{
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
ffPreparePublicIp(&instance.config.publicIP);
ffPreparePublicIp(&options->publicIP);
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
ffPrepareWeather(&instance.config.weather);
ffPrepareWeather(&options->weather);
}
}
static void parseStructureCommand(const char* line, FFlist* customValues)
static void genJsonConfig(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
{
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
if (!modules)
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
yyjson_mut_val* module = yyjson_mut_obj(doc);
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&type);
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
if (baseInfo->generateJsonConfig)
baseInfo->generateJsonConfig(baseInfo, doc, module);
if (yyjson_mut_obj_size(module) > 1)
yyjson_mut_arr_add_val(modules, module);
else
yyjson_mut_arr_add_strbuf(doc, modules, &type);
}
static void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
{
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJsonResult)
baseInfo->generateJsonResult(baseInfo, doc, module);
else
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
}
static void parseStructureCommand(
const char* line,
FFlist* customValues,
void (*fn)(FFModuleBaseInfo *baseInfo, yyjson_mut_doc* jsonDoc),
yyjson_mut_doc* jsonDoc
)
{
// handle `--set` and `--set-keyless`
FF_LIST_FOR_EACH(FFCustomValue, customValue, *customValues)
@@ -85,19 +94,35 @@ static void parseStructureCommand(const char* line, FFlist* customValues)
if (customValue->printKey)
ffStrbufAppend(&options.moduleArgs.key, &customValue->key);
ffStrbufAppend(&options.moduleArgs.outputFormat, &customValue->value);
ffPrintCustom(&options);
if (__builtin_expect(jsonDoc != NULL, false))
fn((FFModuleBaseInfo*) &options, jsonDoc);
else
ffPrintCustom(&options);
return;
}
}
if(!ffParseModuleCommand(line))
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
if(isalpha(line[0]))
{
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
{
FFModuleBaseInfo* baseInfo = *modules;
if (ffStrEqualsIgnCase(line, baseInfo->name))
{
if (__builtin_expect(jsonDoc != NULL, false))
fn(baseInfo, jsonDoc);
else
baseInfo->printModule(baseInfo);
return;
}
}
}
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
}
void ffPrintCommandOption(FFdata* data)
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
{
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
@@ -106,25 +131,25 @@ void ffPrintCommandOption(FFdata* data)
data->structure.chars[colonIndex] = '\0';
uint64_t ms = 0;
if(instance.config.stat)
if(instance.config.display.stat)
ms = ffTimeGetTick();
parseStructureCommand(data->structure.chars + startIndex, &data->customValues);
parseStructureCommand(data->structure.chars + startIndex, &data->customValues, genJsonResult, jsonDoc);
if(instance.config.stat)
if(instance.config.display.stat)
{
ms = ffTimeGetTick() - ms;
if (resultDoc)
if (jsonDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
}
else
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
if(instance.config.pipe)
if(instance.config.display.pipe)
puts(str);
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
@@ -132,9 +157,28 @@ void ffPrintCommandOption(FFdata* data)
}
#if defined(_WIN32)
if (!instance.config.noBuffer) fflush(stdout);
if (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
#endif
startIndex = colonIndex + 1;
}
}
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);
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
parseStructureCommand(data->structure.chars + startIndex, &data->customValues, genJsonConfig, jsonDoc);
startIndex = colonIndex + 1;
}
}
+2 -2
View File
@@ -20,9 +20,9 @@ typedef struct FFdata
bool loadUserConfig;
} FFdata;
bool ffParseModuleCommand(const char* type);
bool ffParseModuleOptions(const char* key, const char* value);
void ffPrepareCommandOption(FFdata* data);
void ffPrintCommandOption(FFdata* data);
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
#endif
+1 -5
View File
@@ -7,7 +7,7 @@
static bool loadLibSymbols(FFDBusLibrary* lib)
{
FF_LIBRARY_LOAD(dbus, &instance.config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
@@ -33,9 +33,6 @@ static const FFDBusLibrary* loadLib(void)
static FFDBusLibrary lib;
static bool loaded = false;
static bool loadSuccess = false;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
ffThreadMutexLock(&mutex);
if(!loaded)
{
@@ -43,7 +40,6 @@ static const FFDBusLibrary* loadLib(void)
loadSuccess = loadLibSymbols(&lib);
}
ffThreadMutexUnlock(&mutex);
return loadSuccess ? &lib : NULL;
}
+20 -251
View File
@@ -15,8 +15,6 @@
#include <signal.h>
#endif
#include "modules/modules.h"
FFinstance instance; // Global singleton
static void initState(FFstate* state)
@@ -32,132 +30,11 @@ static void initState(FFstate* state)
static void defaultConfig(void)
{
ffInitLogoOptions(&instance.config.logo);
ffStrbufInit(&instance.config.colorKeys);
ffStrbufInit(&instance.config.colorTitle);
instance.config.brightColor = true;
ffStrbufInitStatic(&instance.config.keyValueSeparator, ": ");
instance.config.processingTimeout = 1000;
#if defined(__linux__) || defined(__FreeBSD__)
ffStrbufInit(&instance.config.playerName);
ffStrbufInit(&instance.config.osFile);
instance.config.dsForceDrm = false;
#elif defined(_WIN32)
instance.config.wmiTimeout = 5000;
#endif
instance.config.showErrors = false;
instance.config.allowSlowOperations = false;
instance.config.pipe = !isatty(STDOUT_FILENO);
#ifdef NDEBUG
instance.config.disableLinewrap = !instance.config.pipe;
instance.config.hideCursor = !instance.config.pipe;
#else
instance.config.disableLinewrap = false;
instance.config.hideCursor = false;
#endif
instance.config.escapeBedrock = true;
instance.config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
instance.config.sizeNdigits = 2;
instance.config.sizeMaxPrefix = UINT8_MAX;
instance.config.temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS;
instance.config.multithreading = true;
instance.config.stat = false;
instance.config.noBuffer = false;
instance.config.keyWidth = 0;
ffStrbufInitStatic(&instance.config.barCharElapsed, "");
ffStrbufInitStatic(&instance.config.barCharTotal, "-");
instance.config.barWidth = 10;
instance.config.barBorder = true;
instance.config.percentType = 1;
instance.config.percentNdigits = 0;
ffInitBatteryOptions(&instance.config.battery);
ffInitBiosOptions(&instance.config.bios);
ffInitBluetoothOptions(&instance.config.bluetooth);
ffInitBoardOptions(&instance.config.board);
ffInitBreakOptions(&instance.config.break_);
ffInitBrightnessOptions(&instance.config.brightness);
ffInitCPUOptions(&instance.config.cpu);
ffInitCPUUsageOptions(&instance.config.cpuUsage);
ffInitChassisOptions(&instance.config.chassis);
ffInitColorsOptions(&instance.config.colors);
ffInitCommandOptions(&instance.config.command);
ffInitCursorOptions(&instance.config.cursor);
ffInitCustomOptions(&instance.config.custom);
ffInitDEOptions(&instance.config.de);
ffInitDateTimeOptions(&instance.config.dateTime);
ffInitDiskOptions(&instance.config.disk);
ffInitDisplayOptions(&instance.config.display);
ffInitFontOptions(&instance.config.font);
ffInitGPUOptions(&instance.config.gpu);
ffInitGamepadOptions(&instance.config.gamepad);
ffInitHostOptions(&instance.config.host);
ffInitIconsOptions(&instance.config.icons);
ffInitKernelOptions(&instance.config.kernel);
ffInitLMOptions(&instance.config.lm);
ffInitLocalIpOptions(&instance.config.localIP);
ffInitLocaleOptions(&instance.config.locale);
ffInitMediaOptions(&instance.config.media);
ffInitMemoryOptions(&instance.config.memory);
ffInitMonitorOptions(&instance.config.monitor);
ffInitNetIOOptions(&instance.config.netIo);
ffInitOSOptions(&instance.config.os);
ffInitOpenCLOptions(&instance.config.openCL);
ffInitOpenGLOptions(&instance.config.openGL);
ffInitPackagesOptions(&instance.config.packages);
ffInitPlayerOptions(&instance.config.player);
ffInitPowerAdapterOptions(&instance.config.powerAdapter);
ffInitProcessesOptions(&instance.config.processes);
ffInitPublicIpOptions(&instance.config.publicIP);
ffInitSeparatorOptions(&instance.config.separator);
ffInitShellOptions(&instance.config.shell);
ffInitSoundOptions(&instance.config.sound);
ffInitSwapOptions(&instance.config.swap);
ffInitTerminalFontOptions(&instance.config.terminalFont);
ffInitTerminalOptions(&instance.config.terminal);
ffInitTerminalSizeOptions(&instance.config.terminalSize);
ffInitThemeOptions(&instance.config.theme);
ffInitTitleOptions(&instance.config.title);
ffInitUptimeOptions(&instance.config.uptime);
ffInitUsersOptions(&instance.config.users);
ffInitVersionOptions(&instance.config.version);
ffInitVulkanOptions(&instance.config.vulkan);
ffInitWMOptions(&instance.config.wm);
ffInitWMThemeOptions(&instance.config.wmTheme);
ffInitWallpaperOptions(&instance.config.wallpaper);
ffInitWeatherOptions(&instance.config.weather);
ffInitWifiOptions(&instance.config.wifi);
ffStrbufInit(&instance.config.libPCI);
ffStrbufInit(&instance.config.libVulkan);
ffStrbufInit(&instance.config.libWayland);
ffStrbufInit(&instance.config.libXcbRandr);
ffStrbufInit(&instance.config.libXcb);
ffStrbufInit(&instance.config.libXrandr);
ffStrbufInit(&instance.config.libX11);
ffStrbufInit(&instance.config.libGIO);
ffStrbufInit(&instance.config.libDConf);
ffStrbufInit(&instance.config.libDBus);
ffStrbufInit(&instance.config.libXFConf);
ffStrbufInit(&instance.config.libSQLite3);
ffStrbufInit(&instance.config.librpm);
ffStrbufInit(&instance.config.libImageMagick);
ffStrbufInit(&instance.config.libZ);
ffStrbufInit(&instance.config.libChafa);
ffStrbufInit(&instance.config.libEGL);
ffStrbufInit(&instance.config.libGLX);
ffStrbufInit(&instance.config.libOSMesa);
ffStrbufInit(&instance.config.libOpenCL);
ffStrbufInit(&instance.config.libfreetype);
ffStrbufInit(&instance.config.libPulse);
ffStrbufInit(&instance.config.libnm);
ffStrbufInit(&instance.config.libDdcutil);
ffOptionsInitLogo(&instance.config.logo);
ffOptionsInitGeneral(&instance.config.general);
ffOptionsInitModules(&instance.config.modules);
ffOptionsInitDisplay(&instance.config.display);
ffOptionsInitLibrary(&instance.config.library);
}
void ffInitInstance(void)
@@ -174,29 +51,6 @@ void ffInitInstance(void)
defaultConfig();
}
#if defined(FF_HAVE_THREADS) && !(defined(__APPLE__) || defined(_WIN32) || defined(__ANDROID__))
#include "detection/gtk_qt/gtk_qt.h"
#define FF_START_DETECTION_THREADS
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffConnectDisplayServer)
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectQt)
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK2)
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK3)
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK4)
void startDetectionThreads(void)
{
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, NULL));
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, NULL));
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, NULL));
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, NULL));
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, NULL));
}
#endif //FF_HAVE_THREADS
static volatile bool ffDisableLinewrap = true;
static volatile bool ffHideCursor = true;
@@ -232,15 +86,15 @@ static void exitSignalHandler(int signal)
void ffStart(void)
{
#ifdef FF_START_DETECTION_THREADS
if(instance.config.multithreading)
if(instance.config.general.multithreading)
startDetectionThreads();
#endif
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe && !instance.state.resultDoc;
ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc;
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc;
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
#ifdef _WIN32
setvbuf(stdout, NULL, _IOFBF, instance.config.noBuffer ? 0 : 4096);
setvbuf(stdout, NULL, _IOFBF, instance.config.display.noBuffer ? 0 : 4096);
SetConsoleCtrlHandler(consoleHandler, TRUE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
@@ -248,7 +102,7 @@ void ffStart(void)
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
SetConsoleOutputCP(CP_UTF8);
#else
if (instance.config.noBuffer) setvbuf(stdout, NULL, _IONBF, 0);
if (instance.config.display.noBuffer) setvbuf(stdout, NULL, _IONBF, 0);
struct sigaction action = { .sa_handler = exitSignalHandler };
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
@@ -256,7 +110,7 @@ void ffStart(void)
#endif
//reset everything to default before we start printing
if(!instance.config.pipe && !instance.state.resultDoc)
if(!instance.config.display.pipe && !instance.state.resultDoc)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(ffHideCursor)
@@ -278,100 +132,11 @@ void ffFinish(void)
static void destroyConfig(void)
{
ffDestroyLogoOptions(&instance.config.logo);
ffStrbufDestroy(&instance.config.colorKeys);
ffStrbufDestroy(&instance.config.colorTitle);
ffStrbufDestroy(&instance.config.keyValueSeparator);
ffStrbufDestroy(&instance.config.barCharElapsed);
ffStrbufDestroy(&instance.config.barCharTotal);
#if defined(__linux__) || defined(__FreeBSD__)
ffStrbufDestroy(&instance.config.playerName);
ffStrbufDestroy(&instance.config.osFile);
#endif
ffDestroyBatteryOptions(&instance.config.battery);
ffDestroyBiosOptions(&instance.config.bios);
ffDestroyBluetoothOptions(&instance.config.bluetooth);
ffDestroyBoardOptions(&instance.config.board);
ffDestroyBreakOptions(&instance.config.break_);
ffDestroyBrightnessOptions(&instance.config.brightness);
ffDestroyCPUOptions(&instance.config.cpu);
ffDestroyCPUUsageOptions(&instance.config.cpuUsage);
ffDestroyChassisOptions(&instance.config.chassis);
ffDestroyColorsOptions(&instance.config.colors);
ffDestroyCommandOptions(&instance.config.command);
ffDestroyCursorOptions(&instance.config.cursor);
ffDestroyCustomOptions(&instance.config.custom);
ffDestroyDEOptions(&instance.config.de);
ffDestroyDateTimeOptions(&instance.config.dateTime);
ffDestroyDiskOptions(&instance.config.disk);
ffDestroyDisplayOptions(&instance.config.display);
ffDestroyFontOptions(&instance.config.font);
ffDestroyGPUOptions(&instance.config.gpu);
ffDestroyGamepadOptions(&instance.config.gamepad);
ffDestroyHostOptions(&instance.config.host);
ffDestroyIconsOptions(&instance.config.icons);
ffDestroyKernelOptions(&instance.config.kernel);
ffDestroyLMOptions(&instance.config.lm);
ffDestroyLocalIpOptions(&instance.config.localIP);
ffDestroyLocaleOptions(&instance.config.locale);
ffDestroyMediaOptions(&instance.config.media);
ffDestroyMemoryOptions(&instance.config.memory);
ffDestroyMonitorOptions(&instance.config.monitor);
ffDestroyNetIOOptions(&instance.config.netIo);
ffDestroyOSOptions(&instance.config.os);
ffDestroyOpenCLOptions(&instance.config.openCL);
ffDestroyOpenGLOptions(&instance.config.openGL);
ffDestroyPackagesOptions(&instance.config.packages);
ffDestroyPlayerOptions(&instance.config.player);
ffDestroyPowerAdapterOptions(&instance.config.powerAdapter);
ffDestroyProcessesOptions(&instance.config.processes);
ffDestroyPublicIpOptions(&instance.config.publicIP);
ffDestroySeparatorOptions(&instance.config.separator);
ffDestroyShellOptions(&instance.config.shell);
ffDestroySoundOptions(&instance.config.sound);
ffDestroySwapOptions(&instance.config.swap);
ffDestroyTerminalFontOptions(&instance.config.terminalFont);
ffDestroyTerminalOptions(&instance.config.terminal);
ffDestroyTerminalSizeOptions(&instance.config.terminalSize);
ffDestroyThemeOptions(&instance.config.theme);
ffDestroyTitleOptions(&instance.config.title);
ffDestroyUptimeOptions(&instance.config.uptime);
ffDestroyUsersOptions(&instance.config.users);
ffDestroyVersionOptions(&instance.config.version);
ffDestroyVulkanOptions(&instance.config.vulkan);
ffDestroyWMOptions(&instance.config.wm);
ffDestroyWMThemeOptions(&instance.config.wmTheme);
ffDestroyWallpaperOptions(&instance.config.wallpaper);
ffDestroyWeatherOptions(&instance.config.weather);
ffDestroyWifiOptions(&instance.config.wifi);
ffStrbufDestroy(&instance.config.libPCI);
ffStrbufDestroy(&instance.config.libVulkan);
ffStrbufDestroy(&instance.config.libWayland);
ffStrbufDestroy(&instance.config.libXcbRandr);
ffStrbufDestroy(&instance.config.libXcb);
ffStrbufDestroy(&instance.config.libXrandr);
ffStrbufDestroy(&instance.config.libX11);
ffStrbufDestroy(&instance.config.libGIO);
ffStrbufDestroy(&instance.config.libDConf);
ffStrbufDestroy(&instance.config.libDBus);
ffStrbufDestroy(&instance.config.libXFConf);
ffStrbufDestroy(&instance.config.libSQLite3);
ffStrbufDestroy(&instance.config.librpm);
ffStrbufDestroy(&instance.config.libImageMagick);
ffStrbufDestroy(&instance.config.libZ);
ffStrbufDestroy(&instance.config.libChafa);
ffStrbufDestroy(&instance.config.libEGL);
ffStrbufDestroy(&instance.config.libGLX);
ffStrbufDestroy(&instance.config.libOSMesa);
ffStrbufDestroy(&instance.config.libOpenCL);
ffStrbufDestroy(&instance.config.libfreetype);
ffStrbufDestroy(&instance.config.libPulse);
ffStrbufDestroy(&instance.config.libnm);
ffStrbufDestroy(&instance.config.libDdcutil);
ffOptionsDestroyLogo(&instance.config.logo);
ffOptionsDestroyGeneral(&instance.config.general);
ffOptionsDestroyModules(&instance.config.modules);
ffOptionsDestroyDisplay(&instance.config.display);
ffOptionsDestroyLibrary(&instance.config.library);
}
static void destroyState(void)
@@ -379,6 +144,7 @@ static void destroyState(void)
ffPlatformDestroy(&instance.state.platform);
yyjson_doc_free(instance.state.configDoc);
yyjson_mut_doc_free(instance.state.resultDoc);
ffStrbufDestroy(&instance.state.migrateConfigPath);
}
void ffDestroyInstance(void)
@@ -469,6 +235,9 @@ void ffListFeatures(void)
#ifdef FF_HAVE_DDCUTIL
"libddcutil\n"
#endif
#ifdef FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
""
, stdout);
}
+54 -293
View File
@@ -35,6 +35,18 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs*
return false;
}
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs)
{
if (!ffStrbufEqual(&defaultModuleArgs->key, &moduleArgs->key))
yyjson_mut_obj_add_strbuf(doc, module, "key", &moduleArgs->key);
if (!ffStrbufEqual(&defaultModuleArgs->outputFormat, &moduleArgs->outputFormat))
yyjson_mut_obj_add_strbuf(doc, module, "format", &moduleArgs->outputFormat);
if (!ffStrbufEqual(&defaultModuleArgs->keyColor, &moduleArgs->keyColor))
yyjson_mut_obj_add_strbuf(doc, module, "keyColor", &moduleArgs->keyColor);
if (moduleArgs->keyWidth != defaultModuleArgs->keyWidth)
yyjson_mut_obj_add_uint(doc, module, "keyWidth", moduleArgs->keyWidth);
}
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[])
{
if (yyjson_is_int(val))
@@ -70,21 +82,17 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p
return "Invalid enum value type; must be a string or integer";
}
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
{
yyjson_mut_doc* doc = instance.state.resultDoc;
if (__builtin_expect(!doc, true)) return NULL;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJson)
baseInfo->generateJson(baseInfo, doc, module);
if (baseInfo->generateJsonResult)
baseInfo->generateJsonResult(baseInfo, doc, module);
else
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
return module;
}
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_mut_doc* jsonDoc)
{
if(!isalpha(type[0])) return false;
@@ -94,7 +102,9 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
if (ffStrEqualsIgnCase(type, baseInfo->name))
{
if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal);
if (!genJson(baseInfo))
if (__builtin_expect(jsonDoc != NULL, false))
genJsonResult(baseInfo, jsonDoc);
else
baseInfo->printModule(baseInfo);
return true;
}
@@ -112,34 +122,42 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
ffPrepareCPUUsage();
break;
}
case 'd': case 'D': {
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
{
if (module) cfg->modules.diskIo.moduleInfo.parseJsonObject(&cfg->modules.diskIo, module);
ffPrepareDiskIO(&cfg->modules.diskIo);
}
break;
}
case 'n': case 'N': {
if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME))
{
if (module) ffParseNetIOJsonObject(&cfg->netIo, module);
ffPrepareNetIO(&cfg->netIo);
if (module) cfg->modules.netIo.moduleInfo.parseJsonObject(&cfg->modules.netIo, module);
ffPrepareNetIO(&cfg->modules.netIo);
}
break;
}
case 'p': case 'P': {
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME))
{
if (module) ffParsePublicIpJsonObject(&cfg->publicIP, module);
ffPreparePublicIp(&cfg->publicIP);
if (module) cfg->modules.publicIP.moduleInfo.parseJsonObject(&cfg->modules.publicIP, module);
ffPreparePublicIp(&cfg->modules.publicIP);
}
break;
}
case 'w': case 'W': {
if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME))
{
if (module) ffParseWeatherJsonObject(&cfg->weather, module);
ffPrepareWeather(&cfg->weather);
if (module) cfg->modules.weather.moduleInfo.parseJsonObject(&cfg->modules.weather, module);
ffPrepareWeather(&cfg->modules.weather);
}
break;
}
}
}
static const char* printJsonConfig(bool prepare)
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
{
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
@@ -151,14 +169,12 @@ static const char* printJsonConfig(bool prepare)
if (!modules) return NULL;
if (!yyjson_is_arr(modules)) return "Property 'modules' must be an array of strings or objects";
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
yyjson_val* item;
size_t idx, max;
yyjson_arr_foreach(modules, idx, max, item)
{
uint64_t ms = 0;
if(!prepare && instance.config.stat)
if(!prepare && instance.config.display.stat)
ms = ffTimeGetTick();
yyjson_val* module = item;
@@ -177,22 +193,22 @@ static const char* printJsonConfig(bool prepare)
if(prepare)
prepareModuleJsonObject(type, module);
else if(!parseModuleJsonObject(type, module))
else if(!parseModuleJsonObject(type, module, jsonDoc))
return "Unknown module type";
if(!prepare && instance.config.stat)
if(!prepare && instance.config.display.stat)
{
ms = ffTimeGetTick() - ms;
if (resultDoc)
if (jsonDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
}
else
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
if(instance.config.pipe)
if(instance.config.display.pipe)
puts(str);
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
@@ -200,280 +216,25 @@ static const char* printJsonConfig(bool prepare)
}
#if defined(_WIN32)
if (!instance.config.noBuffer && !resultDoc) fflush(stdout);
if (!instance.config.display.noBuffer && !jsonDoc) fflush(stdout);
#endif
}
return NULL;
}
const char* ffParseGeneralJsonConfig(void)
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
{
FFconfig* config = &instance.config;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
if (!yyjson_is_obj(root))
return "Invalid JSON config format. Root value must be an object";
yyjson_val* object = yyjson_obj_get(root, "general");
if (!object) return NULL;
if (!yyjson_is_obj(object)) return "Property 'general' must be an object";
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(object, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "allowSlowOperations"))
config->allowSlowOperations = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
config->multithreading = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "stat"))
{
if ((config->stat = yyjson_get_bool(val)))
config->showErrors = true;
}
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
config->escapeBedrock = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "pipe"))
config->pipe = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
config->processingTimeout = (int32_t) yyjson_get_int(val);
#if defined(__linux__) || defined(__FreeBSD__)
else if (ffStrEqualsIgnCase(key, "playerName"))
ffStrbufSetS(&config->playerName, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "osFile"))
ffStrbufSetS(&config->osFile, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
config->dsForceDrm = yyjson_get_bool(val);
#elif defined(_WIN32)
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
config->wmiTimeout = (int32_t) yyjson_get_int(val);
#endif
else
return "Unknown general property";
}
return NULL;
}
const char* ffParseDisplayJsonConfig(void)
{
FFconfig* config = &instance.config;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
if (!yyjson_is_obj(root))
return "Invalid JSON config format. Root value must be an object";
yyjson_val* object = yyjson_obj_get(root, "display");
if (!object) return NULL;
if (!yyjson_is_obj(object)) return "Property 'display' must be an object";
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(object, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "showErrors"))
config->showErrors = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "disableLinewrap"))
config->disableLinewrap = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "hideCursor"))
config->hideCursor = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "separator"))
ffStrbufSetS(&config->keyValueSeparator, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "color"))
{
if (yyjson_is_str(val))
{
ffOptionParseColor(yyjson_get_str(val), &config->colorKeys);
ffStrbufSet(&config->colorTitle, &config->colorKeys);
}
else if (yyjson_is_obj(val))
{
const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys"));
if (colorKeys)
ffOptionParseColor(colorKeys, &config->colorKeys);
const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title"));
if (colorTitle)
ffOptionParseColor(colorTitle, &config->colorTitle);
}
else
return "display.color must be either a string or an object";
}
else if (ffStrEqualsIgnCase(key, "brightColor"))
config->brightColor = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "binaryPrefix"))
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "iec", FF_BINARY_PREFIX_TYPE_IEC },
{ "si", FF_BINARY_PREFIX_TYPE_SI },
{ "jedec", FF_BINARY_PREFIX_TYPE_JEDEC },
{},
});
if (error) return error;
config->binaryPrefixType = (FFBinaryPrefixType) value;
}
else if (ffStrEqualsIgnCase(key, "sizeNdigits"))
config->sizeNdigits = (uint8_t) yyjson_get_uint(val);
else if (ffStrEqualsIgnCase(key, "sizeMaxPrefix"))
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "B", 0 },
{ "kB", 1 },
{ "MB", 2 },
{ "GB", 3 },
{ "TB", 4 },
{ "PB", 5 },
{ "EB", 6 },
{ "ZB", 7 },
{ "YB", 8 },
{}
});
if (error) return error;
config->sizeMaxPrefix = (uint8_t) value;
}
else if (ffStrEqualsIgnCase(key, "temperatureUnit"))
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS },
{ "C", FF_TEMPERATURE_UNIT_CELSIUS },
{ "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT },
{ "F", FF_TEMPERATURE_UNIT_FAHRENHEIT },
{ "KELVIN", FF_TEMPERATURE_UNIT_KELVIN },
{ "K", FF_TEMPERATURE_UNIT_KELVIN },
{},
});
if (error) return error;
config->temperatureUnit = (FFTemperatureUnit) value;
}
else if (ffStrEqualsIgnCase(key, "percentType"))
config->percentType = (uint8_t) yyjson_get_uint(val);
else if (ffStrEqualsIgnCase(key, "percentNdigits"))
config->percentNdigits = (uint8_t) yyjson_get_uint(val);
else if (ffStrEqualsIgnCase(key, "bar"))
{
if (yyjson_is_obj(val))
{
const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed"));
if (charElapsed)
ffStrbufSetS(&config->barCharElapsed, charElapsed);
const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal"));
if (charTotal)
ffStrbufSetS(&config->barCharTotal, charTotal);
yyjson_val* border = yyjson_obj_get(val, "border");
if (border)
config->barBorder = yyjson_get_bool(border);
yyjson_val* width = yyjson_obj_get(val, "width");
if (width)
config->barWidth = (uint8_t) yyjson_get_uint(width);
}
else
return "display.bar must be an object";
}
else if (ffStrEqualsIgnCase(key, "noBuffer"))
config->noBuffer = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "keyWidth"))
config->keyWidth = (uint32_t) yyjson_get_uint(val);
else
return "Unknown display property";
}
return NULL;
}
const char* ffParseLibraryJsonConfig(void)
{
FFconfig* config = &instance.config;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
if (!yyjson_is_obj(root))
return "Invalid JSON config format. Root value must be an object";
yyjson_val* object = yyjson_obj_get(root, "library");
if (!object) return NULL;
if (!yyjson_is_obj(object)) return "Property 'library' must be an object";
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(object, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "pci"))
ffStrbufSetS(&config->libPCI, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "vulkan"))
ffStrbufSetS(&config->libVulkan, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "freetype"))
ffStrbufSetS(&config->libfreetype, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "wayland"))
ffStrbufSetS(&config->libWayland, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "xcbRandr"))
ffStrbufSetS(&config->libXcbRandr, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "xcb"))
ffStrbufSetS(&config->libXcb, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "Xrandr"))
ffStrbufSetS(&config->libXrandr, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "X11"))
ffStrbufSetS(&config->libX11, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "gio"))
ffStrbufSetS(&config->libGIO, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "DConf"))
ffStrbufSetS(&config->libDConf, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "dbus"))
ffStrbufSetS(&config->libDBus, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "XFConf"))
ffStrbufSetS(&config->libXFConf, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "sqlite") || ffStrEqualsIgnCase(key, "sqlite3"))
ffStrbufSetS(&config->libSQLite3, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "rpm"))
ffStrbufSetS(&config->librpm, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "imagemagick"))
ffStrbufSetS(&config->libImageMagick, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "z"))
ffStrbufSetS(&config->libZ, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "chafa"))
ffStrbufSetS(&config->libChafa, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "egl"))
ffStrbufSetS(&config->libEGL, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "glx"))
ffStrbufSetS(&config->libGLX, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "osmesa"))
ffStrbufSetS(&config->libOSMesa, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "opencl"))
ffStrbufSetS(&config->libOpenCL, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "pulse"))
ffStrbufSetS(&config->libPulse, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "nm"))
ffStrbufSetS(&config->libnm, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "ddcutil"))
ffStrbufSetS(&config->libDdcutil, yyjson_get_str(val));
else
return "Unknown library property";
}
return NULL;
}
void ffPrintJsonConfig(bool prepare)
{
const char* error = printJsonConfig(prepare);
const char* error = printJsonConfig(prepare, jsonDoc);
if (error)
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
{
if (jsonDoc)
{
yyjson_mut_val* obj = yyjson_mut_obj(jsonDoc);
yyjson_mut_obj_add_str(jsonDoc, obj, "error", error);
yyjson_mut_doc_set_root(jsonDoc, obj);
}
else
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
}
}
+6 -4
View File
@@ -4,10 +4,12 @@
bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs);
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
void ffPrintJsonConfig(bool prepare);
const char* ffParseGeneralJsonConfig(void);
const char* ffParseDisplayJsonConfig(void);
const char* ffParseLibraryJsonConfig(void);
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc);
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs);
yyjson_api_inline yyjson_mut_val* yyjson_mut_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) {
return yyjson_mut_strncpy(doc, buf->chars, buf->length);
}
yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
+57 -56
View File
@@ -5,31 +5,32 @@ static FFModuleBaseInfo* A[] = {
};
static FFModuleBaseInfo* B[] = {
(void*) &instance.config.battery,
(void*) &instance.config.bios,
(void*) &instance.config.bluetooth,
(void*) &instance.config.board,
(void*) &instance.config.break_,
(void*) &instance.config.brightness,
(void*) &instance.config.modules.battery,
(void*) &instance.config.modules.bios,
(void*) &instance.config.modules.bluetooth,
(void*) &instance.config.modules.board,
(void*) &instance.config.modules.break_,
(void*) &instance.config.modules.brightness,
NULL,
};
static FFModuleBaseInfo* C[] = {
(void*) &instance.config.chassis,
(void*) &instance.config.command,
(void*) &instance.config.colors,
(void*) &instance.config.cpu,
(void*) &instance.config.cpuUsage,
(void*) &instance.config.cursor,
(void*) &instance.config.custom,
(void*) &instance.config.modules.chassis,
(void*) &instance.config.modules.command,
(void*) &instance.config.modules.colors,
(void*) &instance.config.modules.cpu,
(void*) &instance.config.modules.cpuUsage,
(void*) &instance.config.modules.cursor,
(void*) &instance.config.modules.custom,
NULL,
};
static FFModuleBaseInfo* D[] = {
(void*) &instance.config.dateTime,
(void*) &instance.config.de,
(void*) &instance.config.display,
(void*) &instance.config.disk,
(void*) &instance.config.modules.dateTime,
(void*) &instance.config.modules.de,
(void*) &instance.config.modules.display,
(void*) &instance.config.modules.disk,
(void*) &instance.config.modules.diskIo,
NULL,
};
@@ -38,23 +39,23 @@ static FFModuleBaseInfo* E[] = {
};
static FFModuleBaseInfo* F[] = {
(void*) &instance.config.font,
(void*) &instance.config.modules.font,
NULL,
};
static FFModuleBaseInfo* G[] = {
(void*) &instance.config.gamepad,
(void*) &instance.config.gpu,
(void*) &instance.config.modules.gamepad,
(void*) &instance.config.modules.gpu,
NULL,
};
static FFModuleBaseInfo* H[] = {
(void*) &instance.config.host,
(void*) &instance.config.modules.host,
NULL,
};
static FFModuleBaseInfo* I[] = {
(void*) &instance.config.icons,
(void*) &instance.config.modules.icons,
NULL,
};
@@ -63,42 +64,42 @@ static FFModuleBaseInfo* J[] = {
};
static FFModuleBaseInfo* K[] = {
(void*) &instance.config.kernel,
(void*) &instance.config.modules.kernel,
NULL,
};
static FFModuleBaseInfo* L[] = {
(void*) &instance.config.lm,
(void*) &instance.config.locale,
(void*) &instance.config.localIP,
(void*) &instance.config.modules.lm,
(void*) &instance.config.modules.locale,
(void*) &instance.config.modules.localIP,
NULL,
};
static FFModuleBaseInfo* M[] = {
(void*) &instance.config.media,
(void*) &instance.config.memory,
(void*) &instance.config.monitor,
(void*) &instance.config.modules.media,
(void*) &instance.config.modules.memory,
(void*) &instance.config.modules.monitor,
NULL,
};
static FFModuleBaseInfo* N[] = {
(void*) &instance.config.netIo,
(void*) &instance.config.modules.netIo,
NULL,
};
static FFModuleBaseInfo* O[] = {
(void*) &instance.config.openCL,
(void*) &instance.config.openGL,
(void*) &instance.config.os,
(void*) &instance.config.modules.openCL,
(void*) &instance.config.modules.openGL,
(void*) &instance.config.modules.os,
NULL,
};
static FFModuleBaseInfo* P[] = {
(void*) &instance.config.packages,
(void*) &instance.config.player,
(void*) &instance.config.powerAdapter,
(void*) &instance.config.processes,
(void*) &instance.config.publicIP,
(void*) &instance.config.modules.packages,
(void*) &instance.config.modules.player,
(void*) &instance.config.modules.powerAdapter,
(void*) &instance.config.modules.processes,
(void*) &instance.config.modules.publicIP,
NULL,
};
@@ -111,40 +112,40 @@ static FFModuleBaseInfo* R[] = {
};
static FFModuleBaseInfo* S[] = {
(void*) &instance.config.separator,
(void*) &instance.config.shell,
(void*) &instance.config.sound,
(void*) &instance.config.swap,
(void*) &instance.config.modules.separator,
(void*) &instance.config.modules.shell,
(void*) &instance.config.modules.sound,
(void*) &instance.config.modules.swap,
NULL,
};
static FFModuleBaseInfo* T[] = {
(void*) &instance.config.terminal,
(void*) &instance.config.terminalFont,
(void*) &instance.config.terminalSize,
(void*) &instance.config.title,
(void*) &instance.config.theme,
(void*) &instance.config.modules.terminal,
(void*) &instance.config.modules.terminalFont,
(void*) &instance.config.modules.terminalSize,
(void*) &instance.config.modules.title,
(void*) &instance.config.modules.theme,
NULL,
};
static FFModuleBaseInfo* U[] = {
(void*) &instance.config.uptime,
(void*) &instance.config.users,
(void*) &instance.config.modules.uptime,
(void*) &instance.config.modules.users,
NULL,
};
static FFModuleBaseInfo* V[] = {
(void*) &instance.config.version,
(void*) &instance.config.vulkan,
(void*) &instance.config.modules.version,
(void*) &instance.config.modules.vulkan,
NULL,
};
static FFModuleBaseInfo* W[] = {
(void*) &instance.config.wallpaper,
(void*) &instance.config.weather,
(void*) &instance.config.wm,
(void*) &instance.config.wifi,
(void*) &instance.config.wmTheme,
(void*) &instance.config.modules.wallpaper,
(void*) &instance.config.modules.weather,
(void*) &instance.config.modules.wm,
(void*) &instance.config.modules.wifi,
(void*) &instance.config.modules.wmTheme,
NULL,
};
+9 -3
View File
@@ -17,7 +17,9 @@ typedef struct FFModuleBaseInfo
bool (*parseCommandOptions)(void* options, const char* key, const char* value);
void (*parseJsonObject)(void* options, struct yyjson_val *module);
void (*printModule)(void* options);
void (*generateJson)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
void (*generateJsonResult)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
void (*printHelpFormat)(void);
void (*generateJsonConfig)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* obj);
} FFModuleBaseInfo;
static inline void ffOptionInitModuleBaseInfo(
@@ -26,14 +28,18 @@ static inline void ffOptionInitModuleBaseInfo(
void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value)
void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module)
void* printModule, // void (*const printModule)(void* options)
void* generateJson // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
void* generateJsonResult, // void (*const generateJsonResult)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
void (*printHelpFormat)(void),
void* generateJsonConfig // void (*const generateJsonConfig)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
)
{
baseInfo->name = name;
baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions;
baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject;
baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule;
baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson;
baseInfo->generateJsonResult = (__typeof__(baseInfo->generateJsonResult)) generateJsonResult;
baseInfo->printHelpFormat = printHelpFormat;
baseInfo->generateJsonConfig = (__typeof__(baseInfo->generateJsonConfig)) generateJsonConfig;
}
typedef struct FFModuleArgs
+4 -4
View File
@@ -65,7 +65,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
double size = (double) bytes;
uint8_t counter = 0;
while(size >= base && counter < instance.config.sizeMaxPrefix && prefixes[counter + 1])
while(size >= base && counter < instance.config.display.sizeMaxPrefix && prefixes[counter + 1])
{
size /= base;
counter++;
@@ -74,12 +74,12 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
if(counter == 0)
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
else
ffStrbufAppendF(result, "%.*f %s", instance.config.sizeNdigits, size, prefixes[counter]);
ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]);
}
void ffParseSize(uint64_t bytes, FFstrbuf* result)
{
switch (instance.config.binaryPrefixType)
switch (instance.config.display.binaryPrefixType)
{
case FF_BINARY_PREFIX_TYPE_IEC:
parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL});
@@ -98,7 +98,7 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result)
void ffParseTemperature(double celsius, FFstrbuf* buffer)
{
switch (instance.config.temperatureUnit)
switch (instance.config.display.temperatureUnit)
{
case FF_TEMPERATURE_UNIT_CELSIUS:
ffStrbufAppendF(buffer, "%.1f°C", celsius);
+26 -11
View File
@@ -14,16 +14,16 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " "))
return;
if(!instance.config.pipe)
if(!instance.config.display.pipe)
{
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if (instance.config.brightColor)
if (instance.config.display.brightColor)
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
if(moduleArgs && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR) && moduleArgs->keyColor.length > 0)
ffPrintColor(&moduleArgs->keyColor);
else
ffPrintColor(&instance.config.colorKeys);
ffPrintColor(&instance.config.display.colorKeys);
}
//NULL check is required for modules with custom keys, e.g. disk with the folder path
@@ -43,18 +43,18 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
ffStrbufWriteTo(&key, stdout);
}
if(!instance.config.pipe)
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
ffStrbufWriteTo(&instance.config.keyValueSeparator, stdout);
ffStrbufWriteTo(&instance.config.display.keyValueSeparator, stdout);
if(!instance.config.pipe)
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if (!instance.config.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
if (!instance.config.display.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
{
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.keyWidth;
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.display.keyWidth;
if (keyWidth > 0)
printf("\e[%uG", (unsigned) (keyWidth + instance.state.logoWidth));
}
@@ -77,17 +77,17 @@ void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFMo
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
{
if(!instance.config.showErrors)
if(!instance.config.display.showErrors)
return;
ffPrintLogoAndKey(moduleName, moduleIndex, moduleArgs, printType);
if(!instance.config.pipe)
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
vprintf(message, arguments);
if(!instance.config.pipe)
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
putchar('\n');
@@ -132,3 +132,18 @@ void ffPrintCharTimes(char c, uint32_t times)
if(remaining > 0)
fwrite(str, 1, remaining, stdout);
}
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[])
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateS(name);
ffStrbufLowerCase(&buffer);
printf("--%s-format:\n", buffer.chars);
printf("Sets the format string for %s output.\n", name);
puts("To see how a format string is constructed, take a look at \"fastfetch --help format\".");
puts("The following values are passed:");
for(unsigned i = 0; i < numArgs; i++)
printf(" {%u}: %s\n", i + 1, args[i]);
printf("The default is something similar to \"%s\".\n", def);
}
+2
View File
@@ -25,4 +25,6 @@ FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex,
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[]);
#endif
+3 -2
View File
@@ -34,10 +34,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
//Child
if(childPid == 0)
{
int nullFile = open("/dev/null", O_WRONLY);
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
close(pipes[0]);
close(pipes[1]);
close(useStdErr ? STDOUT_FILENO : STDERR_FILENO);
setenv("LANG", "C", 1);
execvp(argv[0], argv);
exit(901);
@@ -48,7 +49,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
int timeout = instance.config.processingTimeout;
int timeout = instance.config.general.processingTimeout;
if (timeout >= 0)
fcntl(childPipeFd, F_SETFL, fcntl(childPipeFd, F_GETFL) | O_NONBLOCK);
+1 -1
View File
@@ -8,7 +8,7 @@ enum { FF_PIPE_BUFSIZ = 4096 };
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
{
int timeout = instance.config.processingTimeout;
int timeout = instance.config.general.processingTimeout;
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
L"\\\\.\\pipe\\LOCAL\\",
+4 -11
View File
@@ -15,18 +15,14 @@ typedef enum FFInitState
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
static dataObject data; \
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
ffThreadMutexLock(&mutex); \
if(initState != FF_INITSTATE_UNINITIALIZED) {\
ffThreadMutexUnlock(&mutex); \
return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \
} \
initState = FF_INITSTATE_SUCCESSFUL; \
void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \
if(libraryHandle == NULL) { \
initState = FF_INITSTATE_FAILED; \
ffThreadMutexUnlock(&mutex); \
return NULL; \
} \
@@ -35,20 +31,17 @@ typedef enum FFInitState
if(data.ff ## symbolName == NULL) { \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
ffThreadMutexUnlock(&mutex); \
return NULL; \
}
#define FF_LIBRARY_DATA_LOAD_RETURN \
initState = FF_INITSTATE_SUCCESSFUL; \
ffThreadMutexUnlock(&mutex); \
return &data;
#define FF_LIBRARY_DATA_LOAD_ERROR \
{ \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
ffThreadMutexUnlock(&mutex); \
return NULL; \
}
@@ -99,7 +92,7 @@ typedef struct GSettingsData
static const GSettingsData* getGSettingsData(void)
{
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance.config.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance.config.library.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_lookup)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_has_key)
@@ -172,7 +165,7 @@ typedef struct DConfData
static const DConfData* getDConfData(void)
{
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance.config.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance.config.library.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_read_full)
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
@@ -243,7 +236,7 @@ typedef struct XFConfData
static const XFConfData* getXFConfData(void)
{
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance.config.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance.config.library.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_has_property)
@@ -305,7 +298,7 @@ typedef struct SQLiteData
static const SQLiteData* getSQLiteData(void)
{
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance.config.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance.config.library.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
+1 -1
View File
@@ -2,7 +2,7 @@
# This file sets the default config for all users of the system.
# For more information about how configuration files work,
# see ~/.config/fastfetch/config.conf, generated during first run.
# see ~/.config/fastfetch/config.conf.
# All options that can be put there (or passed as argument) can be put here too.
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf
+1 -3
View File
@@ -8,9 +8,6 @@
"top": 2
}
},
"display": {
"percentType": 9 // colored percent number
},
"modules": [
"title",
"separator",
@@ -34,6 +31,7 @@
"gpu",
"memory",
"disk",
"localip",
"battery",
"poweradapter",
"locale",
+79 -64
View File
@@ -1,9 +1,11 @@
Usage: fastfetch <options>
Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way
Usage: fastfetch <?options>
Informative options:
-h,--help: Show this message
-h,--help <command>: Show help for a specific command
-v,--version: Show the version of fastfetch
-h, --help: Show this message
-h, --help <command>: Show help for a specific command
-v, --version: Show the version of fastfetch
--list-config-paths: List search paths of config files
--list-data-paths: List search paths of presets and logos
--list-logos: List available logos
@@ -14,33 +16,33 @@ Informative options:
--print-config-system: Print the default system config
--print-config-user: Print the default user config
--print-structure: Print the default structure
--gen-config <?type>: Generate a sample config file in the default path. Param `type` can be `jsonc` or `conf`
--gen-config-force <?type>: Generate a sample config file in the default path. Overwrite the existing one
Config options:
-c, --load-config <file>: Load a config file or preset (+)
--gen-config <type>: Generate a sample config file in the default path. Param `type` can be `jsonc` or deprecated `conf`
--gen-config-force <type>: Generate a sample config file in the default path. Overwrite the existing one
--migrate-config <?path>: Migrate old flag based config file to new JSONC format. Optional param `path` is the file path that new file should be write to
General options:
--load-config <file>: Load a config file or preset (+)
--config <file>: Alias of --load-config (+)
--multithreading <?value>: Use multiple threads to detect values
--stat <?value>: Show time usage (in ms) for individual modules
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
--thread <?value>: Use separate threads to send HTTP requests
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
--pipe <?value>: Disable logo and all escape sequences
--wmi-timeout <num>: Set the timeout (ms) for WMI queries. Windows only. Default is 5000
--processing-timeout <num>: Set the timeout (ms) when waiting for child processes. Default is 1000
--ds-force-drm <?value>: Set if only DRM should be used to detect displays. Default is false
--ds-force-drm <?value>: Set if only DRM should be used to detect displays. Default is false. Linux only
Logo options:
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
-l, --logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-preserve-aspect-radio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
--logo-preserve-aspect-ratio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
--logo-color-[1-9] <color>: Overwrite a color in the logo
--logo-padding <padding>: Set the padding on the left and the right of the logo
--logo-padding-left <padding>: Set the padding on the left of the logo
--logo-padding-right <padding>: Set the padding on the right of the logo
--logo-padding-top <padding>: Set the padding on the top of the logo
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
--logo-separate <?value>: If true, print modules at bottom of the logo
--logo-recache <?value>: If true, regenerate image logo cache
--file <file>: Short for --logo-type file --logo <file>
--file-raw <file>: Short for --logo-type file-raw --logo <file>
@@ -57,7 +59,9 @@ Logo options:
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
Display options:
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use `fastfetch --list-modules` to see the ones available.
--stat <?value>: Show time usage (in ms) for individual modules
--pipe <?value>: Disable logo and all escape sequences
--color-keys <color>: Set the color of the keys
--color-title <color>: Set the color of the title
--color <color>: Set the color of both the keys and title
@@ -70,7 +74,7 @@ Display options:
--disable-linewrap <?value>: Whether to disable line wrap during the run
--hide-cursor <?value>: Whether to hide the cursor during the run
--binary-prefix <value>: Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 9
--percent-ndigits <value>: Set the number of digits to keep after the decimal point when formatting percentage numbers. Default is 0
--bar-char-elapsed <str>: Set the character to use in elapsed part. Default is '■'
--bar-char-total <str>: Set the character to use in total part. Default is '-'
@@ -83,8 +87,8 @@ Display options:
General module options:
--<module>-format <format>: Set the format string to use for each specific module.
To see how a format string works, use fastfetch --help format.
To see help about a specific format string, use fastfetch --help <module>-format.
To see how a format string works, use `fastfetch --help format`.
To see help about a specific format string, use `fastfetch --help <module>-format`.
--<module>-key <key>: Set the key to use for each specific module.
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
@@ -93,37 +97,39 @@ General module options:
--<module>-key-width <num>: Override the global `--key-width` option for each specific module.
Library options: Set the path of a library to load
--lib-PCI <path>
--lib-vulkan <path>
--lib-wayland <path>
--lib-xcb-randr <path>
--lib-xcb <path>
--lib-Xrandr <path>
--lib-X11 <path>
--lib-gio <path>
--lib-DConf <path>
--lib-DBus <path>
--lib-XFConf <path>
--lib-sqlite3 <path>
--lib-rpm <path>
--lib-imagemagick <path>
--lib-z <path>
--lib-chafa <path>
--lib-egl <path>
--lib-glx <path>
--lib-osmesa <path>
--lib-opencl <path>
--lib-pulse <path>
--lib-freetype <path>
--lib-ddcutil <path>
--lib-PCI <path>: GPU output
--lib-vulkan <path>: Vulkan module & fallback for GPU output
--lib-wayland <path>: Better display performance and output in wayland sessions
--lib-xcb-randr <path>: X11 sessions for better display detection and faster WM detection
--lib-xcb <path>: X11 sessions for better display detection and faster WM detection
--lib-Xrandr <path>: X11 sessions for better display detection and faster WM detection
--lib-X11 <path>: X11 sessions for better display detection and faster WM detection
--lib-gio <path>: Needed for values that are only stored GSettings
--lib-DConf <path>: Needed for values that are only stored in DConf + Fallback for GSettings
--lib-DBus <path>: Bluetooth, Player & Media detection
--lib-XFConf <path>: Needed for XFWM theme and XFCE Terminal font
--lib-sqlite3 <path>: Needed for pkg & rpm package count
--lib-rpm <path>: Slower fallback for rpm package count
--lib-imagemagick <path>: Images in terminal using sixel or kitty graphics protocol
--lib-z <path>: Libz. Faster image output when using kitty graphics protocol
--lib-chafa <path>: Image output as ascii art
--lib-egl <path>: Needed by the OpenGL module for gl context creation
--lib-glx <path>: Needed by the OpenGL module for gl context creation
--lib-osmesa <path>: Needed by the OpenGL module for gl context creation
--lib-opencl <path>: OpenCL module
--lib-pulse <path>: Pulseaudio. Used for Sound detection
--lib-nm: NetworkManager. Used for Wifi detection
--lib-freetype <path>: Used for Termux font detection
--lib-ddcutil <path>: Used for brightness detection of external displays
Module specific options:
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
--title-color-user <color>: Set color of the user name (left part). Default is empty (use color of `--color-title`).
--title-color-at <color>: Set color of the @ symbol (middle part). Default is empty (use color of `--color-title`)
--title-color-host <color>: Set color of the host name (right part). Default is empty (use color of `--color-title`)
--chassis-use-wmi <?value>: Set if WMI query should be used on Windows, which detects more information but slower. Default is false
--separator-string <str>: Set the string printed by the separator module
--os-file <path>: Set the path to the file containing OS information
--os-file <path>: Set the path to the file containing OS information. Linux only
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
--disk-show-regular <?value>: Set if regular volume should be printed. Default is true
--disk-show-external <?value>: Set if external volume should be printed. Default is true
@@ -132,33 +138,42 @@ Module specific options:
--disk-show-readonly <?value>: Set if read only volumes should be printed. Default is false
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
--disk-use-available <?value>: Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
--display-compact-type: <?string>: Set if all displays should be printed in one line. Default is none
--display-detect-name: <?value>: Set if display name should be detected and printed (if supported). Default is false
--display-precise-refresh-rate: <?value>:Set if decimal refresh rates should not be rounded into integers when printing. Default is true
--sound-type: <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
--diskio-name-prefix <str>: Show disks with given name prefix only. Default is empty
--bluetooth-show-disconnected <?value>: Set if disconnected bluetooth devices should be printed. Default is false
--packages-winget <?value>: Set if winget package count should be detected. Default is false
--display-compact-type <?string>: Set if all displays should be printed in one line. Default is none
--display-detect-name <?value>: Set if display name should be detected and printed (if supported). Default is false
--display-precise-refresh-rate <?value>: Set if decimal refresh rates should not be rounded into integers when printing. Default is true
--brightness-ddcci-sleep <num>: Set the sleep times (in ms) when sending DDC/CI requests. See <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail. Default is 10
--sound-type <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
--battery-dir <folder>: The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only
--battery-use-setup-api <?value>: Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--cpu-freq-ndigits <num>: Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2
--cpuusage-separate <?value>: Display CPU usage per CPU logical core, instead of an average result. Default is false
--de-slow-version-detection <?value>: Set if DE version should be detected with slow operations. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--gpu-use-nvml <?value>: Use nvml (NVIDIA Management Library) to detect more detailed GPU information (memory usage, CUDA core count, etc). Default is false
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
--gpu-hide-type <?value>: Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
--localip-show-mac <?value>: Show mac addresses in local ip module. Default is false
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
--localip-name-prefix <str>: Show interfaces with given interface name prefix only. Default is empty
--localip-default-route-only <?value>: Show the interface that is used for default routing only. Default is false
--localip-default-route-only <?value>: Show the interface that is used for default routing only. Default is true
--localip-compact <?value>: Show all IPs in one line. Default is false
--netio-name-prefix <str>: Show interfaces with given name prefix only. Default is empty
--netio-default-route-only <?value>: Show the interfac that is used for default routing only. Default is false
--publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--publicip-url: The URL of public IP detection server to be used.
--weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
--weather-output-format: The output weather format to be used. It must be URI encoded.
--player-name: The name of the player to use
--opengl-library <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
--netio-name-prefix <str>: Show interfaces with given name prefix only. Default is empty
--netio-default-route-only <?value>: Show the interfac that is used for default routing only. Default is true
--publicip-timeout <num>: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--publicip-url <str>: The URL of public IP detection server to be used.
--weather-location <str>: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
--weather-timeout <num>: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
--weather-output-format <str>: The output weather format to be used. It must be URI encoded.
--wm-detect-plugin <?value>: Set if window manager plugin should be detected on supported platforms. Default is false
--player-name <str>: The name of the player to use for module Media and Player. Linux only
--opengl-library <str>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, /bin/sh for *nix
--command-key <str>: Set the module key to display
--command-text <str>: Set the command text to be executed
@@ -168,4 +183,4 @@ Module specific options:
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
If a value starts with a ?, it is optional. "true" will be used if not set.
A (+) at the end indicates that more help can be printed with --help <option>
All options can be made permanent in $XDG_CONFIG_HOME/fastfetch/config.conf
All options can be made permanent with command `fastfetch <options> --migrate-config`
+2 -2
View File
@@ -1,6 +1,6 @@
usage: fastfetch --color <color>
Usage: fastfetch --color <color>
<color> must be a color encoding for linux terminals. It is inserted between "ESC[" and "m".
<color> must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m".
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
Examples:
--color 35: sets the color to pink
+1 -1
View File
@@ -1,4 +1,4 @@
usage: fastfetch --load-config <file>
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:
+1 -1
View File
@@ -1 +1 @@
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:LocalIp:Battery:PowerAdapter:Locale:Break:Colors
+1
View File
@@ -15,6 +15,7 @@ typedef struct FFBatteryResult
double capacity;
FFstrbuf status;
double temperature;
uint32_t cycleCount;
} FFBatteryResult;
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results);
+1
View File
@@ -35,6 +35,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
+31 -34
View File
@@ -5,30 +5,16 @@
#include <IOKit/IOKitLib.h>
static double detectBatteryTemp(void)
{
double result = 0;
if(ffDetectCoreTemps(FF_TEMP_BATTERY, &result))
return FF_BATTERY_TEMP_UNSET;
return result;
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery");
if (matchDict == NULL)
return "IOServiceMatching(\"AppleSmartBattery\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
@@ -39,7 +25,13 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
const char* error;
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
@@ -54,33 +46,38 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->technology);
ffCfDictGetString(properties, CFSTR("DeviceName"), &battery->modelName);
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
{
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
ffStrbufAppendS(&battery->modelName, "Builtin");
ffStrbufAppendS(&battery->technology, "Lithium");
if (!battery->modelName.length)
ffStrbufAppendS(&battery->modelName, "Built-in");
}
ffCfDictGetInt(properties, CFSTR("CycleCount"), (int32_t*) &battery->cycleCount);
if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "AC connected, ");
else
ffStrbufAppendS(&battery->status, "Discharging, ");
if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Charging, ");
if (!ffCfDictGetBool(properties, CFSTR("AtCriticalLevel"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
if (options->temp)
{
ffStrbufAppendS(&battery->manufacturer, "Unknown");
ffStrbufAppendS(&battery->modelName, "Unknown");
ffStrbufAppendS(&battery->technology, "Unknown");
int64_t temp;
if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp))
battery->temperature = (double) temp / 10 - 273.15;
else
ffDetectCoreTemps(FF_TEMP_BATTERY, &battery->temperature);
}
ffStrbufInit(&battery->status);
if (!ffCfDictGetBool(properties, CFSTR("FullyCharged"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Fully charged");
else if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Charging");
else
ffStrbufAppendS(&battery->status, "");
battery->temperature = options->temp ? detectBatteryTemp() : FF_BATTERY_TEMP_UNSET;
CFRelease(properties);
IOObjectRelease(registryEntry);
}
+1
View File
@@ -34,6 +34,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
+24 -7
View File
@@ -1,11 +1,11 @@
#include "fastfetch.h"
#include "common/io/io.h"
#include "battery.h"
#include "common/io/io.h"
#include "detection/temps/temps_linux.h"
#include "util/stringUtils.h"
#include <dirent.h>
static void parseBattery(FFstrbuf* dir, FFlist* results)
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
{
uint32_t dirLength = dir->length;
@@ -65,7 +65,26 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
ffReadFileBuffer(dir->chars, &result->status);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufAppendS(dir, "/cycle_count");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(dir->length)
result->cycleCount = (uint32_t) ffStrbufToUInt(&testBatteryBuffer, 0);
result->temperature = FF_BATTERY_TEMP_UNSET;
if (options->temp)
{
const FFlist* tempsResult = ffDetectTemps();
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
{
if (ffStrbufEqualS(&value->name, id))
{
result->temperature = value->value;
break;
}
}
}
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
@@ -84,7 +103,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
uint32_t baseDirLength = baseDir.length;
DIR* dirp = opendir(baseDir.chars);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
return "opendir(batteryDir) == NULL";
@@ -95,12 +114,10 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
continue;
ffStrbufAppendS(&baseDir, entry->d_name);
parseBattery(&baseDir, results);
parseBattery(&baseDir, entry->d_name, options, results);
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
closedir(dirp);
if(results->length == 0)
return "batteryDir doesn't contain any battery folder";
+133 -124
View File
@@ -30,137 +30,146 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
SetupDiDestroyDeviceInfoList(*hdev);
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results)
{
if(instance.config.allowSlowOperations)
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(hdev == INVALID_HANDLE_VALUE)
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
{
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(hdev == INVALID_HANDLE_VALUE)
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
if(!pdidd)
break; //Out of memory
pdidd->cbSize = sizeof(*pdidd);
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
continue;
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hBattery == INVALID_HANDLE_VALUE)
continue;
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
DWORD dwWait = 0;
DWORD dwOut;
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
continue;
BATTERY_INFORMATION bi = {0};
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
continue;
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
continue;
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
ffStrbufInitS(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
else
ffStrbufInitS(&battery->technology, "Unknown");
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
{
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
if(!pdidd)
break; //Out of memory
pdidd->cbSize = sizeof(*pdidd);
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
continue;
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hBattery == INVALID_HANDLE_VALUE)
continue;
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
DWORD dwWait = 0;
DWORD dwOut;
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
continue;
BATTERY_INFORMATION bi = {0};
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
continue;
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
continue;
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
ffStrbufInitS(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
else
ffStrbufInitS(&battery->technology, "Unknown");
{
ffStrbufInit(&battery->modelName);
bqi.InformationLevel = BatteryDeviceName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->modelName, name);
}
{
ffStrbufInit(&battery->manufacturer);
bqi.InformationLevel = BatteryManufactureName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->manufacturer, name);
}
battery->temperature = 0.0/0.0;
if(options->temp)
{
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
battery->temperature = temp;
}
{
BATTERY_STATUS bs;
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
else
battery->capacity = 0;
ffStrbufInit(&battery->status);
if(bs.PowerState & BATTERY_POWER_ON_LINE)
ffStrbufAppendS(&battery->status, "AC Connected, ");
if(bs.PowerState & BATTERY_DISCHARGING)
ffStrbufAppendS(&battery->status, "Discharging, ");
if(bs.PowerState & BATTERY_CHARGING)
ffStrbufAppendS(&battery->status, "Charging");
if(bs.PowerState & BATTERY_CRITICAL)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
}
else
{
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
battery->temperature = 0.0/0.0;
bqi.InformationLevel = BatteryDeviceName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->modelName, name);
}
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
if(info.AcOnLine)
{
ffStrbufAppendS(&battery->status, "AC Connected");
if(info.Charging)
ffStrbufAppendS(&battery->status, ", Charging");
}
else if(info.Discharging)
ffStrbufAppendS(&battery->status, "Discharging");
{
ffStrbufInit(&battery->manufacturer);
bqi.InformationLevel = BatteryManufactureName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->manufacturer, name);
}
battery->cycleCount = bi.CycleCount;
battery->temperature = 0.0/0.0;
if(options->temp)
{
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
battery->temperature = temp;
}
{
BATTERY_STATUS bs;
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
else
battery->capacity = 0;
ffStrbufInit(&battery->status);
if(bs.PowerState & BATTERY_POWER_ON_LINE)
ffStrbufAppendS(&battery->status, "AC Connected, ");
if(bs.PowerState & BATTERY_DISCHARGING)
ffStrbufAppendS(&battery->status, "Discharging, ");
if(bs.PowerState & BATTERY_CHARGING)
ffStrbufAppendS(&battery->status, "Charging, ");
if(bs.PowerState & BATTERY_CRITICAL)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
return NULL;
}
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
battery->temperature = 0.0/0.0;
battery->cycleCount = 0;
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
if(info.AcOnLine)
{
ffStrbufAppendS(&battery->status, "AC Connected");
if(info.Charging)
ffStrbufAppendS(&battery->status, ", Charging");
}
else if(info.Discharging)
ffStrbufAppendS(&battery->status, "Discharging");
return NULL;
}
return "NtPowerInformation(SystemBatteryState) failed";
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
return true
? detectWithSetupApi(options, results)
: detectWithNtApi(options, results);
}
+1
View File
@@ -11,6 +11,7 @@ typedef struct FFBiosResult
FFstrbuf release;
FFstrbuf vendor;
FFstrbuf version;
FFstrbuf type;
} FFBiosResult;
const char* ffDetectBios(FFBiosResult* bios);
+2
View File
@@ -9,5 +9,7 @@ const char* ffDetectBios(FFBiosResult* bios)
if (ffStrbufIgnCaseEqualS(&bios->version, "unknown"))
ffStrbufClear(&bios->version);
ffStrbufSetStatic(&bios->type, "Bootloader");
return NULL;
}
+3 -3
View File
@@ -23,7 +23,7 @@ const char* ffDetectBios(FFBiosResult* bios)
ffCfDictGetString(properties, CFSTR("vendor"), &bios->vendor);
ffCfDictGetString(properties, CFSTR("version"), &bios->version);
ffCfDictGetString(properties, CFSTR("release-date"), &bios->date);
ffStrbufAppendS(&bios->release, "Efi");
ffStrbufSetStatic(&bios->type, "UEFI");
CFRelease(properties);
IOObjectRelease(registryEntry);
@@ -54,12 +54,12 @@ const char* ffDetectBios(FFBiosResult* bios)
uint32_t index = ffStrbufFirstIndexC(&bios->version, '-');
if (index != bios->version.length)
{
ffStrbufAppendNS(&bios->release, index, bios->version.chars);
ffStrbufAppendNS(&bios->type, index, bios->version.chars);
ffStrbufRemoveSubstr(&bios->version, 0, index + 1);
}
else
{
ffStrbufAppendS(&bios->release, "iBoot");
ffStrbufSetStatic(&bios->type, "iBoot");
}
CFRelease(properties);
}
+2
View File
@@ -1,6 +1,7 @@
#include "bios.h"
#include "common/settings.h"
#include "common/sysctl.h"
#include "util/smbiosHelper.h"
const char* ffDetectBios(FFBiosResult* result)
@@ -13,5 +14,6 @@ const char* ffDetectBios(FFBiosResult* result)
ffCleanUpSmbiosValue(&result->vendor);
ffSettingsGetFreeBSDKenv("smbios.bios.version", &result->version);
ffCleanUpSmbiosValue(&result->version);
ffSysctlGetString("machdep.bootmethod", &result->type);
return NULL;
}
+4
View File
@@ -23,5 +23,9 @@ const char* ffDetectBios(FFBiosResult* bios)
getSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
getSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor);
getSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version);
if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE))
ffStrbufSetStatic(&bios->type, "UEFI");
else
ffStrbufSetStatic(&bios->type, "BIOS");
return NULL;
}
+37
View File
@@ -2,6 +2,30 @@
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
#include <ntstatus.h>
#include <winternl.h>
typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
{
GUID BootIdentifier;
FIRMWARE_TYPE FirmwareType;
union
{
ULONGLONG BootFlags;
struct
{
ULONGLONG DbgMenuOsSelection : 1; // REDSTONE4
ULONGLONG DbgHiberBoot : 1;
ULONGLONG DbgSoftBoot : 1;
ULONGLONG DbgMeasuredLaunch : 1;
ULONGLONG DbgMeasuredLaunchCapable : 1; // 19H1
ULONGLONG DbgSystemHiveReplace : 1;
ULONGLONG DbgMeasuredLaunchSmmProtections : 1;
ULONGLONG DbgMeasuredLaunchSmmLevel : 7; // 20H1
};
};
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
const char* ffDetectBios(FFBiosResult* bios)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
@@ -24,5 +48,18 @@ const char* ffDetectBios(FFBiosResult* bios)
)
ffStrbufAppendF(&bios->release, "%u.%u", (unsigned)major, (unsigned)minor);
// Same as GetFirmwareType, but support (?) Windows 7
// https://ntdoc.m417z.com/system_information_class
SYSTEM_BOOT_ENVIRONMENT_INFORMATION sbei;
if (NT_SUCCESS(NtQuerySystemInformation(90 /*SystemBootEnvironmentInformation*/, &sbei, sizeof(sbei), NULL)))
{
switch (sbei.FirmwareType)
{
case FirmwareTypeBios: ffStrbufSetStatic(&bios->type, "BIOS"); break;
case FirmwareTypeUefi: ffStrbufSetStatic(&bios->type, "UEFI"); break;
default: break;
}
}
return NULL;
}
+1 -1
View File
@@ -12,6 +12,6 @@ typedef struct FFBrightnessResult
double min, max, current;
} FFBrightnessResult;
const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result); // list of FFBrightnessResult
#endif
+90 -12
View File
@@ -1,9 +1,27 @@
#include "brightness.h"
#include "detection/displayserver/displayserver.h"
#include "util/apple/cf_helpers.h"
#include "util/apple/ddcci.h"
#include "util/edidHelper.h"
#include <CoreGraphics/CoreGraphics.h>
// DDC/CI
#ifdef __aarch64__
typedef CFTypeRef IOAVServiceRef;
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import));
extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import));
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import));
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import));
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import));
#else
// DDC/CI (Intel)
#include <IOKit/IOKitLib.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <IOKit/i2c/IOI2CInterface.h>
extern void CGSServiceForDisplayNumber(CGDirectDisplayID display, io_service_t* service) __attribute__((weak_import));
#endif
// ACPI
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
// Works for internal display
@@ -31,19 +49,16 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
return NULL;
}
#ifdef __aarch64__
// https://github.com/waydabber/m1ddc
// Works for Apple Silicon and USB-C adapter connection ( but not HTMI )
FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
return "IOAVService is not available";
CFMutableDictionaryRef matchDict = IOServiceMatching("DCPAVServiceProxy");
if (matchDict == NULL)
return "IOServiceMatching(\"DCPAVServiceProxy\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
@@ -78,7 +93,7 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
for (uint32_t i = 0; i < 2; ++i)
{
IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, sizeof(i2cIn));
usleep(10000);
usleep(options->ddcciSleep * 1000);
}
}
@@ -105,17 +120,80 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
return NULL;
}
#else
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available";
const char* ffDetectBrightness(FFlist* result)
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_EXTERNAL)
{
io_service_t framebuffer = 0;
CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer);
if (framebuffer == 0) continue;
IOItemCount count;
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue;
io_service_t interface = 0;
if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue;
uint8_t i2cOut[12] = {};
IOI2CConnectRef connect;
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
{
IOObjectRelease(interface);
continue;
}
uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 };
i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3];
IOI2CRequest request = {
.commFlags = kNilOptions,
.sendAddress = 0x6e,
.sendTransactionType = kIOI2CSimpleTransactionType,
.sendBuffer = (vm_address_t) i2cIn,
.sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]),
.minReplyDelay = options->ddcciSleep,
.replyAddress = 0x6F,
.replySubAddress = 0x51,
.replyTransactionType = kIOI2CDDCciReplyTransactionType,
.replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]),
.replyBuffer = (vm_address_t) i2cOut,
};
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
IOI2CInterfaceClose(connect, kNilOptions);
IOObjectRelease(interface);
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue;
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->max = max;
brightness->min = 0;
brightness->current = current;
ffStrbufInitCopy(&brightness->name, &display->name);
}
}
return NULL;
}
#endif
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result)
{
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
detectWithDisplayServices(displayServer, result);
#ifdef __aarch64__
if (displayServer->displays.length > result->length)
detectWithDdcci(result);
#endif
detectWithDdcci(displayServer, options, result);
return NULL;
}
+2 -2
View File
@@ -9,7 +9,7 @@
#include <sys/fcntl.h>
#include <unistd.h>
const char* ffDetectBrightness(FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
// https://man.freebsd.org/cgi/man.cgi?query=backlight&sektion=9
char path[] = "/dev/backlight/backlight0";
@@ -42,7 +42,7 @@ const char* ffDetectBrightness(FFlist* result)
#else
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
{
return "Backlight is supported only on FreeBSD 13 and newer";
}
+16 -5
View File
@@ -90,20 +90,31 @@ static const char* detectWithBacklight(FFlist* result)
#include "common/library.h"
#include "util/mallocHelper.h"
#include <ddcutil_macros.h>
#include <ddcutil_c_api.h>
static const char* detectWithDdcci(FFlist* result)
// Try to be compatible with ddcutil 2.0
#if DDCUTIL_VMAJOR >= 2
double ddca_set_default_sleep_multiplier(double multiplier); // ddcutil 1.4
#endif
static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
{
FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD(libddcutil, &instance.config.library.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display)
__typeof__(&ddca_set_default_sleep_multiplier) ffddca_set_default_sleep_multiplier = dlsym(libddcutil, "ddca_set_default_sleep_multiplier");
if (ffddca_set_default_sleep_multiplier)
ffddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0);
libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330
FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL;
if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0))
if (ffddca_get_display_info_list2(false, &infoList) < 0)
return "ddca_get_display_info_list2(false, &infoList) failed";
if (infoList->ct == 0)
@@ -137,14 +148,14 @@ static const char* detectWithDdcci(FFlist* result)
}
#endif
const char* ffDetectBrightness(FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
detectWithBacklight(result);
#ifdef FF_HAVE_DDCUTIL
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
if (result->length < displayServer->displays.length)
detectWithDdcci(result);
detectWithDdcci(options, result);
#endif
return NULL;
@@ -1,6 +1,6 @@
#include "brightness.h"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
{
return "Not supported on this platform";
}
@@ -73,7 +73,7 @@ static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer)
}
extern "C"
const char* ffDetectBrightness(FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
+1 -1
View File
@@ -12,7 +12,7 @@ typedef struct FFChassisResult
FFstrbuf version;
} FFChassisResult;
const char* ffDetectChassis(FFChassisResult* result);
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options);
const char* ffChassisTypeToString(uint32_t type);
#endif
+1 -1
View File
@@ -2,7 +2,7 @@
#include "common/settings.h"
#include "util/smbiosHelper.h"
const char* ffDetectChassis(FFChassisResult* result)
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
{
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
+1 -1
View File
@@ -17,7 +17,7 @@ static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstr
ffStrbufClear(buffer);
}
const char* ffDetectChassis(FFChassisResult* result)
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
{
getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
+1 -1
View File
@@ -1,6 +1,6 @@
#include "chassis.h"
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
{
return "Not supported on this platform";
}
+3 -3
View File
@@ -36,7 +36,7 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
{
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
if(len == 0)
return "ChassisTypes contain no data failed";
return "ChassisTypes contain no data";
for (uint32_t i = 0; i < len; ++i)
{
if (i > 0)
@@ -65,9 +65,9 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
}
extern "C"
const char* ffDetectChassis(FFChassisResult* result)
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
{
if (instance.config.allowSlowOperations)
if (options->useWmi)
return detectWithWmi(result);
return detectWithRegistry(result);
}
+1 -5
View File
@@ -29,12 +29,8 @@ static const char* detectFrequency(FFCPUResult* cpu)
{
// https://github.com/giampaolo/psutil/pull/2222/files
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleARMIODevice");
if (matchDict == NULL)
return "IOServiceMatching(\"AppleARMIODevice\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
+4 -1
View File
@@ -16,7 +16,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
ffDetectThermalTemp(&cpu->temperature);
{
if (!ffDetectCpuTemp(&cpu->temperature))
ffDetectThermalTemp(&cpu->temperature);
}
return NULL;
}
+8 -5
View File
@@ -47,7 +47,8 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
ffParsePropLine(line, "isa :", cpuIsa) ||
ffParsePropLine(line, "uarch :", cpuUarch) ||
(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 :", &cpu->name)) || //For POWER
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
);
}
@@ -82,12 +83,10 @@ static double getFrequency(const char* info, const char* scaling)
static double detectCPUTemp(void)
{
const FFTempsResult* temps = ffDetectTemps();
const FFlist* tempsResult = ffDetectTemps();
for(uint32_t i = 0; i < temps->values.length; i++)
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
{
FFTempValue* value = ffListGet(&temps->values, i);
if(
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
@@ -115,6 +114,10 @@ static void parseIsa(FFstrbuf* cpuIsa)
}
// The final ISA output of the above example is "rv64gch".
}
if(ffStrbufStartsWithS(cpuIsa, "mips"))
{
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
}
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
+39 -23
View File
@@ -4,42 +4,58 @@
#include <stdint.h>
// We need to use uint64_t because sizeof(long) == 4 on Windows
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
static uint64_t inUseAll1, totalAll1;
static FFlist cpuTimes1;
void ffPrepareCPUUsage(void)
{
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
assert(cpuTimes1.elementSize == 0);
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
ffGetCpuUsageInfo(&cpuTimes1);
}
const char* ffGetCpuUsageResult(double* result)
const char* ffGetCpuUsageResult(FFlist* result)
{
const char* error = NULL;
if(inUseAll1 == 0 && totalAll1 == 0)
if(cpuTimes1.elementSize == 0)
{
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
if(error)
return error;
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
error = ffGetCpuUsageInfo(&cpuTimes1);
if(error) return error;
ffTimeSleep(200);
}
while(true)
{
uint64_t inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
if(error)
return error;
if(cpuTimes1.length == 0) return "No CPU cores found";
if(inUseAll2 != inUseAll1)
FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo));
uint32_t retryCount = 0;
retry:
error = ffGetCpuUsageInfo(&cpuTimes2);
if(error) return error;
if(cpuTimes1.length != cpuTimes2.length) return "Unexpected CPU usage result";
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
{
FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i);
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
if (cpuTime2->totalAll <= cpuTime1->totalAll)
{
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
inUseAll1 = inUseAll2;
totalAll1 = totalAll2;
return NULL;
if (++retryCount <= 3)
{
ffListClear(&cpuTimes2);
ffTimeSleep(200);
goto retry;
}
}
else
ffTimeSleep(200);
}
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
{
FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i);
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
*(double*) ffListAdd(result) = (double)(cpuTime2->inUseAll - cpuTime1->inUseAll) / (double)(cpuTime2->totalAll - cpuTime1->totalAll) * 100;
cpuTime1->inUseAll = cpuTime2->inUseAll;
cpuTime1->totalAll = cpuTime2->totalAll;
}
return NULL;
}
+9 -1
View File
@@ -3,6 +3,14 @@
#ifndef FF_INCLUDED_detection_cpuusage_cpuusage
#define FF_INCLUDED_detection_cpuusage_cpuusage
const char* ffGetCpuUsageResult(double* result);
#include "fastfetch.h"
typedef struct FFCpuUsageInfo {
uint64_t inUseAll;
uint64_t totalAll;
} FFCpuUsageInfo;
const char* ffGetCpuUsageInfo(FFlist* cpuTimes);
const char* ffGetCpuUsageResult(FFlist* result); // list of double
#endif
+20 -11
View File
@@ -4,20 +4,29 @@
#include <mach/processor_info.h>
#include <mach/mach_host.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
host_cpu_load_info_data_t cpustats;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
natural_t numCPUs = 0U;
processor_info_array_t cpuInfo;
mach_msg_type_number_t numCpuInfo;
*inUseAll = *totalAll = 0;
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS)
return "host_processor_info() failed";
if (numCPUs * CPU_STATE_MAX != numCpuInfo)
return "Unexpected host_processor_info() result";
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)(&cpustats), &count) != KERN_SUCCESS)
return "host_statistics() failed";
*inUseAll = cpustats.cpu_ticks[CPU_STATE_USER]
+ cpustats.cpu_ticks[CPU_STATE_SYSTEM]
+ cpustats.cpu_ticks[CPU_STATE_NICE];
*totalAll = *inUseAll + cpustats.cpu_ticks[CPU_STATE_IDLE];
for (natural_t i = 0U; i < numCPUs; ++i)
{
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
}
+26 -9
View File
@@ -1,19 +1,36 @@
#include "detection/cpuusage/cpuusage.h"
#include "util/mallocHelper.h"
#include <sys/types.h>
#include <sys/user.h>
#include <sys/sysctl.h>
#include <sys/resource.h>
#include <stdlib.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
// interrupt processing, user processes, system processing, lock spinning, and idling
uint64_t cpTime[5];
size_t neededLength = sizeof(cpTime);
if(sysctlbyname("kern.cp_time", cpTime, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_time) failed";
size_t neededLength = 0;
if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_times, NULL) failed";
*inUseAll = cpTime[0] + cpTime[1] + cpTime[2] + cpTime[3];
*totalAll = *inUseAll + cpTime[4];
uint32_t coreCount = (uint32_t) (neededLength / (CPUSTATES * sizeof(uint64_t)));
assert(coreCount > 0);
FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength);
if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_times, cpTime) failed";
for (uint32_t i = 0; i < coreCount; ++i)
{
uint64_t* cpTime = cpTimes[i];
uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS];
uint64_t total = cpTime[CP_INTR] + cpTime[CP_IDLE];
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
}
+16 -11
View File
@@ -1,14 +1,13 @@
#include "fastfetch.h"
#include "detection/cpuusage/cpuusage.h"
#include "common/io/io.h"
#include <stdio.h>
#include <inttypes.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
FILE* procStat = fopen("/proc/stat", "r");
FF_AUTO_CLOSE_FILE FILE* procStat = fopen("/proc/stat", "r");
if(procStat == NULL)
{
#ifdef __ANDROID__
@@ -17,16 +16,22 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
return "fopen(\"""/proc/stat\", \"r\") == NULL";
#endif
}
// Skip first line
if (fscanf(procStat, "cpu%*[^\n]\n") < 0)
return "fscanf() first line failed";
if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7)
{
fclose(procStat);
return "fscanf() failed";
}
*inUseAll = user + nice + system;
*totalAll = *inUseAll + idle + iowait + irq + softirq;
uint64_t inUse = user + nice + system;
uint64_t total = inUse + idle + iowait + irq + softirq;
fclose(procStat);
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
}
+9 -6
View File
@@ -6,7 +6,7 @@
#include <ntstatus.h>
#include <winternl.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
ULONG size = 0;
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
@@ -16,8 +16,6 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size)))
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, size) failed";
*inUseAll = *totalAll = 0;
for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i)
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i;
@@ -28,9 +26,14 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart;
coreInfo->KernelTime.QuadPart += dpcTime + interruptTime;
LONGLONG inUse = coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart;
*inUseAll += (uint64_t)inUse;
*totalAll += (uint64_t)(inUse + coreInfo->IdleTime.QuadPart);
uint64_t inUse = (uint64_t) (coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart);
uint64_t total = inUse + (uint64_t)coreInfo->IdleTime.QuadPart;
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "fastfetch.h"
const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options);
+173
View File
@@ -0,0 +1,173 @@
#include "de.h"
#include "common/io/io.h"
#include "common/parsing.h"
#include "common/properties.h"
#include "common/processing.h"
#include "detection/displayserver/displayserver.h"
#include "util/stringUtils.h"
#include <ctype.h>
static void getKDE(FFstrbuf* result, FFDEOptions* options)
{
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
{"X-KDE-PluginInfo-Version =", result}
});
if(result->length == 0)
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
if(result->length == 0)
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", result);
if(result->length == 0)
{
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
{"X-KDE-PluginInfo-Version =", result}
});
}
if(result->length == 0)
ffParsePropFileData("wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", result);
if(result->length == 0)
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", result);
if(result->length == 0 && options->slowVersionDetection)
{
if (ffProcessAppendStdOut(result, (char* const[]){
"plasmashell",
"--version",
NULL
}) == NULL) // plasmashell 5.27.5
ffStrbufSubstrAfterLastC(result, ' ');
}
}
static void getGnome(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
ffParsePropFileData("gnome-shell/org.gnome.Extensions", "version :", result);
if (result->length == 0)
{
if (ffProcessAppendStdOut(result, (char* const[]){
"gnome-shell",
"--version",
NULL
}) == NULL) // GNOME Shell 44.1
ffStrbufSubstrAfterLastC(result, ' ');
}
}
static void getCinnamon(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
ffParsePropFileData("applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", result);
}
static void getMate(FFstrbuf* result, FFDEOptions* options)
{
FF_STRBUF_AUTO_DESTROY major = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY minor = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY micro = ffStrbufCreate();
ffParsePropFileDataValues("mate-about/mate-version.xml", 3, (FFpropquery[]) {
{"<platform>", &major},
{"<minor>", &minor},
{"<micro>", &micro}
});
ffParseSemver(result, &major, &minor, &micro);
if(result->length == 0 && options->slowVersionDetection)
{
ffProcessAppendStdOut(result, (char* const[]){
"mate-session",
"--version",
NULL
});
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufTrim(result, ' ');
}
}
static void getXFCE4(FFstrbuf* result, FFDEOptions* options)
{
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", result);
#ifdef __FreeBSD__
if(result->length == 0)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/");
if (dirp)
{
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5]))
continue;
ffStrbufAppendS(result, &entry->d_name[5]);
}
}
}
#endif
if(result->length == 0 && options->slowVersionDetection)
{
//This is somewhat slow
ffProcessAppendStdOut(result, (char* const[]){
"xfce4-session",
"--version",
NULL
});
ffStrbufSubstrBeforeFirstC(result, '(');
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufTrim(result, ' ');
}
}
static void getLXQt(FFstrbuf* result, FFDEOptions* options)
{
ffParsePropFileData("gconfig/lxqt.pc", "Version:", result);
if(result->length == 0)
ffParsePropFileData("cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", result);
if(result->length == 0)
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", result);
if(result->length == 0 && options->slowVersionDetection)
{
//This is really, really, really slow. Thank you, LXQt developers
ffProcessAppendStdOut(result, (char* const[]){
"lxqt-session",
"-v",
NULL
});
result->length = 0; //don't set '\0' byte
ffParsePropLines(result->chars , "liblxqt", result);
}
}
static void getBudgie(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
ffParsePropFileData("budgie/budgie-version.xml", "<str>", result);
}
const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options)
{
if (ffStrbufEqualS(deName, FF_DE_PRETTY_PLASMA))
getKDE(result, options);
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_GNOME) || ffStrbufEqualS(deName, FF_DE_PRETTY_GNOME))
getGnome(result, options);
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_CINNAMON))
getCinnamon(result, options);
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_XFCE4))
getXFCE4(result, options);
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_MATE))
getMate(result, options);
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_LXQT))
getLXQt(result, options);
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_BUDGIE))
getBudgie(result, options);
else
return "Unsupported DE";
return NULL;
}
+6
View File
@@ -0,0 +1,6 @@
#include "de.h"
const char* ffDetectDEVersion(FF_MAYBE_UNUSED const FFstrbuf* deName, FF_MAYBE_UNUSED FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
{
return "Not supported on this platform";
}
-8
View File
@@ -5,13 +5,6 @@
#include "fastfetch.h"
typedef enum FFDiskPhysicalType
{
FF_DISK_PHYSICAL_TYPE_UNKNOWN,
FF_DISK_PHYSICAL_TYPE_HDD,
FF_DISK_PHYSICAL_TYPE_SSD,
} FFDiskPhysicalType;
typedef struct FFDisk
{
FFstrbuf mountFrom;
@@ -19,7 +12,6 @@ typedef struct FFDisk
FFstrbuf filesystem;
FFstrbuf name;
FFDiskVolumeType type;
FFDiskPhysicalType physicalType;
uint64_t bytesUsed;
uint64_t bytesFree;
+2 -1
View File
@@ -21,6 +21,8 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk)
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
}
#elif __APPLE__
#include "util/apple/cf_helpers.h"
#include <sys/attr.h>
#include <unistd.h>
@@ -71,7 +73,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
#endif
FFDisk* disk = ffListAdd(disks);
disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
disk->bytesTotal = fs->f_blocks * fs->f_bsize;
disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize;
+5 -17
View File
@@ -195,7 +195,7 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk)
return false;
}
static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk)
static bool isRemovable(FFDisk* currentDisk)
{
// https://stackoverflow.com/a/73302025
// Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does.
@@ -218,20 +218,10 @@ static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk)
if (!ffStrStartsWith(partitionName, entry->d_name)) continue;
ffStrbufAppendS(&basePath, entry->d_name);
index = basePath.length;
// /sys/block/sdx/queue/rotational
ffStrbufAppendS(&basePath, "/queue/rotational");
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffReadFileBuffer(basePath.chars, &buffer))
currentDisk->physicalType = ffStrbufEqualS(&buffer, "1") ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD;
else
currentDisk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
ffStrbufSubstrBefore(&basePath, index);
// /sys/block/sdx/removable
ffStrbufAppendS(&basePath, entry->d_name);
ffStrbufAppendS(&basePath, "/removable");
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1");
}
@@ -240,10 +230,9 @@ static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk)
static void detectType(const FFlist* disks, FFDisk* currentDisk)
{
bool isRemovable = detectPhysicalTypeAndReturnRemovable(currentDisk);
if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return;
if(isRemovable)
if(isRemovable(currentDisk))
currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else if(isSubvolume(disks, currentDisk))
currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT;
@@ -289,7 +278,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
//We have a valid device, add it to the list
FFDisk* disk = ffListAdd(disks);
disk->type = FF_DISK_VOLUME_TYPE_NONE;
disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
//detect mountFrom
ffStrbufInitS(&disk->mountFrom, device->mnt_fsname);
-29
View File
@@ -28,37 +28,8 @@ const char* ffDetectDisksImpl(FFlist* disks)
ffStrbufInitWS(&disk->mountpoint, mountpoint);
wchar_t volumeName[64];
disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
if(mountpoint[1] == ':')
{
memcpy(volumeName, L"\\\\.\\ :", sizeof(L"\\\\.\\ :"));
volumeName[4] = mountpoint[0];
FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(volumeName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (handle != INVALID_HANDLE_VALUE)
{
DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {};
if(DeviceIoControl(
handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&(STORAGE_PROPERTY_QUERY) {
.PropertyId = StorageDeviceSeekPenaltyProperty,
.QueryType = PropertyStandardQuery,
},
sizeof(STORAGE_PROPERTY_QUERY),
&dspd,
sizeof(dspd),
NULL,
NULL
))
disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD;
}
}
if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
{
ffStrbufInitWS(&disk->mountFrom, volumeName);
}
else
ffStrbufInit(&disk->mountFrom);
+67
View File
@@ -0,0 +1,67 @@
#include "diskio.h"
#include "common/time.h"
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options);
static FFlist ioCounters1;
static uint64_t time1;
void ffPrepareDiskIO(FFDiskIOOptions* options)
{
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
ffDiskIOGetIoCounters(&ioCounters1, options);
time1 = ffTimeGetNow();
}
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options)
{
const char* error = NULL;
if (time1 == 0)
{
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
error = ffDiskIOGetIoCounters(&ioCounters1, options);
if (error)
return error;
time1 = ffTimeGetNow();
}
if (ioCounters1.length == 0)
return "No physical disk found";
uint64_t time2 = ffTimeGetNow();
while (time2 - time1 < 1000)
{
ffTimeSleep((uint32_t) (1000 - (time2 - time1)));
time2 = ffTimeGetNow();
}
error = ffDiskIOGetIoCounters(result, options);
if (error)
return error;
if (result->length != ioCounters1.length)
return "Different number of physical disks. Hardware change?";
for (uint32_t i = 0; i < result->length; ++i)
{
FFDiskIOResult* icPrev = (FFDiskIOResult*)ffListGet(&ioCounters1, i);
FFDiskIOResult* icCurr = (FFDiskIOResult*)ffListGet(result, i);
if (!ffStrbufEqual(&icPrev->name, &icCurr->name))
return "Network interface name changed";
static_assert(sizeof(FFDiskIOResult) - offsetof(FFDiskIOResult, bytesRead) == sizeof(uint64_t) * 4, "Unexpected struct FFDiskIOResult layout");
for (size_t off = offsetof(FFDiskIOResult, bytesRead); off < sizeof(FFDiskIOResult); off += sizeof(uint64_t))
{
uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off);
uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off);
uint64_t temp = *currValue;
*currValue -= *prevValue;
*currValue /= (time2 - time1) / 1000 /* seconds */;
*prevValue = temp;
}
}
time1 = time2;
return NULL;
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "fastfetch.h"
typedef enum FFDiskIOPhysicalType
{
FF_DISKIO_PHYSICAL_TYPE_UNKNOWN,
FF_DISKIO_PHYSICAL_TYPE_HDD,
FF_DISKIO_PHYSICAL_TYPE_SSD,
} FFDiskIOPhysicalType;
typedef struct FFDiskIOResult
{
FFstrbuf name;
FFstrbuf interconnect;
FFDiskIOPhysicalType type;
FFstrbuf devPath;
uint64_t bytesRead;
uint64_t readCount;
uint64_t bytesWritten;
uint64_t writeCount;
} FFDiskIOResult;
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options);
+89
View File
@@ -0,0 +1,89 @@
#include "diskio.h"
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOBlockStorageDriver.h>
#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)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
io_name_t deviceName;
if (IORegistryEntryGetName(registryEntry, deviceName) != KERN_SUCCESS)
continue;
if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0)
continue;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDriver = 0;
if (IORegistryEntryGetParentEntry(entryPartition, kIOServicePlane, &entryDriver) != KERN_SUCCESS)
continue;
if (!IOObjectConformsTo(entryDriver, kIOBlockStorageDriverClass)) // physical disk only
continue;
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef statistics = IORegistryEntryCreateCFProperty(entryDriver, CFSTR(kIOBlockStorageDriverStatisticsKey), kCFAllocatorDefault, kNilOptions);
if (!statistics)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInitS(&device->name, deviceName);
ffStrbufInit(&device->devPath);
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey), (int64_t*) &device->bytesRead);
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey), (int64_t*) &device->bytesWritten);
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey), (int64_t*) &device->readCount);
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey), (int64_t*) &device->writeCount);
FF_CFTYPE_AUTO_RELEASE CFStringRef bsdName = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions);
if (bsdName)
{
ffCfStrGetString(bsdName, &device->devPath);
ffStrbufPrependS(&device->devPath, "/dev/");
}
ffStrbufInit(&device->interconnect);
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0;
if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS)
{
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
if (protocolCharacteristics)
ffCfDictGetString(protocolCharacteristics, CFSTR("Physical Interconnect"), &device->interconnect);
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
if (deviceCharacteristics)
{
CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey));
if (mediumType)
{
if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0)
device->type = FF_DISKIO_PHYSICAL_TYPE_SSD;
else if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0)
device->type = FF_DISKIO_PHYSICAL_TYPE_HDD;
}
}
}
}
return NULL;
}
+51
View File
@@ -0,0 +1,51 @@
#include "diskio.h"
#include <devstat.h>
#include <memory.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
if (devstat_checkversion(NULL) < 0)
return "devstat_checkversion() failed";
struct statinfo stats = {
.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)),
};
if (devstat_getdevs(NULL, &stats) < 0)
return "devstat_getdevs() failed";
for (int i = 0; i < stats.dinfo->numdevs; i++)
{
struct devstat* current = &stats.dinfo->devices[i];
if (current->device_type & DEVSTAT_TYPE_PASS)
continue;
char deviceName[128];
snprintf(deviceName, sizeof(deviceName), "%s%d", current->device_name, current->unit_number);
if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInitS(&device->name, deviceName);
ffStrbufInitF(&device->devPath, "/dev/%s", deviceName);
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
ffStrbufInit(&device->interconnect);
switch (current->device_type & DEVSTAT_TYPE_IF_MASK)
{
case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break;
case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break;
case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break;
}
device->bytesRead = current->bytes[DEVSTAT_READ];
device->readCount = current->operations[DEVSTAT_READ];
device->bytesWritten = current->bytes[DEVSTAT_WRITE];
device->writeCount = current->operations[DEVSTAT_WRITE];
}
if (stats.dinfo->mem_ptr)
free(stats.dinfo->mem_ptr);
free(stats.dinfo);
return NULL;
}
+108
View File
@@ -0,0 +1,108 @@
#include "diskio.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include <ctype.h>
#include <limits.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS("/dev/disk/by-id/");
uint32_t baseDirLength = baseDir.length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
return "opendir(batteryDir) == NULL";
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.')
continue;
char* part = strstr(entry->d_name, "-part");
if (part && isdigit(part[strlen("-part")]))
continue;
if (ffStrStartsWith(entry->d_name, "nvme-eui.")) // NVMe drive indentifier
continue;
// Other exceptions?
ffStrbufAppendS(&baseDir, entry->d_name);
char pathDev[PATH_MAX];
ssize_t pathLen = readlink(baseDir.chars, pathDev, PATH_MAX);
ffStrbufSubstrBefore(&baseDir, baseDirLength);
if (pathLen < 0) continue;
pathDev[pathLen] = '\0'; // ../../nvme0n1
char pathDev1[PATH_MAX];
const char* devName = basename(pathDev);
snprintf(pathDev1, PATH_MAX, "/dev/%s", devName);
// Avoid duplicated disks
bool flag = false;
FF_LIST_FOR_EACH(FFDiskIOResult, disk, *result)
{
if (ffStrbufEqualS(&disk->devPath, pathDev1))
{
flag = true;
break;
}
}
if (flag) continue;
char pathSysBlock[PATH_MAX];
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/stat", devName);
FF_AUTO_CLOSE_FILE FILE* sysBlockStat = fopen(pathSysBlock, "r");
if (!sysBlockStat) continue;
// I/Os merges sectors ticks ...
uint64_t nRead, sectorRead, nWritten, sectorWritten;
if (fscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) == 0)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
char* slash = strchr(entry->d_name, '-');
if (slash)
{
char* slash2 = strchr(slash + 1, '-');
if (slash2)
ffStrbufInitNS(&device->name, (uint32_t) (slash2 - slash - 1), slash + 1);
else
ffStrbufInitS(&device->name, slash + 1);
ffStrbufInitNS(&device->interconnect, (uint32_t) (slash - entry->d_name), entry->d_name);
}
else
{
ffStrbufInitS(&device->name, entry->d_name);
ffStrbufInit(&device->interconnect);
}
ffStrbufReplaceAllC(&device->name, '_', ' ');
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->interconnect);
result->length--;
continue;
}
ffStrbufInitS(&device->devPath, pathDev1);
device->bytesRead = sectorRead * 512;
device->bytesWritten = sectorWritten * 512;
device->readCount = nRead;
device->writeCount = nWritten;
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffReadFileBuffer(pathSysBlock, &buffer))
device->type = ffStrbufEqualS(&buffer, "1") ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD;
else
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
}
return NULL;
}
+89
View File
@@ -0,0 +1,89 @@
#include "diskio.h"
#include "common/io/io.h"
#include "util/windows/registry.h"
#include "util/windows/unicode.h"
#include <winioctl.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum\") failed";
uint32_t nDevices;
if (!ffRegReadUint(hKey, L"Count", &nDevices, NULL))
return "ffRegReadUint(hKey, L\"Count\", &nDevices) failed";
wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive";
wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive");
for (uint32_t idev = 0; idev <= nDevices; ++idev) {
_ultow(idev, pNum, 10);
FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
continue;
DISK_PERFORMANCE diskPerformance;
DWORD ioctrlSize = sizeof(diskPerformance);
DWORD dwSize;
if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance, ioctrlSize, &dwSize, NULL))
{
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInit(&device->name);
ffStrbufInit(&device->interconnect);
if (ffRegReadStrbuf(hKey, pNum, &device->name, NULL))
{
// SCSI\Disk&Ven_NVMe&Prod_WDC_PC_SN810_SDC\5&19cebb7&0&000000
uint32_t index = ffStrbufFirstIndexC(&device->name, '\\');
if (index != device->name.length)
{
ffStrbufAppendNS(&device->interconnect, index, device->name.chars); // SCSI
ffStrbufSubstrAfter(&device->name, index);
}
ffStrbufSubstrBeforeLastC(&device->name, '\\');
ffStrbufSubstrAfterFirstS(&device->name, "&Ven_");
ffStrbufRemoveS(&device->name, "&Prod");
ffStrbufReplaceAllC(&device->name, '_', ' ');
ffStrbufTrim(&device->name, ' ');
}
else
ffStrbufSetWS(&device->name, szDevice);
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->interconnect);
result->length--;
continue;
}
ffStrbufInitWS(&device->devPath, szDevice);
device->bytesRead = (uint64_t) diskPerformance.BytesRead.QuadPart;
device->readCount = (uint64_t) diskPerformance.ReadCount;
device->bytesWritten = (uint64_t) diskPerformance.BytesWritten.QuadPart;
device->writeCount = (uint64_t) diskPerformance.WriteCount;
DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {};
DWORD retSize = 0;
if(DeviceIoControl(
hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&(STORAGE_PROPERTY_QUERY) {
.PropertyId = StorageDeviceSeekPenaltyProperty,
.QueryType = PropertyStandardQuery,
},
sizeof(STORAGE_PROPERTY_QUERY),
&dspd,
sizeof(dspd),
&retSize,
NULL
) && retSize == sizeof(dspd))
device->type = dspd.IncursSeekPenalty ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD;
else
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
}
}
return NULL;
}
@@ -68,7 +68,6 @@ typedef struct FFDisplayServerResult
FFstrbuf wmProtocolName;
FFstrbuf deProcessName;
FFstrbuf dePrettyName;
FFstrbuf deVersion;
FFlist displays; //List of FFDisplayResult
} FFDisplayServerResult;
@@ -75,7 +75,7 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
{
// Only for MiUI
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
;
if (ffSettingsGetAndroidProperty("persist.sys.miui_resolution", &buffer) &&
ffStrbufContainC(&buffer, ','))
{
@@ -107,7 +107,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
ffStrbufInit(&ds->wmProtocolName);
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 0);
if (!detectWithGetprop(ds))
@@ -1,10 +1,7 @@
#include "displayserver.h"
#include "common/sysctl.h"
#include "util/apple/cf_helpers.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <CoreGraphics/CGDirectDisplay.h>
@@ -70,35 +67,6 @@ static void detectDisplays(FFDisplayServerResult* ds)
}
}
static void detectWMPlugin(FFstrbuf* name)
{
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
u_int requestLength = sizeof(request) / sizeof(*request);
size_t length = 0;
FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length);
if(processes == NULL)
return;
for(size_t i = 0; i < length / sizeof(struct kinfo_proc); i++)
{
const char* comm = processes[i].kp_proc.p_comm;
if(
strcasecmp(comm, "spectacle") != 0 &&
strcasecmp(comm, "amethyst") != 0 &&
strcasecmp(comm, "kwm") != 0 &&
strcasecmp(comm, "chunkwm") != 0 &&
strcasecmp(comm, "yabai") != 0 &&
strcasecmp(comm, "rectangle") != 0
) continue;
ffStrbufAppendS(name, comm);
name->chars[0] = (char) toupper(name->chars[0]);
break;
}
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
{
@@ -116,18 +84,8 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
ffStrbufInit(&ds->wmProtocolName);
if(instance.config.allowSlowOperations)
{
FF_STRBUF_AUTO_DESTROY name;
ffStrbufInit(&name);
detectWMPlugin(&name);
if(name.length)
ffStrbufAppendF(&ds->wmPrettyName, " (with %s)", name.chars);
}
ffStrbufInit(&ds->deProcessName);
ffStrbufInitStatic(&ds->dePrettyName, "Aqua");
ffStrbufInit(&ds->deVersion);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
detectDisplays(ds);
@@ -143,20 +143,21 @@ static void detectDisplays(FFDisplayServerResult* ds)
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
BOOL enabled;
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled == TRUE)
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{
ffStrbufInitStatic(&ds->wmProcessName, "dwm.exe");
ffStrbufInitStatic(&ds->wmPrettyName, "Desktop Window Manager");
}
else
{
// `explorer.exe` only provides a subset of WM functions, as well as the taskbar and desktop icons.
// While a window itself is drawn by kernel (GDI). Killing `explorer.exe` won't affect how windows are displayed generally.
ffStrbufInitStatic(&ds->wmProcessName, "explorer.exe");
ffStrbufInitStatic(&ds->wmPrettyName, "Windows Explorer");
ffStrbufInitStatic(&ds->wmPrettyName, "Internal");
}
ffStrbufInit(&ds->wmProtocolName);
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInit(&ds->displays, sizeof(FFDisplayResult));
detectDisplays(ds);
@@ -85,10 +85,9 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
ffStrbufInit(&ds->wmProtocolName);
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
if (!instance.config.dsForceDrm)
if (!instance.config.general.dsForceDrm)
{
//We try wayland as our prefered display server, as it supports the most features.
//This method can't detect the name of our WM / DE
+1 -6
View File
@@ -202,9 +202,6 @@ static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* regist
if(display.width <= 0 || display.height <= 0)
return;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
ffThreadMutexLock(&mutex);
switch(display.transform)
{
case WL_OUTPUT_TRANSFORM_90:
@@ -262,8 +259,6 @@ static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* regist
ffStrbufDestroy(&display.vendorAndModelId);
ffStrbufDestroy(&display.name);
ffStrbufDestroy(&display.edidName);
ffThreadMutexUnlock(&mutex);
}
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
@@ -276,7 +271,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
bool detectWayland(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(wayland, &instance.config.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
+36 -179
View File
@@ -1,7 +1,6 @@
#include "displayserver_linux.h"
#include "common/io/io.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "common/processing.h"
#include "util/stringUtils.h"
@@ -131,177 +130,6 @@ static void applyBetterWM(FFDisplayServerResult* result, const char* processName
ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName);
}
static void getKDE(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "plasmashell");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
{"X-KDE-PluginInfo-Version =", &result->deVersion}
});
if(result->deVersion.length == 0)
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
{
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
{"X-KDE-PluginInfo-Version =", &result->deVersion}
});
}
if(result->deVersion.length == 0)
ffParsePropFileData("wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
{
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"plasmashell",
"--version",
NULL
}) == NULL) // plasmashell 5.27.5
ffStrbufSubstrAfterLastC(&result->deVersion, ' ');
}
applyBetterWM(result, getenv("KDEWM"));
}
static void getGnome(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "gnome-shell");
const char* sessionMode = getenv("GNOME_SHELL_SESSION_MODE");
if (sessionMode && ffStrEquals(sessionMode, "classic"))
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC);
else
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME);
ffParsePropFileData("gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
if (result->deVersion.length == 0)
{
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"gnome-shell",
"--version",
NULL
}) == NULL) // GNOME Shell 44.1
ffStrbufSubstrAfterLastC(&result->deVersion, ' ');
}
}
static void getCinnamon(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "cinnamon");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
ffParsePropFileData("applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
}
static void getMate(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "mate-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
FF_STRBUF_AUTO_DESTROY major = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY minor = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY micro = ffStrbufCreate();
ffParsePropFileDataValues("mate-about/mate-version.xml", 3, (FFpropquery[]) {
{"<platform>", &major},
{"<minor>", &minor},
{"<micro>", &micro}
});
ffParseSemver(&result->deVersion, &major, &minor, &micro);
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
{
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"mate-session",
"--version",
NULL
});
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
ffStrbufTrim(&result->deVersion, ' ');
}
}
static void getXFCE4(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "xfce4-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
#ifdef __FreeBSD__
if(result->deVersion.length == 0)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/");
if (dirp)
{
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5]))
continue;
ffStrbufAppendS(&result->deVersion, &entry->d_name[5]);
}
}
}
#endif
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
{
//This is somewhat slow
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"xfce4-session",
"--version",
NULL
});
ffStrbufSubstrBeforeFirstC(&result->deVersion, '(');
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
ffStrbufTrim(&result->deVersion, ' ');
}
}
static void getLXQt(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
ffParsePropFileData("gconfig/lxqt.pc", "Version:", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFileData("cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
{
//This is really, really, really slow. Thank you, LXQt developers
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"lxqt-session",
"-v",
NULL
});
result->deVersion.length = 0; //don't set '\0' byte
ffParsePropLines(result->deVersion.chars , "liblxqt", &result->deVersion);
}
FF_STRBUF_AUTO_DESTROY wmProcessNameBuffer = ffStrbufCreate();
ffParsePropFileConfig("lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
applyBetterWM(result, wmProcessNameBuffer.chars);
}
static void getBudgie(FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
ffParsePropFileData("budgie/budgie-version.xml", "<str>", &result->deVersion);
}
static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
@@ -312,19 +140,33 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
strcasecmp(name, "plasma") == 0 ||
strcasecmp(name, "plasmashell") == 0 ||
strcasecmp(name, "plasmawayland") == 0
) getKDE(result);
) {
ffStrbufSetStatic(&result->deProcessName, "plasmashell");
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
applyBetterWM(result, getenv("KDEWM"));
}
else if(
strcasecmp(name, "Gnome") == 0 ||
strcasecmp(name, "ubuntu:GNOME") == 0 ||
strcasecmp(name, "ubuntu") == 0 ||
strcasecmp(name, "gnome-shell") == 0
) getGnome(result);
) {
ffStrbufSetStatic(&result->deProcessName, "gnome-shell");
const char* sessionMode = getenv("GNOME_SHELL_SESSION_MODE");
if (sessionMode && ffStrEquals(sessionMode, "classic"))
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC);
else
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_GNOME);
}
else if(
strcasecmp(name, "X-Cinnamon") == 0 ||
strcasecmp(name, "Cinnamon") == 0
) getCinnamon(result);
) {
ffStrbufSetS(&result->deProcessName, "cinnamon");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
}
else if(
strcasecmp(name, "XFCE") == 0 ||
@@ -332,26 +174,41 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
strcasecmp(name, "XFCE4") == 0 ||
strcasecmp(name, "X-XFCE4") == 0 ||
strcasecmp(name, "xfce4-session") == 0
) getXFCE4(result);
) {
ffStrbufSetS(&result->deProcessName, "xfce4-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
}
else if(
strcasecmp(name, "MATE") == 0 ||
strcasecmp(name, "X-MATE") == 0 ||
strcasecmp(name, "mate-session") == 0
) getMate(result);
) {
ffStrbufSetS(&result->deProcessName, "mate-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
}
else if(
strcasecmp(name, "LXQt") == 0 ||
strcasecmp(name, "X-LXQT") == 0 ||
strcasecmp(name, "lxqt-session") == 0
) getLXQt(result);
) {
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
FF_STRBUF_AUTO_DESTROY wmProcessNameBuffer = ffStrbufCreate();
ffParsePropFileConfig("lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
applyBetterWM(result, wmProcessNameBuffer.chars);
}
else if(
strcasecmp(name, "Budgie") == 0 ||
strcasecmp(name, "X-Budgie") == 0 ||
strcasecmp(name, "budgie-desktop") == 0 ||
strcasecmp(name, "Budgie:GNOME") == 0
) getBudgie(result);
) {
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
}
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
+2 -2
View File
@@ -100,7 +100,7 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect
void ffdsConnectXcb(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcb, &instance.config.libXcb, , "libxcb" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD(xcb, &instance.config.library.libXcb, , "libxcb" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_connect,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_get_setup,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_setup_roots_iterator,)
@@ -429,7 +429,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
void ffdsConnectXcbRandr(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcbRandr, &instance.config.libXcbRandr, , "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD(xcbRandr, &instance.config.library.libXcbRandr, , "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_connect,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_get_setup,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_setup_roots_iterator,)
+2 -2
View File
@@ -60,7 +60,7 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl
void ffdsConnectXlib(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(x11, &instance.config.libX11, , "libX11" FF_LIBRARY_EXTENSION, 7, "libX11-xcb" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD(x11, &instance.config.library.libX11, , "libX11" FF_LIBRARY_EXTENSION, 7, "libX11-xcb" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL(x11, XOpenDisplay,)
FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay,)
@@ -338,7 +338,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
void ffdsConnectXrandr(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xrandr, &instance.config.libXrandr, , "libXrandr" FF_LIBRARY_EXTENSION, 3)
FF_LIBRARY_LOAD(xrandr, &instance.config.library.libXrandr, , "libXrandr" FF_LIBRARY_EXTENSION, 3)
FF_LIBRARY_LOAD_SYMBOL(xrandr, XOpenDisplay,)
FF_LIBRARY_LOAD_SYMBOL(xrandr, XCloseDisplay,)
+16
View File
@@ -6,6 +6,11 @@ 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_VMWARE = "VMware";
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
const char* FF_GPU_VENDOR_NAME_REDHAT = "RedHat";
const char* FF_GPU_VENDOR_NAME_ORACLE = "Oracle";
static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsigned length)
{
@@ -19,6 +24,7 @@ static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsign
const char* ffGetGPUVendorString(unsigned vendorId)
{
// https://devicehunt.com/all-pci-vendors
if(vendorId == 0x106b)
return FF_GPU_VENDOR_NAME_APPLE;
if(arrayContains((const unsigned[]) {0x1002, 0x1022}, vendorId, 2))
@@ -27,6 +33,16 @@ 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[]) {0x15ad}, vendorId, 1))
return FF_GPU_VENDOR_NAME_VMWARE;
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
return FF_GPU_VENDOR_NAME_REDHAT;
else if(arrayContains((const unsigned[]) {0x1ab8}, vendorId, 1))
return FF_GPU_VENDOR_NAME_PARALLEL;
else if(arrayContains((const unsigned[]) {0x1414}, vendorId, 1))
return FF_GPU_VENDOR_NAME_MICROSOFT;
else if(arrayContains((const unsigned[]) {0x108e}, vendorId, 1))
return FF_GPU_VENDOR_NAME_ORACLE;
return NULL;
}
+5
View File
@@ -13,6 +13,11 @@ extern const char* FF_GPU_VENDOR_NAME_APPLE;
extern const char* FF_GPU_VENDOR_NAME_AMD;
extern const char* FF_GPU_VENDOR_NAME_INTEL;
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
extern const char* FF_GPU_VENDOR_NAME_REDHAT;
extern const char* FF_GPU_VENDOR_NAME_ORACLE;
typedef struct FFGPUMemory
{
+1 -2
View File
@@ -30,9 +30,8 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
CFMutableDictionaryRef matchDict = IOServiceMatching(kIOAcceleratorClassName);
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
+39 -20
View File
@@ -1,7 +1,9 @@
#include "detection/gpu/gpu.h"
#include "detection/gpu/gpu_nvidia.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"
@@ -35,7 +37,7 @@ typedef struct PCIData
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
if(gpu->vendor.length > 0)
return;
@@ -45,11 +47,11 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufRecalculateLength(&gpu->vendor);
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
}
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
@@ -110,34 +112,36 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
#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));
if(gpu->driver.length > 0)
return;
#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);
ffStrbufEnsureFree(&gpu->driver, 1023);
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
if(resultLength > 0)
if (gpu->driver.length == 0)
{
gpu->driver.length = (uint32_t) resultLength;
gpu->driver.chars[resultLength] = '\0';
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
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);
ffStrbufTrimRight(&gpu->driver, ' ');
}
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device)
{
const FFTempsResult* tempsResult = ffDetectTemps();
const FFlist* tempsResult = ffDetectTemps();
for(uint32_t i = 0; i < tempsResult->values.length; i++)
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
{
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
//The kernel exposes the device class multiplied by 256 for some reason
if(tempValue->deviceClass == device->device_class * 256)
{
@@ -236,8 +240,23 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml))
{
char pciDeviceId[32];
snprintf(pciDeviceId, sizeof(pciDeviceId) - 1, "%04x:%02x:%02x.%d", device->domain, device->bus, device->dev, device->func);
ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) { .pciBusId = pciDeviceId }, (FFGpuNvidiaResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->useNvml ? &gpu->dedicated : NULL,
.coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL,
}, "libnvidia-ml.so");
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
#ifdef __linux__
if(options->temp)
if(options->temp && gpu->temperature != gpu->temperature)
pciDetectTemp(gpu, device);
#endif
}
@@ -270,7 +289,7 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
PCIData pci;
FF_LIBRARY_LOAD(libpci, &instance.config.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
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);
+97
View File
@@ -0,0 +1,97 @@
#include "gpu_nvidia.h"
#include "3rdparty/nvml/nvml.h"
#include "common/library.h"
struct FFNvmlData {
FF_LIBRARY_SYMBOL(nvmlDeviceGetCount_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByIndex_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByPciBusId_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetPciInfo_v3)
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature)
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
bool inited;
} nvmlData;
const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult result, const char* soName)
{
if (!nvmlData.inited)
{
nvmlData.inited = true;
FF_LIBRARY_LOAD(libnvml, NULL, "dlopen nvml failed", soName , 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlInit_v2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlShutdown)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCount_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByIndex_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByPciBusId_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetPciInfo_v3)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
if (ffnvmlInit_v2() != NVML_SUCCESS)
{
nvmlData.ffnvmlDeviceGetNumGpuCores = NULL;
return "nvmlInit_v2() failed";
}
atexit((void*) ffnvmlShutdown);
libnvml = NULL; // don't close nvml
}
if (nvmlData.ffnvmlDeviceGetNumGpuCores == NULL)
return "loading nvml library failed";
nvmlDevice_t device = NULL;
if (cond.pciBusId)
{
nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(cond.pciBusId, &device);
if (ret != NVML_SUCCESS)
return "nvmlDeviceGetHandleByPciBusId_v2() failed";
}
else
{
uint32_t count;
if (nvmlData.ffnvmlDeviceGetCount_v2(&count) != NVML_SUCCESS)
return "nvmlDeviceGetCount_v2() failed";
for (uint32_t i = 0; i < count; i++, device = NULL)
{
if (nvmlData.ffnvmlDeviceGetHandleByIndex_v2(i, &device) != NVML_SUCCESS)
continue;
nvmlPciInfo_t pciInfo;
if (nvmlData.ffnvmlDeviceGetPciInfo_v3(device, &pciInfo) != NVML_SUCCESS)
continue;
if (pciInfo.pciDeviceId != cond.pciDeviceId || pciInfo.pciSubSystemId != cond.pciSubSystemId)
continue;
break;
}
if (!device) return "Device not found";
}
if (result.temp)
{
uint32_t value;
if (nvmlData.ffnvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &value) == NVML_SUCCESS)
*result.temp = value;
}
if (result.memory)
{
nvmlMemory_v2_t memory = { .version = nvmlMemory_v2 };
if (nvmlData.ffnvmlDeviceGetMemoryInfo_v2(device, &memory) == NVML_SUCCESS)
{
result.memory->total = memory.used + memory.free;
result.memory->used = memory.used;
}
}
if (result.coreCount)
nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount);
return NULL;
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "gpu.h"
// Use pciBusId if not NULL; use pciDeviceId and pciSubSystemId otherwise
typedef struct FFGpuNvidiaCondition
{
// "domain:bus:device.function"
const char* pciBusId;
// (deviceId << 16) | vendorId
uint32_t pciDeviceId;
uint32_t pciSubSystemId;
} FFGpuNvidiaCondition;
// detect x if not NULL
typedef struct FFGpuNvidiaResult
{
double* temp;
FFGPUMemory* memory;
uint32_t* coreCount;
} FFGpuNvidiaResult;
const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult result, const char* soName);
+47 -10
View File
@@ -1,4 +1,5 @@
#include "gpu.h"
#include "detection/gpu/gpu_nvidia.h"
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
@@ -12,9 +13,11 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) };
wchar_t regKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
const uint32_t regKeyPrefixLength = (uint32_t) wcslen(regKey);
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regKeyPrefixLength;
wchar_t regDirectxKey[MAX_PATH] = L"SOFTWARE\\Microsoft\\DirectX\\{";
const uint32_t regDirectxKeyPrefixLength = (uint32_t) wcslen(regDirectxKey);
wchar_t regControlVideoKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
const uint32_t regControlVideoKeyPrefixLength = (uint32_t) wcslen(regControlVideoKey);
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regControlVideoKeyPrefixLength;
for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i)
{
@@ -43,27 +46,61 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{')
{
wmemcpy(regKey + regKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, 100 - regKeyPrefixLength + 1);
wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}\\0000"));
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regKey, &hKey, NULL)) continue;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue;
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL);
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}"));
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
{
uint64_t dedicatedVideoMemory = 0;
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
uint64_t dedicatedSystemMemory, sharedSystemMemory;
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
{
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
gpu->shared.total = sharedSystemMemory;
}
}
else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
{
uint32_t vmem = 0;
if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL))
gpu->dedicated.total = vmem;
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
}
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml))
{
uint32_t vendorId, deviceId, subSystemId;
// 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"
if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x", &vendorId, &deviceId, &subSystemId) == 3)
{
ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) {
.pciDeviceId = (deviceId << 16) | vendorId,
.pciSubSystemId = subSystemId,
}, (FFGpuNvidiaResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->useNvml ? &gpu->dedicated : NULL,
.coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL,
}, "nvml.dll");
}
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
}
+15 -1
View File
@@ -4,6 +4,7 @@
extern "C" {
#include "common/library.h"
#include "detection/gpu/gpu.h"
#include "detection/gpu/gpu_nvidia.h"
}
#include <wsl/winadapter.h>
@@ -92,7 +93,20 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId)))
{
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
ffStrbufAppendS(&gpu->vendor, vendorStr);
ffStrbufSetStatic(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->useNvml)
{
ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) {
.pciBusId = nullptr,
.pciDeviceId = (hardwareId.deviceID << 16) | hardwareId.vendorID,
.pciSubSystemId = hardwareId.subSysID
}, (FFGpuNvidiaResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->useNvml ? &gpu->dedicated : NULL,
.coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL,
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
}
}
}
+1 -12
View File
@@ -36,8 +36,6 @@ static inline void applyGTKSettings(FFGTKResult* result, const char* themeName,
static void detectGTKFromSettings(FFGTKResult* result)
{
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
static const char* themeName = NULL;
static const char* iconsName = NULL;
static const char* fontName = NULL;
@@ -47,11 +45,8 @@ static void detectGTKFromSettings(FFGTKResult* result)
static bool init = false;
ffThreadMutexLock(&mutex);
if(init)
{
ffThreadMutexUnlock(&mutex);
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
return;
}
@@ -103,7 +98,6 @@ static void detectGTKFromSettings(FFGTKResult* result)
wallpaper = ffSettingsGet("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
}
ffThreadMutexUnlock(&mutex);
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
}
@@ -178,14 +172,10 @@ static void detectGTK(const char* version, FFGTKResult* result)
}
#define FF_DETECT_GTK_IMPL(version) \
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
static FFGTKResult result; \
static bool init = false; \
ffThreadMutexLock(&mutex); \
if(init){ \
ffThreadMutexUnlock(&mutex);\
if(init) \
return &result; \
} \
init = true; \
ffStrbufInit(&result.theme); \
ffStrbufInit(&result.icons); \
@@ -194,7 +184,6 @@ static void detectGTK(const char* version, FFGTKResult* result)
ffStrbufInit(&result.cursorSize); \
ffStrbufInit(&result.wallpaper); \
detectGTK(#version, &result); \
ffThreadMutexUnlock(&mutex); \
return &result;
const FFGTKResult* ffDetectGTK2(void)
-6
View File
@@ -138,14 +138,9 @@ const FFQtResult* ffDetectQt(void)
{
static FFQtResult result;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
static bool init = false;
ffThreadMutexLock(&mutex);
if(init)
{
ffThreadMutexUnlock(&mutex);
return &result;
}
init = true;
ffStrbufInit(&result.widgetStyle);
@@ -161,6 +156,5 @@ const FFQtResult* ffDetectQt(void)
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT) == 0)
detectLXQt(&result);
ffThreadMutexUnlock(&mutex);
return &result;
}
+4
View File
@@ -28,6 +28,10 @@ static void getHostProductName(FFstrbuf* name)
if(ffIsSmbiosValueSet(name))
return;
ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name);
if(ffIsSmbiosValueSet(name))
return;
//does a clear before the read
ffReadFileBuffer("/tmp/sysinfo/model", name);
if(ffIsSmbiosValueSet(name))
+4 -3
View File
@@ -4,11 +4,12 @@
const char* ffDetectIcons(FFstrbuf* result)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu", &hKey, NULL))
return "ffRegOpenKeyForRead(Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu) failed";
if(!ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\NewStartPanel", &hKey, NULL) &&
!ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu", &hKey, NULL))
return "ffRegOpenKeyForRead(Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\{NewStartPanel|ClassicStartMenu}) failed";
// Whether these icons are hidden
uint32_t ThisPC = 0, UsersFiles = 0, RemoteNetwork = 0, RecycleBin = 0, ControlPanel = 0;
uint32_t ThisPC = 1, UsersFiles = 1, RemoteNetwork = 1, RecycleBin = 0 /* Shown by default */, ControlPanel = 1;
ffRegReadUint(hKey, L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", &ThisPC, NULL);
ffRegReadUint(hKey, L"{59031a47-3f72-44a7-89c5-5595fe6b30ee}", &UsersFiles, NULL);
ffRegReadUint(hKey, L"{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}", &RemoteNetwork, NULL);
-6
View File
@@ -6,18 +6,12 @@
#include "common/thread.h"
#define FF_DETECTION_INTERNAL_GUARD(ResultType, ...) \
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
static ResultType result; \
static bool init = false; \
ffThreadMutexLock(&mutex); \
if(init) \
{ \
ffThreadMutexUnlock(&mutex); \
return &result; \
} \
init = true; \
__VA_ARGS__; \
ffThreadMutexUnlock(&mutex); \
return &result; \
#endif

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