Compare commits

...

189 Commits

Author SHA1 Message Date
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
290 changed files with 18421 additions and 3906 deletions
+22 -5
View File
@@ -44,10 +44,13 @@ jobs:
run: ctest
- 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
@@ -84,6 +87,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
@@ -136,6 +142,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 +171,17 @@ jobs:
uses: actions/checkout@v4
- name: run VM
uses: vmactions/freebsd-vm@v0
uses: cross-platform-actions/action@v0.21.0
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: |
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
./fastfetch --list-features
time ./fastfetch -c presets/ci
time ./fastfetch -c presets/ci --format json
time ./flashfetch
ldd fastfetch
ctest
@@ -227,6 +238,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
@@ -291,6 +305,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
+76
View File
@@ -1,3 +1,79 @@
# 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
+74 -7
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.1.0
VERSION 2.2.0
LANGUAGES C
DESCRIPTION "Fast 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 #
@@ -273,6 +278,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 +299,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 +315,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 +356,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 +386,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 +394,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 +423,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 +444,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 +474,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 +497,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 +505,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 +534,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 +556,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 +586,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 +609,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 +640,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 +685,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 +887,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 +915,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 +982,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 --mirgrate-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
+527 -228
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"
+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)
+35 -22
View File
@@ -14,20 +14,20 @@ 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:
--load-config,--config,-c <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
--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
--multithreading,--thread <?value>: Use multiple threads to detect values
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
--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. Linux only
Logo options:
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
@@ -41,6 +41,7 @@ Logo options:
--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>
@@ -58,6 +59,8 @@ Logo options:
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.
--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
@@ -122,8 +125,9 @@ Module specific options:
--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,32 +136,41 @@ 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
--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/
--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
--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
--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: 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
--wm-detect-plugin: Set if window manager plugin should be detected on supported platforms. Default is false
--player-name: The name of the player to use for module Media and Player. Linux only
--opengl-library <value>: 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
+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:Battery:PowerAdapter:Locale:Break:Colors
+1 -5
View File
@@ -17,12 +17,8 @@ static double detectBatteryTemp(void)
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;
+1 -1
View File
@@ -32,7 +32,7 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
if(instance.config.allowSlowOperations)
if(options->useSetupApi)
{
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
+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;
}
+6 -1
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
);
}
@@ -115,6 +116,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;
+37 -16
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,24 +112,28 @@ 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)
@@ -236,8 +242,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 +291,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
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#ifndef FF_INCLUDED_detection_libc_libc
#define FF_INCLUDED_detection_libc_libc
#include "fastfetch.h"
typedef struct FFLibcResult
{
const char* name;
const char* version;
} FFLibcResult;
const char* ffDetectLibc(FFLibcResult* result);
#endif
+25
View File
@@ -0,0 +1,25 @@
#include "libc.h"
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#include <features.h>
const char* ffDetectLibc(FFLibcResult* result)
{
#if __ANDROID_NDK__
result->name = "ndk-bionic";
result->version = FF_STR(__NDK_MAJOR__) "." FF_STR(__NDK_MINOR__) "." FF_STR(__NDK_BUILD__)
#if __NDK_BETA__
"-beta" FF_STR(__NDK_BETA__)
#elif __NDK_CANARY__
"-canary"
#endif
;
return NULL;
#else
return "Unknown Android libc";
#endif
}
+13
View File
@@ -0,0 +1,13 @@
#include "libc.h"
const char* ffDetectLibc(FFLibcResult* result)
{
result->name = "libSystem";
#ifdef FF_LIBSYSTEM_VERSION
result->version = FF_LIBSYSTEM_VERSION;
#else
result->version = NULL;
#endif
return NULL;
}
+13
View File
@@ -0,0 +1,13 @@
#include "libc.h"
const char* ffDetectLibc(FFLibcResult* result)
{
result->name = "FBSD";
#ifdef FF_FBSD_VERSION
result->version = FF_FBSD_VERSION;
#else
result->version = NULL;
#endif
return NULL;
}
+26
View File
@@ -0,0 +1,26 @@
#include "libc.h"
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#include <features.h>
const char* ffDetectLibc(FFLibcResult* result)
{
#ifdef __UCLIBC__
result->name = "uClibc";
result->version = FF_STR(__UCLIBC_MAJOR__) "." FF_STR(__UCLIBC_MINOR__) "." FF_STR(__UCLIBC_SUBLEVEL__);
#elif defined(__GNU_LIBRARY__)
result->name = "glibc";
result->version = FF_STR(__GLIBC__) "." FF_STR(__GLIBC_MINOR__);
#else
result->name = "musl";
#ifdef FF_MUSL_VERSION
result->version = FF_MUSL_VERSION;
#else
result->version = NULL;
#endif
#endif
return NULL;
}
+65
View File
@@ -0,0 +1,65 @@
extern "C"
{
#include "libc.h"
}
#ifdef __MINGW32__
#include <_mingw.h>
#endif
template<uint32_t Major, uint32_t Minor>
class version_t {
constexpr static auto buflen() noexcept {
unsigned int len = 2; // "."
if (Major == 0)
len++;
else
for (auto n = Major; n; len++, n /= 10);
if (Minor == 0)
len++;
else
for (auto n = Minor; n; len++, n /= 10);
return len;
}
char buf[buflen()] = {};
public:
constexpr version_t() noexcept {
auto ptr = buf + buflen();
*--ptr = '\0';
if (Minor == 0) {
*--ptr = '0';
} else {
for (auto n = Minor; n; n /= 10)
*--ptr = "0123456789"[n % 10];
}
*--ptr = '.';
if (Major == 0) {
*--ptr = '0';
} else {
for (auto n = Major; n; n /= 10)
*--ptr = "0123456789"[n % 10];
}
}
constexpr operator const char *() const { return buf; }
};
template<uint32_t Major, uint32_t Minor>
constexpr version_t<Major, Minor> version;
extern "C"
const char* ffDetectLibc(FFLibcResult* result)
{
#ifdef _UCRT
result->name = "ucrt";
#else
result->name = "msvcrt";
#endif
result->version = version<(__MSVCRT_VERSION__ >> 8), (__MSVCRT_VERSION__ & 8)>;
return NULL;
}
+7 -7
View File
@@ -55,13 +55,13 @@ static const char* getSshdVersion(FFstrbuf* version)
static const char* getSddmVersion(FFstrbuf* version)
{
FF_LIBRARY_LOAD(zlib, &instance.config.libZ, "dlopen libz failed", "libz" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzopen);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzread);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzerror);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gztell);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose);
FF_LIBRARY_LOAD(zlib, &instance.config.library.libZ, "dlopen libz failed", "libz" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzopen)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzread)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzerror)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gztell)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose)
gzFile file = ffgzopen("/usr/share/man/man1/sddm.1.gz", "rb");
if (file == Z_NULL)
+2 -2
View File
@@ -161,8 +161,8 @@ static const char* getMedia(FFMediaResult* result)
// FIXME: This is shared for both player and media module.
// However it uses an option in one specific module
if(instance.config.playerName.length > 0)
getCustomBus(&data, &instance.config.playerName, result);
if(instance.config.general.playerName.length > 0)
getCustomBus(&data, &instance.config.general.playerName, result);
else
getBestBus(&data, result);
+55 -113
View File
@@ -1,139 +1,81 @@
#include "monitor.h"
#include "detection/displayserver/displayserver.h"
#include "util/apple/cf_helpers.h"
#include "util/apple/ddcci.h"
#include "util/edidHelper.h"
#import <AppKit/NSScreen.h>
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
static const char* detectWithDisplayServices(const FFDisplayServerResult* displayServer, FFlist* results)
static bool detectHdrSupportWithNSScreen(FFDisplayResult* display)
{
if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available";
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
NSScreen* mainScreen = NSScreen.mainScreen;
if (display->primary)
return mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1;
else
{
if (display->type == FF_DISPLAY_TYPE_BUILTIN)
for (NSScreen* screen in NSScreen.screens)
{
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
if(displayInfo)
if (screen == mainScreen) continue;
NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"];
if (screenNumber && screenNumber.longValue == (long) display->id)
{
int width, height;
if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) || // Default resolution (limited by connectors, GPUs, etc.)
ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) ||
width <= 0 || height <= 0)
continue;
FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results);
monitor->width = (uint32_t) width;
monitor->height = (uint32_t) height;
ffStrbufInitCopy(&monitor->name, &display->name);
CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id);
monitor->physicalWidth = (uint32_t) (size.width + 0.5);
monitor->physicalHeight = (uint32_t) (size.height + 0.5);
monitor->hdrCompatible = false;
if (CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")))
monitor->hdrCompatible = true;
else
{
NSScreen* mainScreen = NSScreen.mainScreen;
if (display->primary)
monitor->hdrCompatible = mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1;
else
{
for (NSScreen* screen in NSScreen.screens)
{
if (screen == mainScreen) continue;
NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"];
if (screenNumber && screenNumber.longValue == (long) display->id)
{
monitor->hdrCompatible = screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1;
break;
}
}
continue;
}
}
return screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1;
}
}
}
return NULL;
}
static const char* detectWithDdcci(FFlist* results)
{
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)
return "IOServiceGetMatchingServices() failed";
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
ffStrbufClear(&location);
if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded"))
{
// Builtin display should be handled by DisplayServices
IOObjectRelease(registryEntry);
continue;
}
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
IOObjectRelease(registryEntry);
if (!service) continue;
FF_CFTYPE_AUTO_RELEASE CFDataRef edid = NULL;
if (IOAVServiceCopyEDID(service, &edid) != KERN_SUCCESS)
continue;
uint32_t edidLength = (uint32_t) CFDataGetLength(edid);
if (edidLength == 0 || edidLength % 128 != 0)
continue;
uint32_t width, height;
const uint8_t* edidData = CFDataGetBytePtr(edid);
ffEdidGetPhysicalResolution(edidData, &width, &height);
if (width == 0 || height == 0) continue;
FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results);
display->width = width;
display->height = height;
ffStrbufInit(&display->name);
ffEdidGetName(edidData, &display->name);
ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight);
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, edidLength);
}
return NULL;
return false;
}
const char* ffDetectMonitor(FFlist* results)
{
if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available";
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
detectWithDisplayServices(displayServer, results);
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
if(!displayInfo) continue;
uint8_t edidData[128] = {};
uint32_t edidLength = 0;
if (false || !ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength))
{
uint32_t width, height;
ffEdidGetPhysicalResolution(edidData, &width, &height);
if (width > 0 && height > 0)
{
FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results);
ffStrbufInitCopy(&monitor->name, &display->name);
monitor->width = width;
monitor->height = height;
ffEdidGetPhysicalSize(edidData, &monitor->physicalWidth, &monitor->physicalHeight);
monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) ||
detectHdrSupportWithNSScreen(display);
continue;
}
}
int width, height;
if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) || // Default resolution (limited by connectors, GPUs, etc.)
ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) ||
width <= 0 || height <= 0)
continue;
FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results);
monitor->width = (uint32_t) width;
monitor->height = (uint32_t) height;
ffStrbufInitCopy(&monitor->name, &display->name);
CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id);
monitor->physicalWidth = (uint32_t) (size.width + 0.5);
monitor->physicalHeight = (uint32_t) (size.height + 0.5);
monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) ||
detectHdrSupportWithNSScreen(display);
}
if (displayServer->displays.length > results->length)
detectWithDdcci(results);
return NULL;
}
+2
View File
@@ -1,3 +1,5 @@
#pragma once
#include "fastfetch.h"
typedef struct FFNetIOResult
+1 -1
View File
@@ -72,7 +72,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result)
OpenCLData data;
FF_LIBRARY_LOAD(opencl, &instance.config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed",
FF_LIBRARY_LOAD(opencl, &instance.config.library.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed",
#ifdef _WIN32
"OpenCL"FF_LIBRARY_EXTENSION, -1,
#endif
+3 -3
View File
@@ -122,7 +122,7 @@ static const char* eglPrint(FFOpenGLResult* result)
{
EGLData eglData;
FF_LIBRARY_LOAD(egl, &instance.config.libEGL, "dlopen egl failed", "libEGL" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD(egl, &instance.config.library.libEGL, "dlopen egl failed", "libEGL" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
@@ -239,7 +239,7 @@ static const char* glxPrint(FFOpenGLResult* result)
{
GLXData data;
FF_LIBRARY_LOAD(glx, &instance.config.libGLX, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD(glx, &instance.config.library.libGLX, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXChooseVisual);
@@ -303,7 +303,7 @@ static const char* osMesaPrint(FFOpenGLResult* result)
{
OSMesaData data;
FF_LIBRARY_LOAD(osmesa, &instance.config.libOSMesa, "dlopen osmesa failed", "libOSMesa" FF_LIBRARY_EXTENSION, 8);
FF_LIBRARY_LOAD(osmesa, &instance.config.library.libOSMesa, "dlopen osmesa failed", "libOSMesa" FF_LIBRARY_EXTENSION, 8);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaGetProcAddress);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaCreateContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent);
+22 -22
View File
@@ -35,10 +35,10 @@ static bool detectOSCodeName(FFOSResult* os)
switch (num)
{
case 14: ffStrbufAppendS(&os->codename, "Sonoma"); return true;
case 13: ffStrbufAppendS(&os->codename, "Ventura"); return true;
case 12: ffStrbufAppendS(&os->codename, "Monterey"); return true;
case 11: ffStrbufAppendS(&os->codename, "Big Sur"); return true;
case 14: ffStrbufSetStatic(&os->codename, "Sonoma"); return true;
case 13: ffStrbufSetStatic(&os->codename, "Ventura"); return true;
case 12: ffStrbufSetStatic(&os->codename, "Monterey"); return true;
case 11: ffStrbufSetStatic(&os->codename, "Big Sur"); return true;
case 10: {
version = str_end + 1;
num = strtoul(version, &str_end, 10);
@@ -46,23 +46,23 @@ static bool detectOSCodeName(FFOSResult* os)
switch (num)
{
case 16: ffStrbufAppendS(&os->codename, "Big Sur"); return true;
case 15: ffStrbufAppendS(&os->codename, "Catalina"); return true;
case 14: ffStrbufAppendS(&os->codename, "Mojave"); return true;
case 13: ffStrbufAppendS(&os->codename, "High Sierra"); return true;
case 12: ffStrbufAppendS(&os->codename, "Sierra"); return true;
case 11: ffStrbufAppendS(&os->codename, "El Capitan"); return true;
case 10: ffStrbufAppendS(&os->codename, "Yosemite"); return true;
case 9: ffStrbufAppendS(&os->codename, "Mavericks"); return true;
case 8: ffStrbufAppendS(&os->codename, "Mountain Lion"); return true;
case 7: ffStrbufAppendS(&os->codename, "Lion"); return true;
case 6: ffStrbufAppendS(&os->codename, "Snow Leopard"); return true;
case 5: ffStrbufAppendS(&os->codename, "Leopard"); return true;
case 4: ffStrbufAppendS(&os->codename, "Tiger"); return true;
case 3: ffStrbufAppendS(&os->codename, "Panther"); return true;
case 2: ffStrbufAppendS(&os->codename, "Jaguar"); return true;
case 1: ffStrbufAppendS(&os->codename, "Puma"); return true;
case 0: ffStrbufAppendS(&os->codename, "Cheetah"); return true;
case 16: ffStrbufSetStatic(&os->codename, "Big Sur"); return true;
case 15: ffStrbufSetStatic(&os->codename, "Catalina"); return true;
case 14: ffStrbufSetStatic(&os->codename, "Mojave"); return true;
case 13: ffStrbufSetStatic(&os->codename, "High Sierra"); return true;
case 12: ffStrbufSetStatic(&os->codename, "Sierra"); return true;
case 11: ffStrbufSetStatic(&os->codename, "El Capitan"); return true;
case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); return true;
case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); return true;
case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); return true;
case 7: ffStrbufSetStatic(&os->codename, "Lion"); return true;
case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); return true;
case 5: ffStrbufSetStatic(&os->codename, "Leopard"); return true;
case 4: ffStrbufSetStatic(&os->codename, "Tiger"); return true;
case 3: ffStrbufSetStatic(&os->codename, "Panther"); return true;
case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); return true;
case 1: ffStrbufSetStatic(&os->codename, "Puma"); return true;
case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); return true;
}
}
}
@@ -113,7 +113,7 @@ void ffDetectOSImpl(FFOSResult* os)
parseSystemVersion(os);
if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS"))
ffStrbufAppendS(&os->id, "macos");
ffStrbufSetStatic(&os->id, "macos");
if(os->version.length == 0)
ffSysctlGetString("kern.osproductversion", &os->version);
+3 -3
View File
@@ -133,13 +133,13 @@ static void getDebianVersion(FFOSResult* result)
static void detectOS(FFOSResult* os)
{
if(instance.config.osFile.length > 0)
if(instance.config.general.osFile.length > 0)
{
parseFile(instance.config.osFile.chars, os);
parseFile(instance.config.general.osFile.chars, os);
return;
}
if(instance.config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
if(instance.config.general.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
{
if(os->id.length == 0)
ffStrbufAppendS(&os->id, "bedrock");
+3 -3
View File
@@ -3,11 +3,11 @@
#include <stddef.h>
void ffDetectPackagesImpl(FFPackagesResult* result);
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options);
const char* ffDetectPackages(FFPackagesResult* result)
const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* options)
{
ffDetectPackagesImpl(result);
ffDetectPackagesImpl(result, options);
for(uint32_t i = 0; i < offsetof(FFPackagesResult, all) / sizeof(uint32_t); ++i)
result->all += ((uint32_t *)result)[i];
+2 -1
View File
@@ -19,6 +19,7 @@ typedef struct FFPackagesResult
uint32_t nixDefault;
uint32_t nixSystem;
uint32_t nixUser;
uint32_t opkg;
uint32_t pacman;
uint32_t paludis;
uint32_t pkg;
@@ -35,6 +36,6 @@ typedef struct FFPackagesResult
FFstrbuf pacmanBranch;
} FFPackagesResult;
const char* ffDetectPackages(FFPackagesResult* result);
const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* options);
#endif
+1 -1
View File
@@ -68,7 +68,7 @@ static uint32_t getMacPortsPackages()
return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT"/opt/local");
}
void ffDetectPackagesImpl(FFPackagesResult* result)
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
{
getBrewPackages(result);
result->port = getMacPortsPackages();

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