diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6832bdcfb..7d8de61d54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 @@ -165,12 +174,13 @@ jobs: uses: vmactions/freebsd-vm@v0 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 + 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 run: | 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 +237,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 +304,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 diff --git a/CHANGELOG.md b/CHANGELOG.md index feeaeb4723..2546d975f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +# 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 + # 2.1.0 This release introduces a new output format: JSON result diff --git a/CMakeLists.txt b/CMakeLists.txt index 04eebf6797..91b13df6cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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.1.1 LANGUAGES C DESCRIPTION "Fast system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -222,6 +222,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 +276,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 @@ -310,6 +314,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 @@ -375,6 +380,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 @@ -385,6 +391,7 @@ if(LINUX) 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 @@ -428,11 +435,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 @@ -477,6 +486,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 @@ -488,6 +498,7 @@ elseif(BSD) 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 @@ -531,12 +542,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 @@ -580,11 +593,13 @@ 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/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 @@ -651,6 +666,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) @@ -856,6 +893,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 +960,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() ################### diff --git a/README.md b/README.md index 3148465d55..26ccceda90 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ For the image logo, WezTerm with iterm image protocol is known to work, surprisi * [`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) +* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Both the package [termux-api](https://github.com/termux/termux-packages/tree/master/packages/termux-api) and the Android app [Termux API](https://github.com/termux/termux-api) must be installed and the app `Termux API` must be configured to be able to self-running. In order to make Wifi detection actuall work, location privilege must be granted to the app `Termux API`. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail. * [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android. For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol. @@ -108,21 +108,21 @@ All categories not listed here should work without needing a specific implementa ##### 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 +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, DiskIO, 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 ``` ##### Builtin logos ``` -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 +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, Chimera Linux, 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, EndeavourSmall, 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, LainOS, 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, Xenia, Xferience, YiffOS, Zorin ``` Run `fastfetch --print-logos` to print them ##### Package managers ``` -apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps +apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, opkg, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps ``` ##### WM themes @@ -137,7 +137,7 @@ 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 +Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Console, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake ``` ## Building diff --git a/doc/json_schema.json b/doc/json_schema.json index d7e681566c..e309dee87f 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -545,6 +545,7 @@ "datetime", "display", "disk", + "diskio", "de", "font", "gamepad", @@ -595,7 +596,6 @@ ], "properties": { "type": { - "title": "Module type", "type": "string" } }, @@ -614,45 +614,151 @@ "title": "No additional properties", "properties": { "type": { - "enum": [ - "bios", - "board", - "brightness", - "chassis", - "cpuusage", - "cursor", - "datetime", - "de", - "font", - "gamepad", - "host", - "icons", - "kernel", - "lm", - "locale", - "media", - "memory", - "monitor", - "opencl", - "os", - "packages", - "player", - "poweradapter", - "processes", - "shell", - "swap", - "terminal", - "terminalfont", - "terminalsize", - "theme", - "uptime", - "users", - "version", - "vulkan", - "wallpaper", - "wm", - "wifi", - "wmtheme" + "anyOf": [ + { + "const": "bios", + "description": "Print BIOS name, version, release date, etc" + }, + { + "const": "board", + "description": "Print mather board name and other info" + }, + { + "const": "chassis", + "description": "Print chassis type (desktop, laptop, etc)" + }, + { + "const": "cursor", + "description": "Print cursor style name" + }, + { + "const": "datetime", + "description": "Print current date and time" + }, + { + "const": "de", + "description": "Print desktop environment name" + }, + { + "const": "font", + "description": "Print system font name" + }, + { + "const": "gamepad", + "description": "List connected gamepads" + }, + { + "const": "host", + "description": "Print product name of your computer" + }, + { + "const": "icons", + "description": "Print icon style name" + }, + { + "const": "kernel", + "description": "Print system kernel version" + }, + { + "const": "lm", + "description": "Print login manager (desktop manager) name and version" + }, + { + "const": "locale", + "description": "Print system locale name" + }, + { + "const": "media", + "description": "Print playing song name" + }, + { + "const": "memory", + "description": "Print system memory usage info" + }, + { + "const": "monitor", + "description": "Print connected physical monitor information" + }, + { + "const": "opencl", + "description": "Print highest OpenCL version supported by the GPU" + }, + { + "const": "os", + "description": "Print operating system name and version" + }, + { + "const": "packages", + "description": "List installed package managers and count of installed packages" + }, + { + "const": "player", + "description": "Print music player name" + }, + { + "const": "poweradapter", + "description": "Print power adapter name and charging watts" + }, + { + "const": "processes", + "description": "Count running processes" + }, + { + "const": "shell", + "description": "Print current shell name and version" + }, + { + "const": "swap", + "description": "Print swap (paging file) space usage" + }, + { + "const": "terminal", + "description": "Print current terminal name and version" + }, + { + "const": "terminalfont", + "description": "Print font name and size used by current terminal" + }, + { + "const": "terminalsize", + "description": "Print current terminal size" + }, + { + "const": "theme", + "description": "Print current theme information" + }, + { + "const": "uptime", + "description": "Print system uptime" + }, + { + "const": "users", + "description": "List users currently logged in" + }, + { + "const": "version", + "description": "Print Fastfetch version" + }, + { + "const": "vulkan", + "description": "Print highest Vulkan version supported by the GPU" + }, + { + "const": "wallpaper", + "description": "Print image file path of current wallpaper" + }, + { + "const": "wm", + "description": "Print window manager name and version" + }, + { + "const": "wifi", + "description": "Print connected Wi-Fi info (SSID, connection and security protocol)" + }, + { + "const": "wmtheme", + "description": "Print current theme of window manager" + } ] }, "key": { @@ -674,7 +780,8 @@ "title": "Battery", "properties": { "type": { - "const": "battery" + "const": "battery", + "description": "Print battery capacity, status, etc" }, "dir": { "title": "The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only", @@ -704,6 +811,7 @@ "title": "Bluetooth", "properties": { "type": { + "description": "List bluetooth devices", "const": "bluetooth" }, "showDisconnected": { @@ -726,10 +834,27 @@ }, "additionalProperties": false }, + { + "title": "Brightness", + "properties": { + "type": { + "const": "brightness", + "description": "Print current brightness / luminance of your monitors" + }, + "ddcciSleep": { + "type": "integer", + "description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee for detail", + "minimum": 0, + "maximum": 400, + "default": 10 + } + } + }, { "title": "CPU", "properties": { "type": { + "description": "Print CPU name, frequency, etc", "const": "cpu" }, "temp": { @@ -737,6 +862,13 @@ "type": "boolean", "default": false }, + "freqNdigits": { + "title": "Set the number of digits to keep after the decimal point when printing CPU frequency", + "type": "integer", + "minimum": 0, + "maximum": 9, + "default": 2 + }, "key": { "$ref": "#/$defs/key" }, @@ -752,10 +884,25 @@ }, "additionalProperties": false }, + { + "title": "CPU Usage", + "properties": { + "type": { + "const": "cpuusage", + "description": "Print CPU usage. Costs some time to collect data" + }, + "separate": { + "type": "boolean", + "description": "Display CPU usage per CPU logical core, instead of an average result", + "default": false + } + } + }, { "title": "Colors", "properties": { "type": { + "description": "Print some colored blocks", "const": "colors" }, "symbol": { @@ -783,6 +930,7 @@ "title": "Command", "properties": { "type": { + "description": "Running custom shell scripts", "const": "command" }, "shell": { @@ -810,9 +958,9 @@ }, { "title": "Custom", - "description": "Print a custom string, with or without key", "properties": { "type": { + "description": "Print a custom string, with or without key", "const": "custom" }, "key": { @@ -839,6 +987,7 @@ "title": "Display", "properties": { "type": { + "description": "Print resolutions, refresh rates, etc", "const": "display" }, "compactType": { @@ -874,6 +1023,7 @@ "title": "Disk", "properties": { "type": { + "description": "Print partitions, space usage, disk type, etc", "const": "disk" }, "folders": { @@ -925,10 +1075,37 @@ }, "additionalProperties": false }, + { + "title": "DiskIO", + "properties": { + "type": { + "description": "Print physical disk I/O throughput", + "const": "diskio" + }, + "namePrefix": { + "title": "Show disks with given name prefix only", + "type": "string" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "GPU", "properties": { "type": { + "description": "Print GPU names, graphic memory size, type, etc", "const": "gpu" }, "temp": { @@ -969,6 +1146,7 @@ "title": "Local IP", "properties": { "type": { + "description": "List local IP addresses (v4 or v6), MAC addresses, etc", "const": "localip" }, "showIpv4": { @@ -1021,9 +1199,10 @@ "additionalProperties": false }, { - "title": "Network throughput (usage)", + "title": "NetIO", "properties": { "type": { + "description": "Print network I/O throughput", "const": "netio" }, "namePrefix": { @@ -1054,6 +1233,7 @@ "title": "OpenGL", "properties": { "type": { + "description": "Print highest OpenGL version supported by the GPU", "const": "opengl" }, "library": { @@ -1085,6 +1265,7 @@ "title": "Public IP", "properties": { "type": { + "description": "Print your public IP address, etc", "const": "publicip" }, "url": { @@ -1118,6 +1299,7 @@ "title": "Separator", "properties": { "type": { + "description": "Print a separator line", "const": "separator" }, "string": { @@ -1132,6 +1314,7 @@ "title": "Sound", "properties": { "type": { + "description": "Print sound devices, volume, etc", "const": "sound" }, "soundType": { @@ -1163,6 +1346,7 @@ "title": "Title", "properties": { "type": { + "description": "Print title, which contains your user name, hostname", "const": "title" }, "fqdn": { @@ -1207,6 +1391,7 @@ "title": "Weather", "properties": { "type": { + "description": "Print weather information", "const": "weather" }, "location": { diff --git a/presets/all b/presets/all index b0ed3cab52..20442e13fe 100644 --- a/presets/all +++ b/presets/all @@ -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 diff --git a/presets/all.jsonc b/presets/all.jsonc index f8d4cc82ed..f26925af69 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -52,6 +52,7 @@ "gamepad", "weather", "netio", + "diskio", "version", "break", "colors" diff --git a/src/common/commandoption.c b/src/common/commandoption.c index e8a7e8001d..7b0402b51c 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -60,6 +60,9 @@ void ffPrepareCommandOption(FFdata* data) if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME)) ffPrepareCPUUsage(); + if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME)) + ffPrepareDiskIO(&instance.config.diskIo); + if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME)) ffPrepareNetIO(&instance.config.netIo); diff --git a/src/common/init.c b/src/common/init.c index 35f1467fc4..eab996eaa1 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -93,6 +93,7 @@ static void defaultConfig(void) ffInitDEOptions(&instance.config.de); ffInitDateTimeOptions(&instance.config.dateTime); ffInitDiskOptions(&instance.config.disk); + ffInitDiskIOOptions(&instance.config.diskIo); ffInitDisplayOptions(&instance.config.display); ffInitFontOptions(&instance.config.font); ffInitGPUOptions(&instance.config.gpu); @@ -307,6 +308,7 @@ static void destroyConfig(void) ffDestroyDEOptions(&instance.config.de); ffDestroyDateTimeOptions(&instance.config.dateTime); ffDestroyDiskOptions(&instance.config.disk); + ffDestroyDiskIOOptions(&instance.config.diskIo); ffDestroyDisplayOptions(&instance.config.display); ffDestroyFontOptions(&instance.config.font); ffDestroyGPUOptions(&instance.config.gpu); @@ -469,6 +471,9 @@ void ffListFeatures(void) #ifdef FF_HAVE_DDCUTIL "libddcutil\n" #endif + #ifdef FF_HAVE_DIRECTX_HEADERS + "Directx Headers\n" + #endif "" , stdout); } diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 6d8fee3291..26dd884d68 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -112,6 +112,14 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) ffPrepareCPUUsage(); break; } + case 'd': case 'D': { + if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME)) + { + if (module) ffParseDiskIOJsonObject(&cfg->diskIo, module); + ffPrepareDiskIO(&cfg->diskIo); + } + break; + } case 'n': case 'N': { if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) { diff --git a/src/common/modules.c b/src/common/modules.c index 420903c8ee..2164701448 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -30,6 +30,7 @@ static FFModuleBaseInfo* D[] = { (void*) &instance.config.de, (void*) &instance.config.display, (void*) &instance.config.disk, + (void*) &instance.config.diskIo, NULL, }; diff --git a/src/common/option.h b/src/common/option.h index 3fef4995a0..47e96585cc 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -18,6 +18,7 @@ typedef struct FFModuleBaseInfo 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 (*printHelpFormat)(void); } FFModuleBaseInfo; static inline void ffOptionInitModuleBaseInfo( @@ -26,7 +27,8 @@ 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* generateJson, // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj) + void (*printHelpFormat)(void) ) { baseInfo->name = name; @@ -34,6 +36,7 @@ static inline void ffOptionInitModuleBaseInfo( baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject; baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule; baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson; + baseInfo->printHelpFormat = printHelpFormat; } typedef struct FFModuleArgs diff --git a/src/common/printing.c b/src/common/printing.c index 0d8635f2f0..b5a32175ba 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -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); +} diff --git a/src/common/printing.h b/src/common/printing.h index a03c555555..d9925757cd 100644 --- a/src/common/printing.h +++ b/src/common/printing.h @@ -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 diff --git a/src/data/help.txt b/src/data/help.txt index 94ba7f6175..a83a81b8e7 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -132,17 +132,21 @@ Module specific options: --disk-show-readonly : Set if read only volumes should be printed. Default is false --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false --disk-use-available : Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false + --diskio-name-prefix : Show disks with given name prefix only. Default is empty --bluetooth-show-disconnected: : Set if disconnected bluetooth devices should be printed. Default is false --display-compact-type: : Set if all displays should be printed in one line. Default is none --display-detect-name: : Set if display name should be detected and printed (if supported). Default is false --display-precise-refresh-rate: :Set if decimal refresh rates should not be rounded into integers when printing. Default is true + --brightness-ddcci-sleep: Set the sleep times (in ms) when sending DDC/CI requests. See for detail. Default is 10 --sound-type: : Set what type of sound devices should be printed. Should be either main, active or all. Default is main --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ - --cpu-temp : Detect and display CPU temperature if supported. Default is false - --gpu-temp : Detect and display GPU temperature if supported. Default is false - --gpu-force-vulkan : Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false + --cpu-temp : Detect and display CPU temperature if supported. Default is false + --cpu-freq-ndigits : Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2 + --cpuusage-separate : Display CPU usage per CPU logical core, instead of an average result. Default is false + --gpu-temp : Detect and display GPU temperature if supported. Default is false + --gpu-force-vulkan : Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false --gpu-hide-type : Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none - --battery-temp : Detect and display Battery temperature if supported. Default is false + --battery-temp : Detect and display Battery temperature if supported. Default is false --localip-show-ipv4 : Show IPv4 addresses in local ip module. Default is true --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false --localip-show-mac : Show mac addresses in local ip module. Default is false @@ -150,8 +154,8 @@ Module specific options: --localip-name-prefix : Show interfaces with given interface name prefix only. Default is empty --localip-default-route-only : Show the interface that is used for default routing only. Default is false --localip-compact : Show all IPs in one line. Default is false - --netio-name-prefix : Show interfaces with given name prefix only. Default is empty - --netio-default-route-only : Show the interfac that is used for default routing only. Default is false + --netio-name-prefix : Show interfaces with given name prefix only. Default is empty + --netio-default-route-only : Show the interfac that is used for default routing only. Default is false --publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) --publicip-url: The URL of public IP detection server to be used. --weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`). diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 52f1797803..c0950c0eef 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -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; diff --git a/src/detection/brightness/brightness.h b/src/detection/brightness/brightness.h index 58aeed20a2..b32e5d15c7 100644 --- a/src/detection/brightness/brightness.h +++ b/src/detection/brightness/brightness.h @@ -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 diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index a3b1d3c8f2..4c58b5e6ab 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -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 + +// 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 +#include +#include +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"; + + 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(FFlist* result) +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; } diff --git a/src/detection/brightness/brightness_bsd.c b/src/detection/brightness/brightness_bsd.c index 72f1e54762..71bf8c9103 100644 --- a/src/detection/brightness/brightness_bsd.c +++ b/src/detection/brightness/brightness_bsd.c @@ -9,7 +9,7 @@ #include #include -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"; } diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index b3e75b2347..85713f2259 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -92,16 +92,19 @@ static const char* detectWithBacklight(FFlist* result) #include -static const char* detectWithDdcci(FFlist* result) +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.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) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_set_default_sleep_multiplier) libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330 + ffddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0); + FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL; if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0)) return "ddca_get_display_info_list2(false, &infoList) failed"; @@ -137,14 +140,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; diff --git a/src/detection/brightness/brightness_nosupport.c b/src/detection/brightness/brightness_nosupport.c index 4bd83c4ded..3ad99ed336 100644 --- a/src/detection/brightness/brightness_nosupport.c +++ b/src/detection/brightness/brightness_nosupport.c @@ -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"; } diff --git a/src/detection/brightness/brightness_windows.cpp b/src/detection/brightness/brightness_windows.cpp index 06c1690178..01e3c03140 100644 --- a/src/detection/brightness/brightness_windows.cpp +++ b/src/detection/brightness/brightness_windows.cpp @@ -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(); diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index ded5e0d899..418ab21651 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -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; diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 835bdd4f6a..2d6a1bd28d 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -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; } diff --git a/src/detection/cpuusage/cpuusage.c b/src/detection/cpuusage/cpuusage.c index 563c6fae52..040d68780b 100644 --- a/src/detection/cpuusage/cpuusage.c +++ b/src/detection/cpuusage/cpuusage.c @@ -4,42 +4,54 @@ #include -// 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"; + + FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo)); - if(inUseAll2 != inUseAll1) +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; - } - else + ffListClear(&cpuTimes2); ffTimeSleep(200); + goto retry; + } + } + + 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; } diff --git a/src/detection/cpuusage/cpuusage.h b/src/detection/cpuusage/cpuusage.h index fb3c81e8e5..655239350f 100644 --- a/src/detection/cpuusage/cpuusage.h +++ b/src/detection/cpuusage/cpuusage.h @@ -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 diff --git a/src/detection/cpuusage/cpuusage_apple.c b/src/detection/cpuusage/cpuusage_apple.c index b946152193..513b5e9304 100644 --- a/src/detection/cpuusage/cpuusage_apple.c +++ b/src/detection/cpuusage/cpuusage_apple.c @@ -4,20 +4,29 @@ #include #include -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; } diff --git a/src/detection/cpuusage/cpuusage_bsd.c b/src/detection/cpuusage/cpuusage_bsd.c index fa1945aaa5..6c58832e03 100644 --- a/src/detection/cpuusage/cpuusage_bsd.c +++ b/src/detection/cpuusage/cpuusage_bsd.c @@ -1,19 +1,36 @@ #include "detection/cpuusage/cpuusage.h" +#include "util/mallocHelper.h" #include -#include #include +#include +#include -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 = neededLength / (CPUSTATES * (uint32_t) 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; } diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index 78c64215ea..784f680b59 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -1,14 +1,13 @@ #include "fastfetch.h" #include "detection/cpuusage/cpuusage.h" +#include "common/io/io.h" #include #include -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; } diff --git a/src/detection/cpuusage/cpuusage_windows.c b/src/detection/cpuusage/cpuusage_windows.c index a22250d834..cf513340e1 100644 --- a/src/detection/cpuusage/cpuusage_windows.c +++ b/src/detection/cpuusage/cpuusage_windows.c @@ -6,7 +6,7 @@ #include #include -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; diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index 06611f85c2..3ccab52c4f 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -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; diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 55fc94a2e6..f885563d12 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -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 #include @@ -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; diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index bc53eb7834..a04571d734 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -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); diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index dadb7d3aec..24a1651bab 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -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); diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c new file mode 100644 index 0000000000..cb452743e6 --- /dev/null +++ b/src/detection/diskio/diskio.c @@ -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; +} diff --git a/src/detection/diskio/diskio.h b/src/detection/diskio/diskio.h new file mode 100644 index 0000000000..7bde1cc325 --- /dev/null +++ b/src/detection/diskio/diskio.h @@ -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); diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c new file mode 100644 index 0000000000..cdaadfa579 --- /dev/null +++ b/src/detection/diskio/diskio_apple.c @@ -0,0 +1,89 @@ +#include "diskio.h" +#include "util/apple/cf_helpers.h" + +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/src/detection/diskio/diskio_bsd.c b/src/detection/diskio/diskio_bsd.c new file mode 100644 index 0000000000..62b8aa2520 --- /dev/null +++ b/src/detection/diskio/diskio_bsd.c @@ -0,0 +1,51 @@ +#include "diskio.h" + +#include +#include + +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; +} diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c new file mode 100644 index 0000000000..9ac39915d1 --- /dev/null +++ b/src/detection/diskio/diskio_linux.c @@ -0,0 +1,108 @@ +#include "diskio.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +#include +#include + +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, §orRead, &nWritten, §orWritten) == 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; +} diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c new file mode 100644 index 0000000000..c2e71f41e3 --- /dev/null +++ b/src/detection/diskio/diskio_windows.c @@ -0,0 +1,89 @@ +#include "diskio.h" +#include "common/io/io.h" +#include "util/windows/registry.h" +#include "util/windows/unicode.h" + +#include + +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; +} diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 6cb786d6a3..616a62cc99 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -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; diff --git a/src/detection/libc/libc.h b/src/detection/libc/libc.h new file mode 100644 index 0000000000..dc89cc2be9 --- /dev/null +++ b/src/detection/libc/libc.h @@ -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 diff --git a/src/detection/libc/libc_android.c b/src/detection/libc/libc_android.c new file mode 100644 index 0000000000..845a66fa4b --- /dev/null +++ b/src/detection/libc/libc_android.c @@ -0,0 +1,25 @@ +#include "libc.h" + +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +#include + +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 +} diff --git a/src/detection/libc/libc_apple.c b/src/detection/libc/libc_apple.c new file mode 100644 index 0000000000..dbaa20d91d --- /dev/null +++ b/src/detection/libc/libc_apple.c @@ -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; +} diff --git a/src/detection/libc/libc_bsd.c b/src/detection/libc/libc_bsd.c new file mode 100644 index 0000000000..0b6ee49439 --- /dev/null +++ b/src/detection/libc/libc_bsd.c @@ -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; +} diff --git a/src/detection/libc/libc_linux.c b/src/detection/libc/libc_linux.c new file mode 100644 index 0000000000..19e8e83282 --- /dev/null +++ b/src/detection/libc/libc_linux.c @@ -0,0 +1,26 @@ +#include "libc.h" + +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +#include + +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; +} diff --git a/src/detection/libc/libc_windows.cpp b/src/detection/libc/libc_windows.cpp new file mode 100644 index 0000000000..8a699d7655 --- /dev/null +++ b/src/detection/libc/libc_windows.cpp @@ -0,0 +1,65 @@ +extern "C" +{ +#include "libc.h" +} + +#ifdef __MINGW32__ +#include <_mingw.h> +#endif + +template +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 +constexpr version_t 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; +} diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 8f931a98d5..be3b51a465 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -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 #import +#import 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; + return false; } -static const char* detectWithDdcci(FFlist* results) +const char* ffDetectMonitor(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"; + if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available"; - FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate(); + const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); - io_registry_entry_t registryEntry; - while((registryEntry = IOIteratorNext(iterator)) != 0) + FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) { - CFMutableDictionaryRef properties; - if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) - { - IOObjectRelease(registryEntry); - continue; - } + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id); + if(!displayInfo) continue; - ffStrbufClear(&location); - if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded")) + uint8_t edidData[128] = {}; + uint32_t edidLength = 0; + if (false || !ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength)) { - // Builtin display should be handled by DisplayServices - IOObjectRelease(registryEntry); - continue; + 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; + } } - 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) + 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; - uint32_t width, height; - const uint8_t* edidData = CFDataGetBytePtr(edid); + FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); + monitor->width = (uint32_t) width; + monitor->height = (uint32_t) height; + ffStrbufInitCopy(&monitor->name, &display->name); - 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); + 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); } - return NULL; -} - -const char* ffDetectMonitor(FFlist* results) -{ - const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); - - detectWithDisplayServices(displayServer, results); - if (displayServer->displays.length > results->length) - detectWithDdcci(results); return NULL; } diff --git a/src/detection/netio/netio.h b/src/detection/netio/netio.h index 295c4478ed..1dd9586a4c 100644 --- a/src/detection/netio/netio.h +++ b/src/detection/netio/netio.h @@ -1,3 +1,5 @@ +#pragma once + #include "fastfetch.h" typedef struct FFNetIOResult diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index ae36b5078e..475d39301e 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -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; diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 1aa2c2433a..93a7560120 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -280,6 +280,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts) packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR); packageCounts->brew += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Cellar", DT_DIR); packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2"); + packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt } static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts) diff --git a/src/detection/poweradapter/poweradapter_apple.c b/src/detection/poweradapter/poweradapter_apple.c index 06d8a8df6b..435532ee45 100644 --- a/src/detection/poweradapter/poweradapter_apple.c +++ b/src/detection/poweradapter/poweradapter_apple.c @@ -6,12 +6,8 @@ const char* ffDetectPowerAdapterImpl(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; diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 7e17fbc9a8..cff71038c3 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -1,13 +1,25 @@ #include "processes.h" -#include +#include "common/io/io.h" + +#include const char* ffDetectProcesses(uint32_t* result) { - struct sysinfo info; - if(sysinfo(&info) != 0) - return "sysinfo() failed"; + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); + if(dir == NULL) + return "opendir(\"/proc\") failed"; + + uint32_t num = 0; + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) + { + if (entry->d_type == DT_DIR && isdigit(entry->d_name[0])) + ++num; + } + + *result = num; - *result = (uint32_t) info.procs; return NULL; } diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index 8f23f2a3aa..1d19621640 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -32,21 +32,48 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */) { AudioDeviceID deviceId = deviceIds[index]; - uint32_t muted; - dataSize = sizeof(muted); + FF_CFTYPE_AUTO_RELEASE CFStringRef name = NULL; + dataSize = sizeof(name); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ - kAudioDevicePropertyMute, + kAudioObjectPropertyName, kAudioObjectPropertyScopeOutput, kAudioObjectPropertyElementMain - }, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError) + }, 0, NULL, &dataSize, &name) != kAudioHardwareNoError) continue; + // Ignore input devices + if(AudioObjectGetPropertyDataSize(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyStreams, + kAudioObjectPropertyScopeInput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize) == kAudioHardwareNoError && dataSize > 0) + continue; + + uint32_t connected; + dataSize = sizeof(connected); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyJackIsConnected, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &connected) == kAudioHardwareNoError) + if (!connected) continue; + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = deviceId == mainDeviceId; device->active = false; device->volume = FF_SOUND_VOLUME_UNKNOWN; ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId); ffStrbufInit(&device->name); + ffCfStrGetString(name, &device->name); + + uint32_t muted; + dataSize = sizeof(muted); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyMute, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError) + muted = false; // Device may not support volume control uint32_t active; dataSize = sizeof(active); @@ -96,18 +123,6 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */) } } } - - CFStringRef name; - dataSize = sizeof(name); - if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ - kAudioObjectPropertyName, - kAudioObjectPropertyScopeOutput, - kAudioObjectPropertyElementMain - }, 0, NULL, &dataSize, &name) == kAudioHardwareNoError) - { - ffCfStrGetString(name, &device->name); - CFRelease(name); - } } return NULL; diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index 7af1e12fe5..7054a3ed33 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -140,12 +140,8 @@ static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcV static const char *smcOpen(io_connect_t *conn) { - CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSMC"); - 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("AppleSMC"), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; io_object_t device = IOIteratorNext(iterator); diff --git a/src/detection/temps/temps_bsd.c b/src/detection/temps/temps_bsd.c index 39693d65de..2355ac8bfe 100644 --- a/src/detection/temps/temps_bsd.c +++ b/src/detection/temps/temps_bsd.c @@ -1,6 +1,17 @@ #include "temps_bsd.h" #include "common/sysctl.h" +const char* ffDetectCpuTemp(double* current) +{ + int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999); + if (temp == -999999) + return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed"; + + // In tenth of degrees Celsius + *current = (double) temp / 10; + return NULL; +} + const char* ffDetectThermalTemp(double* current) { int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999); diff --git a/src/detection/temps/temps_bsd.h b/src/detection/temps/temps_bsd.h index a41aba6bc2..b126811a05 100644 --- a/src/detection/temps/temps_bsd.h +++ b/src/detection/temps/temps_bsd.h @@ -3,6 +3,7 @@ #ifndef FF_INCLUDED_detection_temps_windows #define FF_INCLUDED_detection_temps_windows +const char* ffDetectCpuTemp(double* current); const char* ffDetectThermalTemp(double* current); #endif diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 6833ba0863..c9f1b34215 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -27,6 +27,27 @@ static const char* getSystemMonospaceFont(void) return ffSettingsGet("/org/gnome/desktop/interface/monospace-font-name", "org.gnome.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; } +static void detectKgx(FFTerminalFontResult* terminalFont) +{ + // kgx (gnome console) doesn't support profiles + if(!ffSettingsGet("/org/gnome/Console/use-system-font", "org.gnome.Console", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue) + { + FF_AUTO_FREE const char* fontName = ffSettingsGet("/org/gnome/Console/custom-font", "org.gnome.Console", NULL, "custom-font", FF_VARIANT_TYPE_STRING).strValue; + if(ffStrSet(fontName)) + ffFontInitPango(&terminalFont->font, fontName); + else + ffStrbufAppendF(&terminalFont->error, "Couldn't get terminal font from GSettings (org.gnome.Console::custom-font)"); + } + else + { + FF_AUTO_FREE const char* fontName = getSystemMonospaceFont(); + if(ffStrSet(fontName)) + ffFontInitPango(&terminalFont->font, fontName); + else + ffStrbufAppendS(&terminalFont->error, "Could't get system monospace font name from GSettings / DConf"); + } +} + static void detectFromGSettings(const char* profilePath, const char* profileList, const char* profile, const char* defaultProfileKey, FFTerminalFontResult* terminalFont) { FF_AUTO_FREE const char* defaultProfile = ffSettingsGetGSettings(profileList, NULL, defaultProfileKey, FF_VARIANT_TYPE_STRING).strValue; @@ -51,7 +72,7 @@ static void detectFromGSettings(const char* profilePath, const char* profileList } else { - const char* fontName = getSystemMonospaceFont(); + FF_AUTO_FREE const char* fontName = getSystemMonospaceFont(); if(ffStrSet(fontName)) ffFontInitPango(&terminalFont->font, fontName); else @@ -243,6 +264,8 @@ void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FF detectFromGSettings("/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", "default", terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "gnome-terminal-")) detectFromGSettings("/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", "default", terminalFont); + else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kgx")) + detectKgx(terminalFont); else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "mate-terminal")) detectFromGSettings("/org/mate/terminal/profiles/", "org.mate.terminal.global", "org.mate.terminal.profile", "default-profile", terminalFont); else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "deepin-terminal")) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index cad8c5cbcc..822812882f 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -206,6 +206,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version) return true; } +FF_MAYBE_UNUSED static bool getTerminalVersionKgx(FFstrbuf* version) +{ + if(ffProcessAppendStdOut(version, (char* const[]){ + "gnome-terminal", + "--version", + NULL + })) return false; + + //# KGX 45.0 using VTE 0.74.0 +BIDI +GNUTLS +ICU +SYSTEMD + ffStrbufSubstrAfterFirstS(version, "KGX "); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* version) { const char* konsoleVersion = getenv("KONSOLE_VERSION"); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 957a0b304d..810fe90bc9 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -150,6 +150,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) //Known shells if ( + strcasecmp(name, "ash") == 0 || strcasecmp(name, "bash") == 0 || strcasecmp(name, "zsh") == 0 || strcasecmp(name, "ksh") == 0 || @@ -384,7 +385,9 @@ const FFTerminalShellResult* ffDetectTerminalShell() #elif defined(__linux__) || defined(__FreeBSD__) else if(ffStrbufStartsWithS(&result.terminalProcessName, "gnome-terminal-")) - ffStrbufInitStatic(&result.terminalPrettyName, "gnome-terminal"); + ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Terminal"); + else if(ffStrbufStartsWithS(&result.terminalProcessName, "kgx")) + ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Console"); #elif defined(__APPLE__) diff --git a/src/detection/users/users.h b/src/detection/users/users.h index 8ddc2a0cf4..38b3cf2040 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -10,7 +10,7 @@ typedef struct FFUserResult FFstrbuf name; FFstrbuf hostName; FFstrbuf clientIp; - FFstrbuf tty; + FFstrbuf sessionName; uint64_t loginTime; // ms } FFUserResult; diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index 294c69b3e1..f10b9559d2 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -31,7 +31,7 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitS(&user->name, n->ut_user); ffStrbufInitS(&user->hostName, n->ut_host); - ffStrbufInitS(&user->tty, n->ut_line); + ffStrbufInitS(&user->sessionName, n->ut_line); #ifdef __linux__ if(n->ut_addr_v6[0] || n->ut_addr_v6[1] || n->ut_addr_v6[2] || n->ut_addr_v6[3]) ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", n->ut_addr_v6[0], n->ut_addr_v6[1], n->ut_addr_v6[2], n->ut_addr_v6[3]); diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index a891520b11..115f7935d6 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -28,17 +28,18 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitWS(&user->name, session->pUserName); ffStrbufInitWS(&user->hostName, session->pHostName); + ffStrbufInitWS(&user->sessionName, session->pSessionName); + ffStrbufInit(&user->clientIp); + user->loginTime = 0; DWORD bytes = 0; PWTS_CLIENT_ADDRESS address = NULL; if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSClientAddress, (LPWSTR *) &address, &bytes)) { if (address->AddressFamily == 2 /*AF_INET*/) - ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]); + ffStrbufSetF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]); WTSFreeMemory(address); } - else - ffStrbufInitS(&user->clientIp, "0.0.0.0"); bytes = 0; PWTSINFOW wtsInfo = NULL; @@ -47,8 +48,6 @@ const char* ffDetectUsers(FFlist* users) user->loginTime = to_ms(*(uint64_t*) &wtsInfo->LogonTime); WTSFreeMemory(wtsInfo); } - else - user->loginTime = 0; } WTSFreeMemoryExW(WTSTypeSessionInfoLevel1, sessionInfo, 1); diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 775856eec8..68a86808b1 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -1,4 +1,5 @@ #include "wifi.h" +#include "common/processing.h" #import @@ -31,7 +32,22 @@ if(!inf.serviceActive) continue; - ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); + if (inf.ssid) + ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); + else if (!ffProcessAppendStdOut(&item->conn.ssid, (char* []) { + "/usr/sbin/networksetup", + "-getairportnetwork", + item->inf.description.chars, + NULL + }) && item->conn.ssid.length > 0) + { + uint32_t index = ffStrbufFirstIndexC(&item->conn.ssid, ':'); + if (index < item->conn.ssid.length) + ffStrbufSubstrAfter(&item->conn.ssid, index + 1); + } + else + ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 + ffStrbufAppendS(&item->conn.macAddress, inf.hardwareAddress.UTF8String); switch(inf.activePHYMode) { @@ -116,6 +132,9 @@ case 15 /*kCWSecurityOWETransition*/: ffStrbufAppendS(&item->conn.security, "OWE Transition"); break; + case kCWSecurityUnknown: + // Ignore + break; default: ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security); break; diff --git a/src/fastfetch.c b/src/fastfetch.c index c956357ebe..2268822b05 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -21,22 +21,23 @@ #include "modules/modules.h" -static void constructAndPrintCommandHelpFormat(const char* name, const char* def, uint32_t numArgs, ...) +static void printCommandFormatHelp(const char* command) { - va_list argp; - va_start(argp, numArgs); - - printf("--%s-format:\n", name); - 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(uint32_t i = 1; i <= numArgs; i++) - printf(" {%u}: %s\n", i, va_arg(argp, const char*)); - - printf("The default is something similar to \"%s\".\n", def); + FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateNS((uint32_t) (strlen(command) - strlen("-format")), command); + for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(command[0]) - 'A']; *modules; ++modules) + { + FFModuleBaseInfo* baseInfo = *modules; + if (ffStrbufIgnCaseEqualS(&type, baseInfo->name)) + { + if (baseInfo->printHelpFormat) + baseInfo->printHelpFormat(); + else + fprintf(stderr, "Error: Module '%s' doesn't support output formatting\n", baseInfo->name); + return; + } + } - va_end(argp); + fprintf(stderr, "Error: Module '%s' is not supported\n", type.chars); } static inline void printCommandHelp(const char* command) @@ -49,486 +50,10 @@ static inline void printCommandHelp(const char* command) puts(FASTFETCH_DATATEXT_HELP_FORMAT); else if(ffStrEqualsIgnCase(command, "load-config") || ffStrEqualsIgnCase(command, "config")) puts(FASTFETCH_DATATEXT_HELP_CONFIG); - else if(ffStrEqualsIgnCase(command, "title-format")) - { - constructAndPrintCommandHelpFormat("title", "{6}{7}{8}", 8, - "User name", - "Host name", - "Home directory", - "Executable path of current process", - "User's default shell", - "User name (colored)", - "@ symbol (colored)", - "Host name (colored)" - ); - } - else if(ffStrEqualsIgnCase(command, "os-format")) - { - constructAndPrintCommandHelpFormat("os", "{3} {12}", 12, - "System name (typically just Linux)", - "Name of the OS", - "Pretty name of the OS", - "ID of the OS", - "ID like of the OS", - "Variant of the OS", - "Variant ID of the OS", - "Version of the OS", - "Version ID of the OS", - "Version codename of the OS", - "Build ID of the OS", - "Architecture of the OS" - ); - } - else if(ffStrEqualsIgnCase(command, "host-format")) - { - constructAndPrintCommandHelpFormat("host", "{2} {3}", 8, - "product family", - "product name", - "product version", - "product sku", - "chassis type", - "chassis vendor", - "chassis version", - "sys vendor" - ); - } - else if(ffStrEqualsIgnCase(command, "bios-format")) - { - constructAndPrintCommandHelpFormat("bios", "{2} {3}", 4, - "bios date", - "bios release", - "bios vendor", - "bios version" - ); - } - else if(ffStrEqualsIgnCase(command, "board-format")) - { - constructAndPrintCommandHelpFormat("board", "{2} {3}", 3, - "board name", - "board vendor", - "board version" - ); - } - else if(ffStrEqualsIgnCase(command, "chassis-format")) - { - constructAndPrintCommandHelpFormat("chassis", "{2} {3}", 4, - "chassis type", - "chassis vendor", - "chassis version" - ); - } - else if(ffStrEqualsIgnCase(command, "kernel-format")) - { - constructAndPrintCommandHelpFormat("kernel", "{2}", 3, - "Kernel sysname", - "Kernel release", - "Kernel version" - ); - } - else if(ffStrEqualsIgnCase(command, "uptime-format")) - { - constructAndPrintCommandHelpFormat("uptime", "{} days {} hours {} mins", 4, - "Days", - "Hours", - "Minutes", - "Seconds" - ); - } - else if(ffStrEqualsIgnCase(command, "processes-format")) - { - constructAndPrintCommandHelpFormat("processes", "{}", 1, - "Count" - ); - } - else if(ffStrEqualsIgnCase(command, "packages-format")) - { - constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget)", 24, - "Number of all packages", - "Number of pacman packages", - "Pacman branch on manjaro", - "Number of dpkg packages", - "Number of rpm packages", - "Number of emerge packages", - "Number of eopkg packages", - "Number of xbps packages", - "Number of nix-system packages", - "Number of nix-user packages", - "Number of nix-default packages", - "Number of apk packages", - "Number of pkg packages", - "Number of flatpak-system packages", - "Number of flatpak-user packages", - "Number of snap packages", - "Number of brew packages", - "Number of brew-cask packages", - "Number of macports packages", - "Number of scoop packages", - "Number of choco packages", - "Number of pkgtool packages", - "Number of paludis packages" - "Number of winget packages" - ); - } - else if(ffStrEqualsIgnCase(command, "shell-format")) - { - constructAndPrintCommandHelpFormat("shell", "{3} {4}", 6, - "Shell process name", - "Shell path with exe name", - "Shell exe name", - "Shell version", - "Shell pid", - "Shell pretty name" - ); - } - else if(ffStrEqualsIgnCase(command, "display-format")) - { - constructAndPrintCommandHelpFormat("display", "{}x{} @ {}Hz", 7, - "Screen width", - "Screen height", - "Screen refresh rate", - "Screen scaled width", - "Screen scaled height", - "Screen name", - "Screen type", - "Screen rotation" - ); - } - else if(ffStrEqualsIgnCase(command, "brightness-format")) - { - constructAndPrintCommandHelpFormat("brightness", "{}", 2, - "Screen brightness", - "Screen name" - ); - } - else if(ffStrEqualsIgnCase(command, "monitor-format")) - { - constructAndPrintCommandHelpFormat("monitor", "{}", 6, - "Display name", - "Display native resolution width in pixels", - "Display native resolution height in pixels", - "Display physical width in millimeters", - "Display physical height in millimeters", - "Display physical diagonal length in inches", - "Display physical pixels per inch (PPI)" - ); - } - else if(ffStrEqualsIgnCase(command, "de-format")) - { - constructAndPrintCommandHelpFormat("de", "{2} {3}", 3, - "DE process name", - "DE pretty name", - "DE version" - ); - } - else if(ffStrEqualsIgnCase(command, "wm-format")) - { - constructAndPrintCommandHelpFormat("wm", "{2} ({3})", 3, - "WM process name", - "WM pretty name", - "WM protocol name" - ); - } - else if(ffStrEqualsIgnCase(command, "wmtheme-format")) - { - constructAndPrintCommandHelpFormat("wmtheme", "{}", 1, - "WM theme name" - ); - } - else if(ffStrEqualsIgnCase(command, "theme-format")) - { - constructAndPrintCommandHelpFormat("theme", "{}", 1, - "Combined themes" - ); - } - else if(ffStrEqualsIgnCase(command, "icons-format")) - { - constructAndPrintCommandHelpFormat("icons", "{}", 1, - "Combined icons" - ); - } - else if(ffStrEqualsIgnCase(command, "wallpaper-format")) - { - constructAndPrintCommandHelpFormat("wallpaper", "{}", 1, - "Wallpaper image file" - ); - } - else if(ffStrEqualsIgnCase(command, "font-format")) - { - constructAndPrintCommandHelpFormat("font", "{} [QT], {} [GTK2], {} [GTK3], {} [GTK4]", 4, - "Font 1", - "Font 2", - "Font 3", - "Font 4" - ); - } - else if(ffStrEqualsIgnCase(command, "cursor-format")) - { - constructAndPrintCommandHelpFormat("cursor", "{} ({}pt)", 2, - "Cursor theme", - "Cursor size" - ); - } - else if(ffStrEqualsIgnCase(command, "terminal-format")) - { - constructAndPrintCommandHelpFormat("terminal", "{3}", 10, - "Terminal process name", - "Terminal path with exe name", - "Terminal exe name", - "Terminal pid", - "Terminal pretty name", - "Terminal version" - ); - } - else if(ffStrEqualsIgnCase(command, "terminalfont-format")) - { - constructAndPrintCommandHelpFormat("terminalfont", "{}", 4, - "Terminal font", - "Terminal font name", - "Termianl font size", - "Terminal font styles" - ); - } - else if(ffStrEqualsIgnCase(command, "cpu-format")) - { - constructAndPrintCommandHelpFormat("cpu", "{1} ({5}) @ {7}GHz", 8, - "Name", - "Vendor", - "Physical core count", - "Logical core count", - "Online core count", - "Min frequency", - "Max frequency", - "Temperature" - ); - } - else if(ffStrEqualsIgnCase(command, "cpuusage-format")) - { - constructAndPrintCommandHelpFormat("cpuusage", "{0}%", 1, - "CPU usage without percent mark" - ); - } - else if(ffStrEqualsIgnCase(command, "gpu-format")) - { - constructAndPrintCommandHelpFormat("gpu", "{} {}", 6, - "GPU vendor", - "GPU name", - "GPU driver", - "GPU temperature", - "GPU core count", - "GPU type" - ); - } - else if(ffStrEqualsIgnCase(command, "memory-format")) - { - constructAndPrintCommandHelpFormat("memory", "{} / {} ({}%)", 3, - "Used size", - "Total size", - "Percentage used" - ); - } - else if(ffStrEqualsIgnCase(command, "swap-format")) - { - constructAndPrintCommandHelpFormat("swap", "{} / {} ({}%)", 3, - "Used size", - "Total size", - "Percentage used" - ); - } - else if(ffStrEqualsIgnCase(command, "disk-format")) - { - constructAndPrintCommandHelpFormat("disk", "{1} / {2} ({3}%)", 9, - "Size used", - "Size total", - "Size percentage", - "Files used", - "Files total", - "Files percentage", - "True if external volume", - "True if hidden volume", - "Filesystem" - ); - } - else if(ffStrEqualsIgnCase(command, "battery-format")) - { - constructAndPrintCommandHelpFormat("battery", "{}%, {}", 5, - "Battery manufactor", - "Battery model", - "Battery technology", - "Battery capacity", - "Battery status" - ); - } - else if(ffStrEqualsIgnCase(command, "poweradapter-format")) - { - constructAndPrintCommandHelpFormat("poweradapter", "{}%, {}", 5, - "PowerAdapter watts", - "PowerAdapter name", - "PowerAdapter manufacturer", - "PowerAdapter model", - "PowerAdapter description" - ); - } - else if(ffStrEqualsIgnCase(command, "lm-format")) - { - constructAndPrintCommandHelpFormat("lm", "{} ({})", 2, - "LM service", - "LM type" - ); - } - else if(ffStrEqualsIgnCase(command, "locale-format")) - { - constructAndPrintCommandHelpFormat("locale", "{}", 1, - "Locale code" - ); - } - else if(ffStrEqualsIgnCase(command, "localip-format")) - { - constructAndPrintCommandHelpFormat("localip", "{}", 5, - "Local IPv4 address", - "Local IPv6 address", - "Physical (MAC) address", - "Interface name", - "Is default route" - ); - } - else if(ffStrEqualsIgnCase(command, "publicip-format")) - { - constructAndPrintCommandHelpFormat("publicip", "{}", 1, - "Public IP address" - ); - } - else if(ffStrEqualsIgnCase(command, "netio-format")) - { - constructAndPrintCommandHelpFormat("netio", "{}", 3, - "Size of data received per second (formatted)", - "Size of data sent per second (formatted)", - "Interface name", - "Is default route" - ); - } - else if(ffStrEqualsIgnCase(command, "wifi-format")) - { - constructAndPrintCommandHelpFormat("wifi", "{4} - {6}", 3, - "Interface description", - "Interface status", - "Connection status", - "Connection SSID", - "Connection mac address", - "Connection protocol", - "Connection signal quality (percentage)", - "Connection RX rate", - "Connection TX rate", - "Connection Security algorithm" - ); - } - else if(ffStrEqualsIgnCase(command, "player-format")) - { - constructAndPrintCommandHelpFormat("player", "{}", 4, - "Pretty player name", - "Player name", - "Player Identifier", - "URL name" - ); - } - else if(ffStrEqualsIgnCase(command, "media-format")) - { - constructAndPrintCommandHelpFormat("media", "{3} - {1}", 4, - "Pretty media name", - "Media name", - "Artist name", - "Album name" - ); - } - else if(ffStrEqualsIgnCase(command, "datetime-format") == 0 || ffStrEqualsIgnCase(command, "date-format") || ffStrEqualsIgnCase(command, "time-format")) - { - constructAndPrintCommandHelpFormat("[date][time]", "{1}-{4}-{11} {14}:{18}:{20}", 20, - "year", - "last two digits of year", - "month", - "month with leading zero", - "month name", - "month name short", - "week number on year", - "weekday", - "weekday short", - "day in year", - "day in month", - "day in Week", - "hour", - "hour with leading zero", - "hour 12h format", - "hour 12h format with leading zero", - "minute", - "minute with leading zero", - "second", - "second with leading zero" - ); - } - else if(ffStrEqualsIgnCase(command, "version-format")) - { - constructAndPrintCommandHelpFormat("version", "{1} {2}{3} (5)", 6, - "Project name", - "Version", - "Version tweak", - "Build type (debug or release)", - "Architecture", - "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)", - "Date time when compiling", - "Compiler used" - ); - } - else if(ffStrEqualsIgnCase(command, "vulkan-format")) - { - constructAndPrintCommandHelpFormat("vulkan", "{} (driver), {} (api version)", 3, - "Driver name", - "API version", - "Conformance version" - ); - } - else if(ffStrEqualsIgnCase(command, "opengl-format")) - { - constructAndPrintCommandHelpFormat("opengl", "{}", 3, - "version", - "renderer", - "vendor", - "shading language version" - ); - } - else if(ffStrEqualsIgnCase(command, "opencl-format")) - { - constructAndPrintCommandHelpFormat("opencl", "{}", 3, - "version", - "device", - "vendor" - ); - } - else if(ffStrEqualsIgnCase(command, "bluetooth-format")) - { - constructAndPrintCommandHelpFormat("bluetooth", "{1} (4%)", 4, - "Name", - "Address", - "Type", - "Battery percentage" - ); - } - else if(ffStrEqualsIgnCase(command, "sound-format")) - { - constructAndPrintCommandHelpFormat("sound", "{2} (3%)", 4, - "Main", - "Name", - "Volume", - "Identifier" - ); - } - else if(ffStrEqualsIgnCase(command, "gamepad-format")) - { - constructAndPrintCommandHelpFormat("gamepad", "{1}", 1, - "Name", - "Identifier" - ); - } + else if(isalpha(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // x-format + printCommandFormatHelp(command); else - fprintf(stderr, "No specific help for command %s provided\n", command); + fprintf(stderr, "Error: No specific help for command '%s' provided\n", command); } static void listAvailablePresets(void) diff --git a/src/fastfetch.h b/src/fastfetch.h index 0877c1088a..cbb307a15f 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -99,6 +99,7 @@ typedef struct FFconfig FFDEOptions de; FFDateTimeOptions dateTime; FFDiskOptions disk; + FFDiskIOOptions diskIo; FFDisplayOptions display; FFFontOptions font; FFGPUOptions gpu; diff --git a/src/logo/ascii/ChimeraLinux.txt b/src/logo/ascii/ChimeraLinux.txt new file mode 100644 index 0000000000..c66b6db795 --- /dev/null +++ b/src/logo/ascii/ChimeraLinux.txt @@ -0,0 +1,18 @@ +${c3}ddddddddddddddc ${c1},cc: +${c3}ddddddddddddddc ${c1},cc: +${c3}ddddddddddddddd ${c1},cc: +${c3}ddddddddddddl:' ${c1},cc: +${c3}dddddddddl' ${c1}..;cc: +${c3}dddddddo. ${c1},:cccccc: +${c3}ddddddl ${c1},ccc:''''' +${c3}dddddo. ${c1};ccc. ............ + .ccc. cccccccccccc +${c2}...... ${c1}.ccc. .ccc''''''''' +${c2}OOOOOk. ${c1};ccc. .ccc; ...... +${c2}OOOOOOd ${c1}'ccc:,....,:ccc' ${c4}coooooo +${c2}OOOOOOOx. ${c1}':cccccccc:' ${c4}.looooooo +${c2}OOOOOOOOOd, ${c1}`'''` ${c4}.coooooooo +${c2}OOOOOOOOOOOOdc,. ${c4}..,coooooooooooo +${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo +${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo +${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo \ No newline at end of file diff --git a/src/logo/ascii/endeavour_small.txt b/src/logo/ascii/endeavour_small.txt new file mode 100644 index 0000000000..7265f4dead --- /dev/null +++ b/src/logo/ascii/endeavour_small.txt @@ -0,0 +1,7 @@ + /${c2}o${c3}. +${c1} :${c2}sssso${c3}- +${c1} :${c2}ossssssso${c3}: +${c1} /${c2}ssssssssssso${c3}+ +${c1} -+${c2}ssssssssssssssso${c3}+ +${c1} //${c2}osssssssssssssso${c3}+- + `+++++++++++++++-` diff --git a/src/logo/ascii/xenia.txt b/src/logo/ascii/xenia.txt new file mode 100644 index 0000000000..2d6e940c4d --- /dev/null +++ b/src/logo/ascii/xenia.txt @@ -0,0 +1,21 @@ +${c2} ,c. .c; +${c2} .${c1}KMMMk${c2}.... ....${c1}kMMMK${c2}. +${c2} .${c1}WMMMMMX${c2}..... .....${c1}KMMMMMW. +${c1} XMMMMMMM0${c2}..... ....${c1}OMMMMMMMN +${c1} dMMMMMMMMM;${c2}.... ..... ....,${c1}MMMMMMMMMd +${c1} WMMMMMMMMMl;${c3}okKKKKKKKKKOo${c1};cMMMMMMMMMM +${c1} 'MMMMMMMNX${c2}K0${c3}KKKKKKKKKKKKKKK${c2}0K${c1}XNMMMMMMM; +${c1} oMMMMMMM${c2}Oxo${c3}KKKKKKKKKKKKKKKKK${c2}oxO${c1}MMMMMMMd +${c1} dMMMMMMM${c2}dxxx${c3}KKKKKKKKKKKKKKK${c2}xxxd${c1}NMMMMMMk +${c1} :MMMMX0${c2}xxxxxx${c3}0KKKKKKKK0KK0${c2}xxxxxx0${c1}XMMMMc +${c1} MMMO${c2}xxxxxxxxdx${c3}kdd${c2}0x0${c3}ddk${c2}xdxxxxxxxx${c1}OMMM +${c1} ;${c2}xxkxddxxxxdodxxxxdxdxxxxdodxxxxddxkxx${c1}; +${c1}dxd${c2}KMMMWXo${c1}'.....'${c2}cdxxxdc${c1}'.....'${c2}lXWMMMX${c1}dxd +${c1}cxd${c2}XMMMN${c1},..........${c2}dxd${c1}'.........'${c2}XMMMN${c1}dxl +${c1} .xx${c2}WMMl${c1}...''....'.;k:.'....''...${c2}lMMW${c1}xx. +${c1}..:kXMMx..'....''..kMk..''....'..xMMXkc.. +${c1} dMMMMMMd.....'...xMMMx...''....dMMMMMMx +${c1} kMMMMWOoc:coOkolllokOoc:coOWMMMMO +${c1} .MMMMMMMMl${c2}...${c1}lNMMMMMMM. +${c1} KMMMMMMX${c2}l${c1}KMMMMMMX +${c1} .MMMMMMMMM. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 2063635713..9e475ecdca 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -826,6 +826,19 @@ static const FFlogo C[] = { .colorKeys = FF_COLOR_FG_GREEN, .colorTitle = FF_COLOR_FG_WHITE, }, + // Chimera Linux + { + .names = {"Chimera Linux"}, + .lines = FASTFETCH_DATATEXT_LOGO_CHIMERALINUX, + .colors = { + FF_COLOR_FG_RED, + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_BLUE, + FF_COLOR_FG_RED, + }, + .colorKeys = FF_COLOR_FG_MAGENTA, + .colorTitle = FF_COLOR_FG_RED, + }, // ChonkySealOS { .names = {"ChonkySealOS"}, @@ -1264,6 +1277,17 @@ static const FFlogo E[] = { .colorKeys = FF_COLOR_FG_MAGENTA, .colorTitle = FF_COLOR_FG_RED, }, + // EndeavourSmall + { + .names = {"Endeavour_small", "endeavour-linux_small", "endeavouros_small", "endeavouros-linux_small"}, + .lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL, + .type = FF_LOGO_LINE_TYPE_SMALL_BIT, + .colors = { + FF_COLOR_FG_RED, + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_BLUE, + }, + }, // Endless { .names = {"Endless"}, @@ -4136,6 +4160,16 @@ static const FFlogo W[] = { }; static const FFlogo X[] = { + // Xenia + { + .names = {"Xenia"}, + .lines = FASTFETCH_DATATEXT_LOGO_XENIA, + .colors = { + FF_COLOR_FG_YELLOW, + FF_COLOR_FG_GREEN, + FF_COLOR_FG_RED, + } + }, // Xferience { .names = {"Xferience"}, diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 85103b5c8b..67ca2eed08 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -103,7 +103,7 @@ void ffPrintBattery(FFBatteryOptions* options) void ffInitBatteryOptions(FFBatteryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BATTERY_MODULE_NAME, ffParseBatteryCommandOptions, ffParseBatteryJsonObject, ffPrintBattery, ffGenerateBatteryJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BATTERY_MODULE_NAME, ffParseBatteryCommandOptions, ffParseBatteryJsonObject, ffPrintBattery, ffGenerateBatteryJson, ffPrintBatteryHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; @@ -208,3 +208,14 @@ void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjso ffStrbufDestroy(&battery->status); } } + +void ffPrintBatteryHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BATTERY_MODULE_NAME, "{4}, {5}", FF_BATTERY_NUM_FORMAT_ARGS, (const char* []) { + "Battery manufactor", + "Battery model", + "Battery technology", + "Battery capacity (percentage)", + "Battery status" + }); +} diff --git a/src/modules/battery/battery.h b/src/modules/battery/battery.h index adefbdeddf..d50ad8bae2 100644 --- a/src/modules/battery/battery.h +++ b/src/modules/battery/battery.h @@ -11,3 +11,4 @@ bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, co void ffDestroyBatteryOptions(FFBatteryOptions* options); void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module); void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBatteryHelpFormat(void); diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index b3f3e598ce..6658cfac6f 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -55,7 +55,7 @@ void ffPrintBios(FFBiosOptions* options) void ffInitBiosOptions(FFBiosOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BIOS_MODULE_NAME, ffParseBiosCommandOptions, ffParseBiosJsonObject, ffPrintBios, ffGenerateBiosJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BIOS_MODULE_NAME, ffParseBiosCommandOptions, ffParseBiosJsonObject, ffPrintBios, ffGenerateBiosJson, ffPrintBiosHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -125,3 +125,13 @@ void ffGenerateBiosJson(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut_doc* ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); } + +void ffPrintBiosHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BIOS_MODULE_NAME, "{4} ({2})", FF_BIOS_NUM_FORMAT_ARGS, (const char* []) { + "bios date", + "bios release", + "bios vendor", + "bios version" + }); +} diff --git a/src/modules/bios/bios.h b/src/modules/bios/bios.h index a3bb81d8d1..db7ab37040 100644 --- a/src/modules/bios/bios.h +++ b/src/modules/bios/bios.h @@ -10,3 +10,4 @@ bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const ch void ffDestroyBiosOptions(FFBiosOptions* options); void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module); void ffGenerateBiosJson(FFBiosOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBiosHelpFormat(void); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index ade503bc1c..6ddfb173c6 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -75,7 +75,7 @@ void ffPrintBluetooth(FFBluetoothOptions* options) void ffInitBluetoothOptions(FFBluetoothOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, ffGenerateBluetoothJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, ffGenerateBluetoothJson, ffPrintBluetoothHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->showDisconnected = false; } @@ -156,3 +156,13 @@ void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson ffStrbufDestroy(&device->address); } } + +void ffPrintBluetoothHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BLUETOOTH_MODULE_NAME, "{1} ({4})", FF_BLUETOOTH_NUM_FORMAT_ARGS, (const char* []) { + "Name", + "Address", + "Type", + "Battery percentage" + }); +} diff --git a/src/modules/bluetooth/bluetooth.h b/src/modules/bluetooth/bluetooth.h index b4d1f0a89f..dbccd1410f 100644 --- a/src/modules/bluetooth/bluetooth.h +++ b/src/modules/bluetooth/bluetooth.h @@ -10,3 +10,4 @@ bool ffParseBluetoothCommandOptions(FFBluetoothOptions* options, const char* key void ffDestroyBluetoothOptions(FFBluetoothOptions* options); void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module); void ffGenerateBluetoothJson(FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBluetoothHelpFormat(void); diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 17e187adee..7dde50d89f 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -51,7 +51,7 @@ void ffPrintBoard(FFBoardOptions* options) void ffInitBoardOptions(FFBoardOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BOARD_MODULE_NAME, ffParseBoardCommandOptions, ffParseBoardJsonObject, ffPrintBoard, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BOARD_MODULE_NAME, ffParseBoardCommandOptions, ffParseBoardJsonObject, ffPrintBoard, ffGenerateBoardJson, ffPrintBoardHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -118,3 +118,12 @@ void ffGenerateBoardJson(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_mut_doc ffStrbufDestroy(&board.vendor); ffStrbufDestroy(&board.version); } + +void ffPrintBoardHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BOARD_MODULE_NAME, "{1} ({3})", FF_BOARD_NUM_FORMAT_ARGS, (const char* []) { + "board name", + "board vendor", + "board version" + }); +} diff --git a/src/modules/board/board.h b/src/modules/board/board.h index 0e1dabbaba..f1a8e46e8c 100644 --- a/src/modules/board/board.h +++ b/src/modules/board/board.h @@ -10,3 +10,4 @@ bool ffParseBoardCommandOptions(FFBoardOptions* options, const char* key, const void ffDestroyBoardOptions(FFBoardOptions* options); void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module); void ffGenerateBoardJson(FFBoardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBoardHelpFormat(void); diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 59c39c1d72..e52e357e67 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -9,7 +9,7 @@ void ffPrintBreak(FF_MAYBE_UNUSED FFBreakOptions* options) void ffInitBreakOptions(FF_MAYBE_UNUSED FFBreakOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BREAK_MODULE_NAME, ffParseBreakCommandOptions, ffParseBreakJsonObject, ffPrintBreak, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BREAK_MODULE_NAME, ffParseBreakCommandOptions, ffParseBreakJsonObject, ffPrintBreak, NULL, NULL); } bool ffParseBreakCommandOptions(FF_MAYBE_UNUSED FFBreakOptions* options, FF_MAYBE_UNUSED const char* key, FF_MAYBE_UNUSED const char* value) diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 261122bb06..eaedf10a96 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -11,7 +11,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFBrightnessResult)); - const char* error = ffDetectBrightness(&result); + const char* error = ffDetectBrightness(options, &result); if(error) { @@ -86,8 +86,10 @@ void ffPrintBrightness(FFBrightnessOptions* options) void ffInitBrightnessOptions(FFBrightnessOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson, ffPrintBrightnessHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); + + options->ddcciSleep = 10; } bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value) @@ -97,6 +99,12 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffStrEqualsIgnCase(key, "ddcci-sleep")) + { + options->ddcciSleep = ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -118,6 +126,12 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffStrEqualsIgnCase(key, "ddcciSleep")) + { + options->ddcciSleep = (uint32_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -126,7 +140,7 @@ void ffGenerateBrightnessJson(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjs { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFBrightnessResult)); - const char* error = ffDetectBrightness(&result); + const char* error = ffDetectBrightness(options, &result); if (error) { @@ -157,3 +171,14 @@ void ffGenerateBrightnessJson(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjs ffStrbufDestroy(&item->name); } } + +void ffPrintBrightnessHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BRIGHTNESS_MODULE_NAME, "{1}", FF_BRIGHTNESS_NUM_FORMAT_ARGS, (const char* []) { + "Screen brightness (percentage)", + "Screen name", + "Maximum brightness value", + "Minimum brightness value", + "Current brightness value", + }); +} diff --git a/src/modules/brightness/brightness.h b/src/modules/brightness/brightness.h index 6933c65009..453a4532c3 100644 --- a/src/modules/brightness/brightness.h +++ b/src/modules/brightness/brightness.h @@ -10,3 +10,4 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k void ffDestroyBrightnessOptions(FFBrightnessOptions* options); void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module); void ffGenerateBrightnessJson(FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBrightnessHelpFormat(void); diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index aa67ac1903..cad3e7ac8d 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -8,4 +8,6 @@ typedef struct FFBrightnessOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + uint32_t ddcciSleep; // ms } FFBrightnessOptions; diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 28a0f557dc..fc915a200a 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -52,7 +52,7 @@ void ffPrintChassis(FFChassisOptions* options) void ffInitChassisOptions(FFChassisOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, ffGenerateChassisJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, ffGenerateChassisJson, ffPrintChassisHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -119,3 +119,12 @@ void ffGenerateChassisJson(FF_MAYBE_UNUSED FFChassisOptions* options, yyjson_mut ffStrbufDestroy(&result.vendor); ffStrbufDestroy(&result.version); } + +void ffPrintChassisHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CHASSIS_MODULE_NAME, "{1}", FF_CHASSIS_NUM_FORMAT_ARGS, (const char* []) { + "chassis type", + "chassis vendor", + "chassis version" + }); +} diff --git a/src/modules/chassis/chassis.h b/src/modules/chassis/chassis.h index c5553f7722..f0d810d166 100644 --- a/src/modules/chassis/chassis.h +++ b/src/modules/chassis/chassis.h @@ -10,3 +10,4 @@ bool ffParseChassisCommandOptions(FFChassisOptions* options, const char* key, co void ffDestroyChassisOptions(FFChassisOptions* options); void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module); void ffGenerateChassisJson(FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintChassisHelpFormat(void); diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 4bcf9bafd2..4ac68d12e5 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -57,7 +57,7 @@ void ffPrintColors(FFColorsOptions* options) void ffInitColorsOptions(FFColorsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors, NULL, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); options->symbol = FF_COLORS_SYMBOL_BLOCK; diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 393aab97b7..5273e74ca0 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -4,6 +4,8 @@ #include "modules/command/command.h" #include "util/stringUtils.h" +#define FF_COMMAND_NUM_FORMAT_ARGS 1 + void ffPrintCommand(FFCommandOptions* options) { FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); @@ -30,13 +32,22 @@ void ffPrintCommand(FFCommandOptions* options) return; } - ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufPutTo(&result, stdout); + if (options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&result, stdout); + } + else + { + ffPrintFormat(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_COMMAND_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &result} + }); + } } void ffInitCommandOptions(FFCommandOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, ffGenerateCommandJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, ffGenerateCommandJson, ffPrintCommandHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInitStatic(&options->shell, @@ -136,3 +147,10 @@ void ffGenerateCommandJson(FF_MAYBE_UNUSED FFCommandOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, module, "result", &result); } + +void ffPrintCommandHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_COMMAND_MODULE_NAME, "{1}", FF_COMMAND_NUM_FORMAT_ARGS, (const char* []) { + "Command result" + }); +} diff --git a/src/modules/command/command.h b/src/modules/command/command.h index ec8e2bab37..932b1b8c3c 100644 --- a/src/modules/command/command.h +++ b/src/modules/command/command.h @@ -10,3 +10,4 @@ bool ffParseCommandCommandOptions(FFCommandOptions* options, const char* key, co void ffDestroyCommandOptions(FFCommandOptions* options); void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module); void ffGenerateCommandJson(FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCommandHelpFormat(void); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 3cd5a6cf7a..133bebec95 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -48,7 +48,7 @@ void ffPrintCPU(FFCPUOptions* options) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); if(cpu.frequencyMax > 0.0) - ffStrbufAppendF(&str, " @ %.9g GHz", cpu.frequencyMax); + ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, cpu.frequencyMax); if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET { @@ -79,9 +79,10 @@ void ffPrintCPU(FFCPUOptions* options) void ffInitCPUOptions(FFCPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, ffGenerateCPUJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, ffGenerateCPUJson, ffPrintCPUHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; + options->freqNdigits = 2; } bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char* value) @@ -97,6 +98,12 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char return true; } + if (ffStrEqualsIgnCase(subKey, "freq-ndigits")) + { + options->freqNdigits = (uint8_t) ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -124,6 +131,12 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "freqNdigits")) + { + options->freqNdigits = (uint8_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -168,3 +181,17 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va ffStrbufDestroy(&cpu.name); ffStrbufDestroy(&cpu.vendor); } + +void ffPrintCPUHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CPU_MODULE_NAME, "{1} ({5}) @ {7} GHz", FF_CPU_NUM_FORMAT_ARGS, (const char* []) { + "Name", + "Vendor", + "Physical core count", + "Logical core count", + "Online core count", + "Min frequency", + "Max frequency", + "Temperature" + }); +} diff --git a/src/modules/cpu/cpu.h b/src/modules/cpu/cpu.h index 0a3e7c4c62..dac7362765 100644 --- a/src/modules/cpu/cpu.h +++ b/src/modules/cpu/cpu.h @@ -10,3 +10,4 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char void ffDestroyCPUOptions(FFCPUOptions* options); void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module); void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCPUHelpFormat(void); diff --git a/src/modules/cpu/option.h b/src/modules/cpu/option.h index 1902ddfc27..ae5699939c 100644 --- a/src/modules/cpu/option.h +++ b/src/modules/cpu/option.h @@ -10,4 +10,5 @@ typedef struct FFCPUOptions FFModuleArgs moduleArgs; bool temp; + uint8_t freqNdigits; } FFCPUOptions; diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index ca0909377a..c5cd12345a 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -6,12 +6,12 @@ #include "util/stringUtils.h" #define FF_CPUUSAGE_DISPLAY_NAME "CPU Usage" -#define FF_CPUUSAGE_NUM_FORMAT_ARGS 1 +#define FF_CPUUSAGE_NUM_FORMAT_ARGS 5 void ffPrintCPUUsage(FFCPUUsageOptions* options) { - double percentage = 0.0/0.0; - const char* error = ffGetCpuUsageResult(&percentage); + FF_LIST_AUTO_DESTROY percentages = ffListCreate(sizeof(double)); + const char* error = ffGetCpuUsageResult(&percentages); if(error) { @@ -19,34 +19,75 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) return; } + double maxValue = -999, minValue = 999, sumValue = 0; + uint32_t maxIndex = 999, minIndex = 999; + + uint32_t index = 0; + FF_LIST_FOR_EACH(double, percent, percentages) + { + sumValue += *percent; + if (*percent > maxValue) + { + maxValue = *percent; + maxIndex = index; + } + if (*percent < minValue) + { + minValue = *percent; + minIndex = index; + } + ++index; + } + double avgValue = sumValue / (double) percentages.length; + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) - ffAppendPercentBar(&str, percentage, 0, 50, 80); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if (!options->separate) + { + if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffAppendPercentBar(&str, avgValue, 0, 50, 80); + if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + { + if(str.length > 0) + ffStrbufAppendC(&str, ' '); + ffAppendPercentNum(&str, avgValue, 50, 80, str.length > 0); + } + } + else { - if(str.length > 0) - ffStrbufAppendC(&str, ' '); - ffAppendPercentNum(&str, percentage, 50, 80, str.length > 0); + FF_LIST_FOR_EACH(double, percent, percentages) + { + if(str.length > 0) + ffStrbufAppendC(&str, ' '); + ffAppendPercentNum(&str, *percent, 50, 80, false); + } } ffStrbufPutTo(&str, stdout); } else { - FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate(); - ffAppendPercentNum(&percentageStr, percentage, 50, 80, false); + FF_STRBUF_AUTO_DESTROY avgStr = ffStrbufCreate(); + ffAppendPercentNum(&avgStr, avgValue, 50, 80, false); + FF_STRBUF_AUTO_DESTROY minStr = ffStrbufCreate(); + ffAppendPercentNum(&minStr, minValue, 50, 80, false); + FF_STRBUF_AUTO_DESTROY maxStr = ffStrbufCreate(); + ffAppendPercentNum(&maxStr, maxValue, 50, 80, false); ffPrintFormat(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_CPUUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr} + {FF_FORMAT_ARG_TYPE_STRBUF, &avgStr}, + {FF_FORMAT_ARG_TYPE_STRBUF, &maxStr}, + {FF_FORMAT_ARG_TYPE_UINT, &maxIndex}, + {FF_FORMAT_ARG_TYPE_STRBUF, &minStr}, + {FF_FORMAT_ARG_TYPE_UINT, &minIndex}, }); } } void ffInitCPUUsageOptions(FFCPUUsageOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, ffGenerateCPUUsageJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, ffGenerateCPUUsageJson, ffPrintCPUUsageHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -57,6 +98,12 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffStrEqualsIgnCase(subKey, "separate")) + { + options->separate = ffOptionParseBoolean(value); + return true; + } + return false; } @@ -78,19 +125,40 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffStrEqualsIgnCase(key, "separate")) + { + options->separate = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } void ffGenerateCPUUsageJson(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - double percentage = 0.0/0.0; - const char* error = ffGetCpuUsageResult(&percentage); + FF_LIST_AUTO_DESTROY percentages = ffListCreate(sizeof(double)); + const char* error = ffGetCpuUsageResult(&percentages); if(error) { yyjson_mut_obj_add_str(doc, module, "error", error); return; } - yyjson_mut_obj_add_real(doc, module, "result", percentage); + yyjson_mut_val* result = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(double, percent, percentages) + { + yyjson_mut_arr_add_real(doc, result, *percent); + } +} + +void ffPrintCPUUsageHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CPUUSAGE_MODULE_NAME, "{1}", FF_CPUUSAGE_NUM_FORMAT_ARGS, (const char* []) { + "CPU usage (percentage, average)", + "CPU usage (percentage, maximum)", + "CPU core index of maximum usage", + "CPU usage (percentage, minimum)", + "CPU core index of minimum usage", + }); } diff --git a/src/modules/cpuusage/cpuusage.h b/src/modules/cpuusage/cpuusage.h index e31bc14c78..51af8bb222 100644 --- a/src/modules/cpuusage/cpuusage.h +++ b/src/modules/cpuusage/cpuusage.h @@ -12,3 +12,4 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options); void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module); void ffGenerateCPUUsageJson(FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCPUUsageHelpFormat(void); diff --git a/src/modules/cpuusage/option.h b/src/modules/cpuusage/option.h index 9468553016..d7fea247d7 100644 --- a/src/modules/cpuusage/option.h +++ b/src/modules/cpuusage/option.h @@ -8,4 +8,6 @@ typedef struct FFCPUUsageOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + bool separate; } FFCPUUsageOptions; diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 555ec0374c..2de69177db 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -52,7 +52,7 @@ void ffPrintCursor(FFCursorOptions* options) void ffInitCursorOptions(FFCursorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, ffGenerateCursorJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, ffGenerateCursorJson, ffPrintCursorHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -111,3 +111,11 @@ void ffGenerateCursorJson(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson_mut_d ffStrbufDestroy(&result.theme); ffStrbufDestroy(&result.size); } + +void ffPrintCursorHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CURSOR_MODULE_NAME, "{1} ({2}px)", FF_CURSOR_NUM_FORMAT_ARGS, (const char* []) { + "Cursor theme", + "Cursor size" + }); +} diff --git a/src/modules/cursor/cursor.h b/src/modules/cursor/cursor.h index 02ed47e8fd..44dff4909a 100644 --- a/src/modules/cursor/cursor.h +++ b/src/modules/cursor/cursor.h @@ -10,3 +10,4 @@ bool ffParseCursorCommandOptions(FFCursorOptions* options, const char* key, cons void ffDestroyCursorOptions(FFCursorOptions* options); void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module); void ffGenerateCursorJson(FFCursorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCursorHelpFormat(void); diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 6576cd3c5e..11104d6c1f 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -19,7 +19,7 @@ void ffPrintCustom(FFCustomOptions* options) void ffInitCustomOptions(FFCustomOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom, NULL, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); } diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index adc7c50cf9..50cad80f95 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -143,7 +143,7 @@ void ffPrintDateTime(FFDateTimeOptions* options) void ffInitDateTimeOptions(FFDateTimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, ffGenerateDateTimeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, ffGenerateDateTimeJson, ffPrintDateTimeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -183,3 +183,29 @@ void ffGenerateDateTimeJson(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_m { yyjson_mut_obj_add_uint(doc, module, "result", ffTimeGetNow()); } + +void ffPrintDateTimeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DATETIME_MODULE_NAME, "{1}-{4}-{11} {14}:{18}:{20}", FF_DATETIME_NUM_FORMAT_ARGS, (const char* []) { + "year", + "last two digits of year", + "month", + "month with leading zero", + "month name", + "month name short", + "week number on year", + "weekday", + "weekday short", + "day in year", + "day in month", + "day in Week", + "hour", + "hour with leading zero", + "hour 12h format", + "hour 12h format with leading zero", + "minute", + "minute with leading zero", + "second", + "second with leading zero" + }); +} diff --git a/src/modules/datetime/datetime.h b/src/modules/datetime/datetime.h index 8f4ceb6908..ef1f91dcbc 100644 --- a/src/modules/datetime/datetime.h +++ b/src/modules/datetime/datetime.h @@ -10,3 +10,4 @@ bool ffParseDateTimeCommandOptions(FFDateTimeOptions* options, const char* key, void ffDestroyDateTimeOptions(FFDateTimeOptions* options); void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module); void ffGenerateDateTimeJson(FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDateTimeHelpFormat(void); diff --git a/src/modules/de/de.c b/src/modules/de/de.c index a6d896d7ce..0ea30ca013 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -42,7 +42,7 @@ void ffPrintDE(FFDEOptions* options) void ffInitDEOptions(FFDEOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, ffGenerateDEJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, ffGenerateDEJson, ffPrintDEHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -93,3 +93,12 @@ void ffGenerateDEJson(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->dePrettyName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->deVersion); } + +void ffPrintDEHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DE_MODULE_NAME, "{2} {3}", FF_DE_NUM_FORMAT_ARGS, (const char* []) { + "DE process name", + "DE pretty name", + "DE version" + }); +} diff --git a/src/modules/de/de.h b/src/modules/de/de.h index b8d122184f..6b1ea47780 100644 --- a/src/modules/de/de.h +++ b/src/modules/de/de.h @@ -10,3 +10,4 @@ bool ffParseDECommandOptions(FFDEOptions* options, const char* key, const char* void ffDestroyDEOptions(FFDEOptions* options); void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module); void ffGenerateDEJson(FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDEHelpFormat(void); diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index e6c976f0eb..1e789d433e 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -34,9 +34,10 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) } else { - ffParseFormatString(&key, &options->moduleArgs.key, 2, (FFformatarg[]){ + ffParseFormatString(&key, &options->moduleArgs.key, 3, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &disk->mountpoint}, {FF_FORMAT_ARG_TYPE_STRBUF, &disk->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &disk->mountFrom}, }); } @@ -111,19 +112,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT); bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT); bool isReadOnly = !!(disk->type & FF_DISK_VOLUME_TYPE_READONLY_BIT); - const char* physicalType; - switch(disk->physicalType) - { - case FF_DISK_PHYSICAL_TYPE_HDD: - physicalType = "HDD"; - break; - case FF_DISK_PHYSICAL_TYPE_SSD: - physicalType = "SSD"; - break; - default: - physicalType = "Unknown"; - break; - } ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, @@ -136,7 +124,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) {FF_FORMAT_ARG_TYPE_STRBUF, &disk->filesystem}, {FF_FORMAT_ARG_TYPE_STRBUF, &disk->name}, {FF_FORMAT_ARG_TYPE_BOOL, &isReadOnly}, - {FF_FORMAT_ARG_TYPE_STRING, physicalType} }); } } @@ -217,7 +204,7 @@ void ffPrintDisk(FFDiskOptions* options) void ffInitDiskOptions(FFDiskOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, ffGenerateDiskJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, ffGenerateDiskJson, ffPrintDiskHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->folders); @@ -428,19 +415,6 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ yyjson_mut_arr_add_str(doc, typeArr, "Hidden"); if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT) yyjson_mut_arr_add_str(doc, typeArr, "Read-only"); - - switch(item->physicalType) - { - case FF_DISK_PHYSICAL_TYPE_HDD: - yyjson_mut_obj_add_str(doc, obj, "physicalType", "HDD"); - break; - case FF_DISK_PHYSICAL_TYPE_SSD: - yyjson_mut_obj_add_str(doc, obj, "physicalType", "SSD"); - break; - default: - yyjson_mut_obj_add_null(doc, obj, "physicalType"); - break; - } } FF_LIST_FOR_EACH(FFDisk, item, disks) @@ -451,3 +425,18 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ ffStrbufDestroy(&item->name); } } + +void ffPrintDiskHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DISK_MODULE_NAME, "{1} / {2} ({3}) - {9}", FF_DISK_NUM_FORMAT_ARGS, (const char* []) { + "Size used", + "Size total", + "Size percentage", + "Files used", + "Files total", + "Files percentage", + "True if external volume", + "True if hidden volume", + "Filesystem" + }); +} diff --git a/src/modules/disk/disk.h b/src/modules/disk/disk.h index eb4520b351..a3ee43e184 100644 --- a/src/modules/disk/disk.h +++ b/src/modules/disk/disk.h @@ -10,3 +10,4 @@ bool ffParseDiskCommandOptions(FFDiskOptions* options, const char* key, const ch void ffDestroyDiskOptions(FFDiskOptions* options); void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module); void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDiskHelpFormat(void); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c new file mode 100644 index 0000000000..cb7c981dc2 --- /dev/null +++ b/src/modules/diskio/diskio.c @@ -0,0 +1,228 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "common/parsing.h" +#include "detection/diskio/diskio.h" +#include "modules/diskio/diskio.h" +#include "util/stringUtils.h" + +#define FF_DISKIO_DISPLAY_NAME "Disk IO" +#define FF_DISKIO_NUM_FORMAT_ARGS 10 + +static int sortDevices(const FFDiskIOResult* left, const FFDiskIOResult* right) +{ + return ffStrbufComp(&left->name, &right->name); +} + +static void formatKey(const FFDiskIOOptions* options, FFDiskIOResult* dev, uint32_t index, FFstrbuf* key) +{ + if(options->moduleArgs.key.length == 0) + { + if(!dev->name.length) + ffStrbufSetF(&dev->name, "unknown %u", (unsigned) index); + + ffStrbufSetF(key, FF_DISKIO_DISPLAY_NAME " (%s)", dev->name.chars); + } + else + { + ffStrbufClear(key); + ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, + }); + } +} + +void ffPrintDiskIO(FFDiskIOOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFDiskIOResult)); + const char* error = ffDetectDiskIO(&result, options); + + if(error) + { + ffPrintError(FF_DISKIO_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); + return; + } + + ffListSort(&result, (const void*) sortDevices); + + uint32_t index = 0; + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + formatKey(options, dev, result.length == 1 ? 0 : index + 1, &key); + ffStrbufClear(&buffer); + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + ffParseSize(dev->bytesRead, &buffer); + ffStrbufAppendS(&buffer, "/s (R) - "); + ffParseSize(dev->bytesWritten, &buffer); + ffStrbufAppendS(&buffer, "/s (W)"); + ffStrbufPutTo(&buffer, stdout); + } + else + { + ffStrbufClear(&buffer2); + ffParseSize(dev->bytesRead, &buffer); + ffStrbufAppendS(&buffer, "/s"); + ffParseSize(dev->bytesWritten, &buffer2); + ffStrbufAppendS(&buffer2, "/s"); + + const char* physicalType; + switch(dev->type) + { + case FF_DISKIO_PHYSICAL_TYPE_HDD: + physicalType = "HDD"; + break; + case FF_DISKIO_PHYSICAL_TYPE_SSD: + physicalType = "SSD"; + break; + default: + physicalType = "Unknown"; + break; + } + + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISKIO_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->interconnect}, + {FF_FORMAT_ARG_TYPE_STRING, physicalType}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesRead}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesWritten}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->readCount}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->writeCount}, + }); + } + ++index; + } + + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + ffStrbufDestroy(&dev->name); + ffStrbufDestroy(&dev->interconnect); + ffStrbufDestroy(&dev->devPath); + } +} + +void ffInitDiskIOOptions(FFDiskIOOptions* options) +{ + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISKIO_MODULE_NAME, ffParseDiskIOCommandOptions, ffParseDiskIOJsonObject, ffPrintDiskIO, ffGenerateDiskIOJson, ffPrintDiskIOHelpFormat); + ffOptionInitModuleArg(&options->moduleArgs); + + ffStrbufInit(&options->namePrefix); +} + +bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_DISKIO_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + if (ffStrEqualsIgnCase(subKey, "name-prefix")) + { + ffOptionParseString(key, value, &options->namePrefix); + return true; + } + + return false; +} + +void ffDestroyDiskIOOptions(FFDiskIOOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); +} + +void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + if (ffStrEqualsIgnCase(key, "namePrefix")) + { + ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + continue; + } + + ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); + } +} + +void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFDiskIOResult)); + const char* error = ffDetectDiskIO(&result, options); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name); + yyjson_mut_obj_add_strbuf(doc, obj, "interconnectType", &dev->interconnect); + yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &dev->devPath); + + switch(dev->type) + { + case FF_DISKIO_PHYSICAL_TYPE_HDD: + yyjson_mut_obj_add_str(doc, obj, "physicalType", "HDD"); + break; + case FF_DISKIO_PHYSICAL_TYPE_SSD: + yyjson_mut_obj_add_str(doc, obj, "physicalType", "SSD"); + break; + default: + yyjson_mut_obj_add_null(doc, obj, "physicalType"); + break; + } + + yyjson_mut_obj_add_uint(doc, obj, "bytesRead", dev->bytesRead); + yyjson_mut_obj_add_uint(doc, obj, "bytesWritten", dev->bytesWritten); + yyjson_mut_obj_add_uint(doc, obj, "readCount", dev->readCount); + yyjson_mut_obj_add_uint(doc, obj, "writeCount", dev->writeCount); + } + + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + ffStrbufDestroy(&dev->name); + ffStrbufDestroy(&dev->interconnect); + ffStrbufDestroy(&dev->devPath); + } +} + +void ffPrintDiskIOHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DISKIO_MODULE_NAME, "{1} (R) - {2} (W)", FF_DISKIO_NUM_FORMAT_ARGS, (const char* []) { + "Size of data read per second (formatted)", + "Size of data written per second (formatted)", + "Device name", + "Device interconnect type", + "Device physical type (SSD / HDD)", + "Device raw file path", + "Size of data read per second (in bytes)", + "Size of data written per second (in bytes)", + "Number of reads", + "Number of writes", + }); +} diff --git a/src/modules/diskio/diskio.h b/src/modules/diskio/diskio.h new file mode 100644 index 0000000000..ab4502f11a --- /dev/null +++ b/src/modules/diskio/diskio.h @@ -0,0 +1,15 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_DISKIO_MODULE_NAME "DiskIO" + +void ffPrepareDiskIO(FFDiskIOOptions* options); + +void ffPrintDiskIO(FFDiskIOOptions* options); +void ffInitDiskIOOptions(FFDiskIOOptions* options); +bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, const char* value); +void ffDestroyDiskIOOptions(FFDiskIOOptions* options); +void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module); +void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDiskIOHelpFormat(void); diff --git a/src/modules/diskio/option.h b/src/modules/diskio/option.h new file mode 100644 index 0000000000..b3e3303553 --- /dev/null +++ b/src/modules/diskio/option.h @@ -0,0 +1,13 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFDiskIOOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; + + FFstrbuf namePrefix; +} FFDiskIOOptions; diff --git a/src/modules/display/display.c b/src/modules/display/display.c index f623bc5f4f..c52bf42a66 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -112,7 +112,7 @@ void ffPrintDisplay(FFDisplayOptions* options) void ffInitDisplayOptions(FFDisplayOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, ffGenerateDisplayJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, ffGenerateDisplayJson, ffPrintDisplayHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; options->preciseRefreshRate = false; @@ -225,3 +225,17 @@ void ffGenerateDisplayJson(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut } } } + +void ffPrintDisplayHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DISPLAY_MODULE_NAME, "{1}x{2} @ {3}Hz (as {4}x{5}) [{7}]", FF_DISPLAY_NUM_FORMAT_ARGS, (const char* []) { + "Screen width (in pixels)", + "Screen height (in pixels)", + "Screen refresh rate (in Hz)", + "Screen scaled width (in pixels)", + "Screen scaled height (in pixels)", + "Screen name", + "Screen type (builtin, external or unknown)", + "Screen rotation (in degrees)", + }); +} diff --git a/src/modules/display/display.h b/src/modules/display/display.h index 6c46dfb18c..b01a97ef14 100644 --- a/src/modules/display/display.h +++ b/src/modules/display/display.h @@ -10,3 +10,4 @@ bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, co void ffDestroyDisplayOptions(FFDisplayOptions* options); void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module); void ffGenerateDisplayJson(FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDisplayHelpFormat(void); diff --git a/src/modules/font/font.c b/src/modules/font/font.c index a737c615e9..c4ea4e62e3 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -45,7 +45,7 @@ void ffPrintFont(FFFontOptions* options) void ffInitFontOptions(FFFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, ffGenerateFontJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, ffGenerateFontJson, ffPrintFontHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -106,3 +106,14 @@ void ffGenerateFontJson(FF_MAYBE_UNUSED FFFontOptions* options, yyjson_mut_doc* for (uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i) ffStrbufDestroy(&font.fonts[i]); } + +void ffPrintFontHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_FONT_MODULE_NAME, "{5}", FF_FONT_NUM_FORMAT_ARGS, (const char* []) { + "Font 1", + "Font 2", + "Font 3", + "Font 4", + "Combined fonts" + }); +} diff --git a/src/modules/font/font.h b/src/modules/font/font.h index dedb1dfb95..5d8631a9e7 100644 --- a/src/modules/font/font.h +++ b/src/modules/font/font.h @@ -10,3 +10,4 @@ bool ffParseFontCommandOptions(FFFontOptions* options, const char* key, const ch void ffDestroyFontOptions(FFFontOptions* options); void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module); void ffGenerateFontJson(FFFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintFontHelpFormat(void); diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 43818aa2fa..b0a5b50430 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -51,7 +51,7 @@ void ffPrintGamepad(FFGamepadOptions* options) void ffInitGamepadOptions(FFGamepadOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, ffGenerateGamepadJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, ffGenerateGamepadJson, ffPrintGamepadHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -119,3 +119,11 @@ void ffGenerateGamepadJson(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjson_mut ffStrbufDestroy(&device->name); } } + +void ffPrintGamepadHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_GAMEPAD_MODULE_NAME, "{1}", FF_GAMEPAD_NUM_FORMAT_ARGS, (const char* []) { + "Name", + "Identifier" + }); +} diff --git a/src/modules/gamepad/gamepad.h b/src/modules/gamepad/gamepad.h index eff98e9925..ff05a4dbc5 100644 --- a/src/modules/gamepad/gamepad.h +++ b/src/modules/gamepad/gamepad.h @@ -10,3 +10,4 @@ bool ffParseGamepadCommandOptions(FFGamepadOptions* options, const char* key, co void ffDestroyGamepadOptions(FFGamepadOptions* options); void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module); void ffGenerateGamepadJson(FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintGamepadHelpFormat(void); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 95a25df3b1..acc8ab0a7f 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -10,7 +10,7 @@ #include -#define FF_GPU_NUM_FORMAT_ARGS 6 +#define FF_GPU_NUM_FORMAT_ARGS 10 static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) { @@ -77,6 +77,10 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}, {FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount}, {FF_FORMAT_ARG_TYPE_STRING, type}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.total}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.used}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.total}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.used}, }); } } @@ -121,7 +125,7 @@ void ffPrintGPU(FFGPUOptions* options) void ffInitGPUOptions(FFGPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, ffGenerateGPUJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, ffGenerateGPUJson, ffPrintGPUHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->forceVulkan = false; @@ -277,3 +281,19 @@ void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va ffStrbufDestroy(&gpu->driver); } } + +void ffPrintGPUHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_GPU_MODULE_NAME, "{1} {2}", FF_GPU_NUM_FORMAT_ARGS, (const char* []) { + "GPU vendor", + "GPU name", + "GPU driver", + "GPU temperature", + "GPU core count", + "GPU type", + "GPU total dedicated memory", + "GPU used dedicated memory", + "GPU total shared memory", + "GPU used shared memory", + }); +} diff --git a/src/modules/gpu/gpu.h b/src/modules/gpu/gpu.h index 73bd7fad51..0c1d73bb2e 100644 --- a/src/modules/gpu/gpu.h +++ b/src/modules/gpu/gpu.h @@ -10,3 +10,4 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char void ffDestroyGPUOptions(FFGPUOptions* options); void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module); void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintGPUHelpFormat(void); diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 30df24f127..f65f300302 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,7 +67,7 @@ void ffPrintHost(FFHostOptions* options) void ffInitHostOptions(FFHostOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, ffGenerateHostJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, ffGenerateHostJson, ffPrintHostHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -139,3 +139,14 @@ void ffGenerateHostJson(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut_doc* ffStrbufDestroy(&host.productSku); ffStrbufDestroy(&host.sysVendor); } + +void ffPrintHostHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_HOST_MODULE_NAME, "{2} {3}", FF_HOST_NUM_FORMAT_ARGS, (const char* []) { + "product family", + "product name", + "product version", + "product sku", + "sys vendor" + }); +} diff --git a/src/modules/host/host.h b/src/modules/host/host.h index 4ed4575a1c..c07789382d 100644 --- a/src/modules/host/host.h +++ b/src/modules/host/host.h @@ -10,3 +10,4 @@ bool ffParseHostCommandOptions(FFHostOptions* options, const char* key, const ch void ffDestroyHostOptions(FFHostOptions* options); void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module); void ffGenerateHostJson(FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintHostHelpFormat(void); diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 720432b70a..0b16ec141a 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -32,7 +32,7 @@ void ffPrintIcons(FFIconsOptions* options) void ffInitIconsOptions(FFIconsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, ffGenerateIconsJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, ffGenerateIconsJson, ffPrintIconsHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,10 @@ void ffGenerateIconsJson(FF_MAYBE_UNUSED FFIconsOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, module, "result", &icons); } + +void ffPrintIconsHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_ICONS_MODULE_NAME, "{1}", FF_ICONS_NUM_FORMAT_ARGS, (const char* []) { + "Combined icons" + }); +} diff --git a/src/modules/icons/icons.h b/src/modules/icons/icons.h index dab251e25e..f44c0db2db 100644 --- a/src/modules/icons/icons.h +++ b/src/modules/icons/icons.h @@ -10,3 +10,4 @@ bool ffParseIconsCommandOptions(FFIconsOptions* options, const char* key, const void ffDestroyIconsOptions(FFIconsOptions* options); void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module); void ffGenerateIconsJson(FFIconsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintIconsHelpFormat(void); diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 89aab0af12..56c81b118c 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -32,7 +32,7 @@ void ffPrintKernel(FFKernelOptions* options) void ffInitKernelOptions(FFKernelOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, ffGenerateKernelJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, ffGenerateKernelJson, ffPrintKernelHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -77,3 +77,12 @@ void ffGenerateKernelJson(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson_mut_d yyjson_mut_obj_add_strbuf(doc, obj, "version", &instance.state.platform.systemVersion); yyjson_mut_obj_add_strbuf(doc, obj, "displayVersion", &instance.state.platform.systemDisplayVersion); } + +void ffPrintKernelHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_KERNEL_MODULE_NAME, "{2}", FF_KERNEL_NUM_FORMAT_ARGS, (const char* []) { + "Kernel sysname", + "Kernel release", + "Kernel version" + }); +} diff --git a/src/modules/kernel/kernel.h b/src/modules/kernel/kernel.h index 419f2544a3..6adbe89ab9 100644 --- a/src/modules/kernel/kernel.h +++ b/src/modules/kernel/kernel.h @@ -10,3 +10,4 @@ bool ffParseKernelCommandOptions(FFKernelOptions* options, const char* key, cons void ffDestroyKernelOptions(FFKernelOptions* options); void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module); void ffGenerateKernelJson(FFKernelOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintKernelHelpFormat(void); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index f84a422a34..e64a0e8a2f 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -51,7 +51,7 @@ void ffPrintLM(FFLMOptions* options) void ffInitLMOptions(FFLMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LM_MODULE_NAME, ffParseLMCommandOptions, ffParseLMJsonObject, ffPrintLM, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LM_MODULE_NAME, ffParseLMCommandOptions, ffParseLMJsonObject, ffPrintLM, ffGenerateLMJson, ffPrintLMHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -117,3 +117,12 @@ void ffGenerateLMJson(FF_MAYBE_UNUSED FFLMOptions* options, yyjson_mut_doc* doc, ffStrbufDestroy(&result.type); ffStrbufDestroy(&result.version); } + +void ffPrintLMHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_LM_MODULE_NAME, "{1} {3} ({2})", FF_LM_NUM_FORMAT_ARGS, (const char* []) { + "LM service", + "LM type", + "LM version" + }); +} diff --git a/src/modules/lm/lm.h b/src/modules/lm/lm.h index 72509adcbd..4178e1c9fb 100644 --- a/src/modules/lm/lm.h +++ b/src/modules/lm/lm.h @@ -10,3 +10,4 @@ bool ffParseLMCommandOptions(FFLMOptions* options, const char* key, const char* void ffDestroyLMOptions(FFLMOptions* options); void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module); void ffGenerateLMJson(FFLMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintLMHelpFormat(void); diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 10c53ba3db..674e5f6f31 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -32,7 +32,7 @@ void ffPrintLocale(FFLocaleOptions* options) void ffInitLocaleOptions(FFLocaleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, ffGenerateLocaleJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, ffGenerateLocaleJson, ffPrintLocaleHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,10 @@ void ffGenerateLocaleJson(FF_MAYBE_UNUSED FFLocaleOptions* options, yyjson_mut_d yyjson_mut_obj_add_strbuf(doc, module, "result", &locale); } + +void ffPrintLocaleHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_LOCALE_MODULE_NAME, "{1}", FF_LOCALE_NUM_FORMAT_ARGS, (const char* []) { + "Locale code" + }); +} diff --git a/src/modules/locale/locale.h b/src/modules/locale/locale.h index 8570a3c8de..f0031e2bf0 100644 --- a/src/modules/locale/locale.h +++ b/src/modules/locale/locale.h @@ -10,3 +10,4 @@ bool ffParseLocaleCommandOptions(FFLocaleOptions* options, const char* key, cons void ffDestroyLocaleOptions(FFLocaleOptions* options); void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module); void ffGenerateLocaleJson(FFLocaleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintLocaleHelpFormat(void); diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 36013d5058..86b8e3a857 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -133,7 +133,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) void ffInitLocalIpOptions(FFLocalIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, ffGenerateLocalIpJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, ffGenerateLocalIpJson, ffPrintLocalIpHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->showType = FF_LOCALIP_TYPE_IPV4_BIT; @@ -326,3 +326,14 @@ void ffGenerateLocalIpJson(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjson_mut ffStrbufDestroy(&ip->mac); } } + +void ffPrintLocalIpHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_LOCALIP_MODULE_NAME, "{1}", FF_LOCALIP_NUM_FORMAT_ARGS, (const char* []) { + "Local IPv4 address", + "Local IPv6 address", + "Physical (MAC) address", + "Interface name", + "Is default route" + }); +} diff --git a/src/modules/localip/localip.h b/src/modules/localip/localip.h index 799860a429..b78f7df6b1 100644 --- a/src/modules/localip/localip.h +++ b/src/modules/localip/localip.h @@ -10,3 +10,4 @@ bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, co void ffDestroyLocalIpOptions(FFLocalIpOptions* options); void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module); void ffGenerateLocalIpJson(FFLocalIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintLocalIpHelpFormat(void); diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 7a0e01e770..61a3814a2a 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -107,7 +107,7 @@ void ffPrintMedia(FFMediaOptions* options) void ffInitMediaOptions(FFMediaOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, ffGenerateMediaJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, ffGenerateMediaJson, ffPrintMediaHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -159,3 +159,14 @@ void ffGenerateMediaJson(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "album", &media->album); yyjson_mut_obj_add_strbuf(doc, obj, "status", &media->status); } + +void ffPrintMediaHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_MEDIA_MODULE_NAME, "{3} - {1} ({5})", FF_MEDIA_NUM_FORMAT_ARGS, (const char* []) { + "Pretty media name", + "Media name", + "Artist name", + "Album name", + "Status", + }); +} diff --git a/src/modules/media/media.h b/src/modules/media/media.h index 853814d7e5..e9966c1808 100644 --- a/src/modules/media/media.h +++ b/src/modules/media/media.h @@ -10,3 +10,4 @@ bool ffParseMediaCommandOptions(FFMediaOptions* options, const char* key, const void ffDestroyMediaOptions(FFMediaOptions* options); void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module); void ffGenerateMediaJson(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintMediaHelpFormat(void); diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 1d2bba3913..faea2c7bd0 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -68,7 +68,7 @@ void ffPrintMemory(FFMemoryOptions* options) void ffInitMemoryOptions(FFMemoryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, ffGenerateMemoryJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, ffGenerateMemoryJson, ffPrintMemoryHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -119,3 +119,12 @@ void ffGenerateMemoryJson(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson_mut_d yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal); yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); } + +void ffPrintMemoryHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_MEMORY_MODULE_NAME, "{1} / {2} ({3})", FF_MEMORY_NUM_FORMAT_ARGS, (const char* []) { + "Used size", + "Total size", + "Percentage used" + }); +} diff --git a/src/modules/memory/memory.h b/src/modules/memory/memory.h index b4fefff5dc..9d86997ef5 100644 --- a/src/modules/memory/memory.h +++ b/src/modules/memory/memory.h @@ -10,3 +10,4 @@ bool ffParseMemoryCommandOptions(FFMemoryOptions* options, const char* key, cons void ffDestroyMemoryOptions(FFMemoryOptions* options); void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module); void ffGenerateMemoryJson(FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintMemoryHelpFormat(void); diff --git a/src/modules/modules.h b/src/modules/modules.h index 64ab6ea213..57632fb7dc 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -17,6 +17,7 @@ #include "modules/custom/custom.h" #include "modules/datetime/datetime.h" #include "modules/disk/disk.h" +#include "modules/diskio/diskio.h" #include "modules/display/display.h" #include "modules/de/de.h" #include "modules/font/font.h" diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index be0e22830c..271ccc67b9 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -77,7 +77,7 @@ void ffPrintMonitor(FFMonitorOptions* options) void ffInitMonitorOptions(FFMonitorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, ffGenerateMonitorJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, ffGenerateMonitorJson, ffPrintMonitorHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -147,3 +147,16 @@ void ffGenerateMonitorJson(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut ffStrbufDestroy(&item->name); } } + +void ffPrintMonitorHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_MONITOR_MODULE_NAME, "{2}x{3} px - {4}x{5} mm ({6} inches, {7} ppi)", FF_MONITOR_NUM_FORMAT_ARGS, (const char* []) { + "Display name", + "Display native resolution width in pixels", + "Display native resolution height in pixels", + "Display physical width in millimeters", + "Display physical height in millimeters", + "Display physical diagonal length in inches", + "Display physical pixels per inch (PPI)" + }); +} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h index 8511442040..53eccd5b46 100644 --- a/src/modules/monitor/monitor.h +++ b/src/modules/monitor/monitor.h @@ -10,3 +10,4 @@ bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, co void ffDestroyMonitorOptions(FFMonitorOptions* options); void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module); void ffGenerateMonitorJson(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintMonitorHelpFormat(void); diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 3efef948fa..3f6410257d 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -101,7 +101,7 @@ void ffPrintNetIO(FFNetIOOptions* options) void ffInitNetIOOptions(FFNetIOOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETIO_MODULE_NAME, ffParseNetIOCommandOptions, ffParseNetIOJsonObject, ffPrintNetIO, ffGenerateNetIOJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETIO_MODULE_NAME, ffParseNetIOCommandOptions, ffParseNetIOJsonObject, ffPrintNetIO, ffGenerateNetIOJson, ffPrintNetIOHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->namePrefix); @@ -197,3 +197,21 @@ void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mu ffStrbufDestroy(&inf->name); } } + +void ffPrintNetIOHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_NETIO_MODULE_NAME, "{1} (IN) - {2} (OUT)", FF_NETIO_NUM_FORMAT_ARGS, (const char* []) { + "Size of data received per second (formatted)", + "Size of data sent per second (formatted)", + "Interface name", + "Is default route", + "Size of data received per second (in bytes)", + "Size of data sent per second (in bytes)", + "Number of packets received per second", + "Number of packets sent per second", + "Number of errors received per second", + "Number of errors sent per second", + "Number of packets dropped when receiving per second", + "Number of packets dropped when sending per second", + }); +} diff --git a/src/modules/netio/netio.h b/src/modules/netio/netio.h index 3562d0ccd7..b8a19169c9 100644 --- a/src/modules/netio/netio.h +++ b/src/modules/netio/netio.h @@ -12,3 +12,4 @@ bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const void ffDestroyNetIOOptions(FFNetIOOptions* options); void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module); void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintNetIOHelpFormat(void); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index afe3efa244..600dc8c7d1 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -41,7 +41,7 @@ void ffPrintOpenCL(FFOpenCLOptions* options) void ffInitOpenCLOptions(FFOpenCLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, ffGenerateOpenCLJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, ffGenerateOpenCLJson, ffPrintOpenCLHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -102,3 +102,12 @@ void ffGenerateOpenCLJson(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson_mut_d ffStrbufDestroy(&opencl.device); ffStrbufDestroy(&opencl.vendor); } + +void ffPrintOpenCLHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_OPENCL_MODULE_NAME, "{1}", FF_OPENCL_NUM_FORMAT_ARGS, (const char* []) { + "version", + "device", + "vendor" + }); +} diff --git a/src/modules/opencl/opencl.h b/src/modules/opencl/opencl.h index 592f453bf1..35c4809463 100644 --- a/src/modules/opencl/opencl.h +++ b/src/modules/opencl/opencl.h @@ -10,3 +10,4 @@ bool ffParseOpenCLCommandOptions(FFOpenCLOptions* options, const char* key, cons void ffDestroyOpenCLOptions(FFOpenCLOptions* options); void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module); void ffGenerateOpenCLJson(FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintOpenCLHelpFormat(void); diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 78bbf18428..6a98eb8b79 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -44,7 +44,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options) void ffInitOpenGLOptions(FFOpenGLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, ffGenerateOpenGLJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, ffGenerateOpenGLJson, ffPrintOpenGLHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); #if defined(__linux__) || defined(__FreeBSD__) @@ -143,3 +143,13 @@ void ffGenerateOpenGLJson(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson_mut_d ffStrbufDestroy(&result.vendor); ffStrbufDestroy(&result.slv); } + +void ffPrintOpenGLHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_OPENGL_MODULE_NAME, "{1}", FF_OPENGL_NUM_FORMAT_ARGS, (const char* []) { + "version", + "renderer", + "vendor", + "shading language version" + }); +} diff --git a/src/modules/opengl/opengl.h b/src/modules/opengl/opengl.h index 6c35ede54e..d4f84a8954 100644 --- a/src/modules/opengl/opengl.h +++ b/src/modules/opengl/opengl.h @@ -10,3 +10,4 @@ bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, cons void ffDestroyOpenGLOptions(FFOpenGLOptions* options); void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module); void ffGenerateOpenGLJson(FFOpenGLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintOpenGLHelpFormat(void); diff --git a/src/modules/options.h b/src/modules/options.h index 1be2e88e0c..191767c770 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -18,6 +18,7 @@ #include "modules/datetime/option.h" #include "modules/de/option.h" #include "modules/disk/option.h" +#include "modules/diskio/option.h" #include "modules/display/option.h" #include "modules/font/option.h" #include "modules/host/option.h" diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 120f769fc1..299e871b32 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -138,7 +138,7 @@ void ffPrintOS(FFOSOptions* options) void ffInitOSOptions(FFOSOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, ffGenerateOSJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, ffGenerateOSJson, ffPrintOSHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -196,3 +196,21 @@ void ffGenerateOSJson(FF_MAYBE_UNUSED FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "version", &os->version); yyjson_mut_obj_add_strbuf(doc, obj, "versionID", &os->versionID); } + +void ffPrintOSHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_OS_MODULE_NAME, "{3} {10} {12}", FF_OS_NUM_FORMAT_ARGS, (const char* []) { + "Name of the kernel (Linux, WIN32_NT, Darwin, FreeBSD)", + "Name of the OS", + "Pretty name of the OS", + "ID of the OS", + "ID like of the OS", + "Variant of the OS", + "Variant ID of the OS", + "Version of the OS", + "Version ID of the OS", + "Version codename of the OS", + "Build ID of the OS", + "Architecture of the OS" + }); +} diff --git a/src/modules/os/os.h b/src/modules/os/os.h index b7ed39d0d4..8b16baf4e1 100644 --- a/src/modules/os/os.h +++ b/src/modules/os/os.h @@ -10,3 +10,4 @@ bool ffParseOSCommandOptions(FFOSOptions* options, const char* key, const char* void ffDestroyOSOptions(FFOSOptions* options); void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module); void ffGenerateOSJson(FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintOSHelpFormat(void); diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 1d6ba534ab..2534849262 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 24 +#define FF_PACKAGES_NUM_FORMAT_ARGS 25 void ffPrintPackages(FFPackagesOptions* options) { @@ -64,6 +64,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE(pkgtool) FF_PRINT_PACKAGE(paludis) FF_PRINT_PACKAGE(winget) + FF_PRINT_PACKAGE(opkg) putchar('\n'); } @@ -94,6 +95,7 @@ void ffPrintPackages(FFPackagesOptions* options) {FF_FORMAT_ARG_TYPE_UINT, &counts.pkgtool}, {FF_FORMAT_ARG_TYPE_UINT, &counts.paludis}, {FF_FORMAT_ARG_TYPE_UINT, &counts.winget}, + {FF_FORMAT_ARG_TYPE_UINT, &counts.opkg}, }); } @@ -102,7 +104,7 @@ void ffPrintPackages(FFPackagesOptions* options) void ffInitPackagesOptions(FFPackagesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, ffGeneratePackagesJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, ffGeneratePackagesJson, ffPrintPackagesHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -178,5 +180,37 @@ void ffGeneratePackagesJson(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_m FF_APPEND_PACKAGE_COUNT(snap) FF_APPEND_PACKAGE_COUNT(winget) FF_APPEND_PACKAGE_COUNT(xbps) + FF_APPEND_PACKAGE_COUNT(opkg) yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } + +void ffPrintPackagesHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg)", FF_PACKAGES_NUM_FORMAT_ARGS, (const char* []) { + "Number of all packages", + "Number of pacman packages", + "Pacman branch on manjaro", + "Number of dpkg packages", + "Number of rpm packages", + "Number of emerge packages", + "Number of eopkg packages", + "Number of xbps packages", + "Number of nix-system packages", + "Number of nix-user packages", + "Number of nix-default packages", + "Number of apk packages", + "Number of pkg packages", + "Number of flatpak-system packages", + "Number of flatpak-user packages", + "Number of snap packages", + "Number of brew packages", + "Number of brew-cask packages", + "Number of macports packages", + "Number of scoop packages", + "Number of choco packages", + "Number of pkgtool packages", + "Number of paludis packages", + "Number of winget packages", + "Number of opkg packages" + }); +} diff --git a/src/modules/packages/packages.h b/src/modules/packages/packages.h index 97b4ce239f..39114a098d 100644 --- a/src/modules/packages/packages.h +++ b/src/modules/packages/packages.h @@ -10,3 +10,4 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, void ffDestroyPackagesOptions(FFPackagesOptions* options); void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module); void ffGeneratePackagesJson(FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPackagesHelpFormat(void); diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 5ca58ba279..caba0d8475 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -75,7 +75,7 @@ void ffPrintPlayer(FFPlayerOptions* options) void ffInitPlayerOptions(FFPlayerOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, ffGeneratePlayerJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, ffGeneratePlayerJson, ffPrintPlayerHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,13 @@ void ffGeneratePlayerJson(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_do yyjson_mut_obj_add_strbuf(doc, obj, "playerId", &media->playerId); yyjson_mut_obj_add_strbuf(doc, obj, "url", &media->url); } + +void ffPrintPlayerHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PLAYER_MODULE_NAME, "{1}", FF_PLAYER_NUM_FORMAT_ARGS, (const char* []) { + "Pretty player name", + "Player name", + "Player Identifier", + "URL name" + }); +} diff --git a/src/modules/player/player.h b/src/modules/player/player.h index 829b7857a4..11a4fed8e2 100644 --- a/src/modules/player/player.h +++ b/src/modules/player/player.h @@ -11,3 +11,4 @@ bool ffParsePlayerCommandOptions(FFPlayerOptions* options, const char* key, cons void ffDestroyPlayerOptions(FFPlayerOptions* options); void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module); void ffGeneratePlayerJson(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPlayerHelpFormat(void); diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index a5ce64002c..fef71928a1 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -5,7 +5,7 @@ #include "util/stringUtils.h" #define FF_POWERADAPTER_DISPLAY_NAME "Power Adapter" -#define FF_POWERADAPTER_MODULE_ARGS 5 +#define FF_POWERADAPTER_NUM_FORMAT_ARGS 5 void ffPrintPowerAdapter(FFPowerAdapterOptions* options) { @@ -42,7 +42,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) } else { - ffPrintFormat(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_POWERADAPTER_MODULE_ARGS, (FFformatarg[]){ + ffPrintFormat(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_POWERADAPTER_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_INT, &result->watts}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer}, @@ -62,7 +62,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, ffGeneratePowerAdapterJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, ffGeneratePowerAdapterJson, ffPrintPowerAdapterHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,14 @@ void ffGeneratePowerAdapterJson(FF_MAYBE_UNUSED FFPowerAdapterOptions* options, } } } + +void ffPrintPowerAdapterHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_POWERADAPTER_MODULE_NAME, "{1}W", FF_POWERADAPTER_NUM_FORMAT_ARGS, (const char* []) { + "PowerAdapter watts", + "PowerAdapter name", + "PowerAdapter manufacturer", + "PowerAdapter model", + "PowerAdapter description" + }); +} diff --git a/src/modules/poweradapter/poweradapter.h b/src/modules/poweradapter/poweradapter.h index a99d6acabb..792409ff27 100644 --- a/src/modules/poweradapter/poweradapter.h +++ b/src/modules/poweradapter/poweradapter.h @@ -10,3 +10,4 @@ bool ffParsePowerAdapterCommandOptions(FFPowerAdapterOptions* options, const cha void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options); void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* module); void ffGeneratePowerAdapterJson(FFPowerAdapterOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPowerAdapterHelpFormat(void); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 02a8bb53f1..ce04971722 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -33,7 +33,7 @@ void ffPrintProcesses(FFProcessesOptions* options) void ffInitProcessesOptions(FFProcessesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, ffGenerateProcessesJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, ffGenerateProcessesJson, ffPrintProcessesHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -82,3 +82,10 @@ void ffGenerateProcessesJson(FF_MAYBE_UNUSED FFProcessesOptions* options, yyjson yyjson_mut_obj_add_uint(doc, module, "result", result); } + +void ffPrintProcessesHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PROCESSES_MODULE_NAME, "{1}", FF_PROCESSES_NUM_FORMAT_ARGS, (const char* []) { + "Count" + }); +} diff --git a/src/modules/processes/processes.h b/src/modules/processes/processes.h index 8f14e00e44..b2d9ac6be2 100644 --- a/src/modules/processes/processes.h +++ b/src/modules/processes/processes.h @@ -10,3 +10,4 @@ bool ffParseProcessesCommandOptions(FFProcessesOptions* options, const char* key void ffDestroyProcessesOptions(FFProcessesOptions* options); void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module); void ffGenerateProcessesJson(FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintProcessesHelpFormat(void); diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index e7c277e21e..a6ae2c9eb5 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -42,7 +42,7 @@ void ffPrintPublicIp(FFPublicIpOptions* options) void ffInitPublicIpOptions(FFPublicIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, ffGeneratePublicIpJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, ffGeneratePublicIpJson, ffPrintPublicIpHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->url); @@ -127,3 +127,11 @@ void ffGeneratePublicIpJson(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyj ffStrbufDestroy(&result.ip); ffStrbufDestroy(&result.location); } + +void ffPrintPublicIpHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PUBLICIP_MODULE_NAME, "{1} ({2})", FF_PUBLICIP_NUM_FORMAT_ARGS, (const char* []) { + "Public IP address", + "Location" + }); +} diff --git a/src/modules/publicip/publicip.h b/src/modules/publicip/publicip.h index 870591eb74..69f8752e45 100644 --- a/src/modules/publicip/publicip.h +++ b/src/modules/publicip/publicip.h @@ -12,3 +12,4 @@ bool ffParsePublicIpCommandOptions(FFPublicIpOptions* options, const char* key, void ffDestroyPublicIpOptions(FFPublicIpOptions* options); void ffParsePublicIpJsonObject(FFPublicIpOptions* options, yyjson_val* module); void ffGeneratePublicIpJson(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPublicIpHelpFormat(void); diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 555bb2a04c..75cd4eea7e 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -77,7 +77,7 @@ void ffPrintSeparator(FFSeparatorOptions* options) void ffInitSeparatorOptions(FFSeparatorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorCommandOptions, ffParseSeparatorJsonObject, ffPrintSeparator, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorCommandOptions, ffParseSeparatorJsonObject, ffPrintSeparator, NULL, NULL); ffStrbufInit(&options->string); } diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index f7668c5882..64c074b631 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -44,7 +44,7 @@ void ffPrintShell(FFShellOptions* options) void ffInitShellOptions(FFShellOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, ffGenerateShellJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, ffGenerateShellJson, ffPrintShellHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -97,3 +97,15 @@ void ffGenerateShellJson(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->shellVersion); } + +void ffPrintShellHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_SHELL_MODULE_NAME, "{3} {4}", FF_SHELL_NUM_FORMAT_ARGS, (const char* []) { + "Shell process name", + "Shell path with exe name", + "Shell exe name", + "Shell version", + "Shell pid", + "Shell pretty name" + }); +} diff --git a/src/modules/shell/shell.h b/src/modules/shell/shell.h index 354b512290..961a94cb7e 100644 --- a/src/modules/shell/shell.h +++ b/src/modules/shell/shell.h @@ -10,3 +10,4 @@ bool ffParseShellCommandOptions(FFShellOptions* options, const char* key, const void ffDestroyShellOptions(FFShellOptions* options); void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module); void ffGenerateShellJson(FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintShellHelpFormat(void); diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 3796a7365a..cd0ea1ff13 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -85,7 +85,7 @@ void ffPrintSound(FFSoundOptions* options) void ffInitSoundOptions(FFSoundOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, ffGenerateSoundJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, ffGenerateSoundJson, ffPrintSoundHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->soundType = FF_SOUND_TYPE_MAIN; @@ -173,7 +173,12 @@ void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_bool(doc, obj, "active", item->active); yyjson_mut_obj_add_bool(doc, obj, "main", item->main); - yyjson_mut_obj_add_uint(doc, obj, "volume", item->volume); + + if (item->volume != FF_SOUND_VOLUME_UNKNOWN) + yyjson_mut_obj_add_uint(doc, obj, "volume", item->volume); + else + yyjson_mut_obj_add_null(doc, obj, "volume"); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier); } @@ -184,3 +189,13 @@ void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc ffStrbufDestroy(&device->name); } } + +void ffPrintSoundHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_SOUND_MODULE_NAME, "{2} ({3}%)", FF_SOUND_NUM_FORMAT_ARGS, (const char* []) { + "Is main sound device", + "Device name", + "Volume", + "Identifier" + }); +} diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h index 03ec8fe680..b7ab196a1c 100644 --- a/src/modules/sound/sound.h +++ b/src/modules/sound/sound.h @@ -10,3 +10,4 @@ bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const void ffDestroySoundOptions(FFSoundOptions* options); void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module); void ffGenerateSoundJson(FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintSoundHelpFormat(void); diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 331cbf26dd..0e207434a2 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -75,7 +75,7 @@ void ffPrintSwap(FFSwapOptions* options) void ffInitSwapOptions(FFSwapOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, ffGenerateSwapJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, ffGenerateSwapJson, ffPrintSwapHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,12 @@ void ffGenerateSwapJson(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut_doc* yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal); yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); } + +void ffPrintSwapHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_SWAP_MODULE_NAME, "{1} / {2} ({3})", FF_SWAP_NUM_FORMAT_ARGS, (const char* []) { + "Used size", + "Total size", + "Percentage used" + }); +} diff --git a/src/modules/swap/swap.h b/src/modules/swap/swap.h index fbb125a449..1a6fbc64f3 100644 --- a/src/modules/swap/swap.h +++ b/src/modules/swap/swap.h @@ -10,3 +10,4 @@ bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const ch void ffDestroySwapOptions(FFSwapOptions* options); void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module); void ffGenerateSwapJson(FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintSwapHelpFormat(void); diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index ac68652f04..6745524fa7 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -42,7 +42,7 @@ void ffPrintTerminal(FFTerminalOptions* options) void ffInitTerminalOptions(FFTerminalOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, ffGenerateTerminalJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, ffGenerateTerminalJson, ffPrintTerminalHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -96,3 +96,15 @@ void ffGenerateTerminalJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_m yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->terminalPrettyName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->terminalVersion); } + +void ffPrintTerminalHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TERMINAL_MODULE_NAME, "{5} {6}", FF_TERMINAL_NUM_FORMAT_ARGS, (const char* []) { + "Terminal process name", + "Terminal path with exe name", + "Terminal exe name", + "Terminal pid", + "Terminal pretty name", + "Terminal version" + }); +} diff --git a/src/modules/terminal/terminal.h b/src/modules/terminal/terminal.h index 709b02e568..c10e3fba08 100644 --- a/src/modules/terminal/terminal.h +++ b/src/modules/terminal/terminal.h @@ -10,3 +10,4 @@ bool ffParseTerminalCommandOptions(FFTerminalOptions* options, const char* key, void ffDestroyTerminalOptions(FFTerminalOptions* options); void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module); void ffGenerateTerminalJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTerminalHelpFormat(void); diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index ca28576c92..2353ff869b 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -49,7 +49,7 @@ void ffPrintTerminalFont(FFTerminalFontOptions* options) void ffInitTerminalFontOptions(FFTerminalFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, ffGenerateTerminalFontJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, ffGenerateTerminalFontJson, ffPrintTerminalFontHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -124,3 +124,13 @@ void ffGenerateTerminalFontJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjs ffFontDestroy(&result.font); ffFontDestroy(&result.fallback); } + +void ffPrintTerminalFontHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TERMINALFONT_MODULE_NAME, "{1}", FF_TERMINALFONT_NUM_FORMAT_ARGS, (const char* []) { + "Terminal font combined", + "Terminal font name", + "Terminal font size", + "Terminal font styles" + }); +} diff --git a/src/modules/terminalfont/terminalfont.h b/src/modules/terminalfont/terminalfont.h index 434eb1a1f7..a117c82898 100644 --- a/src/modules/terminalfont/terminalfont.h +++ b/src/modules/terminalfont/terminalfont.h @@ -10,3 +10,4 @@ bool ffParseTerminalFontCommandOptions(FFTerminalFontOptions* options, const cha void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options); void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* module); void ffGenerateTerminalFontJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTerminalFontHelpFormat(void); diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 22ef849efe..8d4f454bdd 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -41,7 +41,7 @@ void ffPrintTerminalSize(FFTerminalSizeOptions* options) void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, ffGenerateTerminalSizeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, ffGenerateTerminalSizeJson, ffPrintTerminalSizeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -93,3 +93,13 @@ void ffGenerateTerminalSizeJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjs yyjson_mut_obj_add_uint(doc, obj, "width", result.width); yyjson_mut_obj_add_uint(doc, obj, "height", result.height); } + +void ffPrintTerminalSizeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TERMINALSIZE_MODULE_NAME, "{1} columns x {2} rows ({3}px x {4}px)", FF_TERMINALSIZE_NUM_FORMAT_ARGS, (const char* []) { + "Terminal rows", + "Terminal columns", + "Terminal width (in pixels)", + "Terminal height (in pixels)" + }); +} diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h index 33699057d5..312ccaf5a8 100644 --- a/src/modules/terminalsize/terminalsize.h +++ b/src/modules/terminalsize/terminalsize.h @@ -10,3 +10,4 @@ bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const cha void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* module); void ffGenerateTerminalSizeJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTerminalSizeHelpFormat(void); diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 2fc89549bd..8c0e60af51 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -32,7 +32,7 @@ void ffPrintTheme(FFThemeOptions* options) void ffInitThemeOptions(FFThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, ffGenerateThemeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, ffGenerateThemeJson, ffPrintThemeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,10 @@ void ffGenerateThemeJson(FF_MAYBE_UNUSED FFThemeOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, module, "result", &theme); } + +void ffPrintThemeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_THEME_MODULE_NAME, "{1}", FF_THEME_NUM_FORMAT_ARGS, (const char* []) { + "Combined themes" + }); +} diff --git a/src/modules/theme/theme.h b/src/modules/theme/theme.h index c0cee8584b..cf658de211 100644 --- a/src/modules/theme/theme.h +++ b/src/modules/theme/theme.h @@ -10,3 +10,4 @@ bool ffParseThemeCommandOptions(FFThemeOptions* options, const char* key, const void ffDestroyThemeOptions(FFThemeOptions* options); void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module); void ffGenerateThemeJson(FFThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintThemeHelpFormat(void); diff --git a/src/modules/title/title.c b/src/modules/title/title.c index a0174322a5..2116a9e4be 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -71,7 +71,7 @@ void ffPrintTitle(FFTitleOptions* options) void ffInitTitleOptions(FFTitleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, ffGenerateTitleJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, ffGenerateTitleJson, ffPrintTitleHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); @@ -172,3 +172,17 @@ void ffGenerateTitleJson(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath); yyjson_mut_obj_add_strbuf(doc, obj, "userShell", &instance.state.platform.userShell); } + +void ffPrintTitleHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TITLE_MODULE_NAME, "{6}{7}{8}", FF_TITLE_NUM_FORMAT_ARGS, (const char* []) { + "User name", + "Host name", + "Home directory", + "Executable path of current process", + "User's default shell", + "User name (colored)", + "@ symbol (colored)", + "Host name (colored)" + }); +} diff --git a/src/modules/title/title.h b/src/modules/title/title.h index 76bec364d9..bad3a99c86 100644 --- a/src/modules/title/title.h +++ b/src/modules/title/title.h @@ -10,3 +10,4 @@ bool ffParseTitleCommandOptions(FFTitleOptions* options, const char* key, const void ffDestroyTitleOptions(FFTitleOptions* options); void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module); void ffGenerateTitleJson(FFTitleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTitleHelpFormat(void); diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 96be154563..d0ed2630dd 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -91,7 +91,7 @@ void ffPrintUptime(FFUptimeOptions* options) void ffInitUptimeOptions(FFUptimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, ffGenerateUptimeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, ffGenerateUptimeJson, ffPrintUptimeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -142,3 +142,13 @@ void ffGenerateUptimeJson(FF_MAYBE_UNUSED FFUptimeOptions* options, yyjson_mut_d yyjson_mut_obj_add_uint(doc, obj, "uptime", result.uptime); yyjson_mut_obj_add_uint(doc, obj, "bootTime", result.bootTime); } + +void ffPrintUptimeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_UPTIME_MODULE_NAME, "{1} days {2} hours {3} mins", FF_UPTIME_NUM_FORMAT_ARGS, (const char* []) { + "Days", + "Hours", + "Minutes", + "Seconds" + }); +} diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h index 2fa12e9638..4cd9537825 100644 --- a/src/modules/uptime/uptime.h +++ b/src/modules/uptime/uptime.h @@ -10,3 +10,4 @@ bool ffParseUptimeCommandOptions(FFUptimeOptions* options, const char* key, cons void ffDestroyUptimeOptions(FFUptimeOptions* options); void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module); void ffGenerateUptimeJson(FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintUptimeHelpFormat(void); diff --git a/src/modules/users/users.c b/src/modules/users/users.c index ab58440c2e..3565fbe8a3 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -75,7 +75,7 @@ void ffPrintUsers(FFUsersOptions* options) ffPrintFormat(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &user->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &user->hostName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &user->tty}, + {FF_FORMAT_ARG_TYPE_STRBUF, &user->sessionName}, {FF_FORMAT_ARG_TYPE_STRBUF, &user->clientIp}, {FF_FORMAT_ARG_TYPE_UINT64, &user->loginTime}, }); @@ -86,14 +86,14 @@ void ffPrintUsers(FFUsersOptions* options) { ffStrbufDestroy(&user->clientIp); ffStrbufDestroy(&user->hostName); - ffStrbufDestroy(&user->tty); + ffStrbufDestroy(&user->sessionName); ffStrbufDestroy(&user->name); } } void ffInitUsersOptions(FFUsersOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, ffGenerateUsersJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, ffGenerateUsersJson, ffPrintUsersHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->compact = false; @@ -159,11 +159,11 @@ void ffGenerateUsersJson(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc FF_LIST_FOR_EACH(FFUserResult, user, results) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_strbuf(doc, obj, "clientIp", &user->clientIp); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &user->name); yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &user->hostName); + yyjson_mut_obj_add_strbuf(doc, obj, "sessionName", &user->sessionName); + yyjson_mut_obj_add_strbuf(doc, obj, "clientIp", &user->clientIp); yyjson_mut_obj_add_uint(doc, obj, "loginTime", user->loginTime); - yyjson_mut_obj_add_strbuf(doc, obj, "name", &user->name); - yyjson_mut_obj_add_strbuf(doc, obj, "tty", &user->tty); } exit: @@ -171,7 +171,18 @@ void ffGenerateUsersJson(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc { ffStrbufDestroy(&user->clientIp); ffStrbufDestroy(&user->hostName); - ffStrbufDestroy(&user->tty); + ffStrbufDestroy(&user->sessionName); ffStrbufDestroy(&user->name); } } + +void ffPrintUsersHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_USERS_MODULE_NAME, "{1}@{2} - login time {5}", FF_USERS_NUM_FORMAT_ARGS, (const char* []) { + "User name", + "Host name", + "Session name", + "Client IP", + "Login Time" + }); +} diff --git a/src/modules/users/users.h b/src/modules/users/users.h index 3ef57a1cf7..71a4449ec2 100644 --- a/src/modules/users/users.h +++ b/src/modules/users/users.h @@ -10,3 +10,4 @@ bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const void ffDestroyUsersOptions(FFUsersOptions* options); void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module); void ffGenerateUsersJson(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintUsersHelpFormat(void); diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 54781eb622..69911fb107 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -1,10 +1,11 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "detection/libc/libc.h" #include "detection/version/version.h" #include "modules/version/version.h" #include "util/stringUtils.h" -#define FF_VERSION_NUM_FORMAT_ARGS 8 +#define FF_VERSION_NUM_FORMAT_ARGS 9 void ffPrintVersion(FFVersionOptions* options) { @@ -18,6 +19,18 @@ void ffPrintVersion(FFVersionOptions* options) } else { + FFLibcResult libcResult; + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + if (!ffDetectLibc(&libcResult)) + { + ffStrbufSetS(&buf, libcResult.name); + if (libcResult.version) + { + ffStrbufAppendC(&buf, ' '); + ffStrbufAppendS(&buf, libcResult.version); + } + } + ffPrintFormat(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_VERSION_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRING, result.projectName}, {FF_FORMAT_ARG_TYPE_STRING, result.version}, @@ -27,13 +40,14 @@ void ffPrintVersion(FFVersionOptions* options) {FF_FORMAT_ARG_TYPE_STRING, result.cmakeBuiltType}, {FF_FORMAT_ARG_TYPE_STRING, result.compileTime}, {FF_FORMAT_ARG_TYPE_STRING, result.compiler}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buf}, }); } } void ffInitVersionOptions(FFVersionOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, ffGenerateVersionJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, ffGenerateVersionJson, ffPrintVersionHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -83,4 +97,35 @@ void ffGenerateVersionJson(FF_MAYBE_UNUSED FFVersionOptions* options, yyjson_mut yyjson_mut_obj_add_str(doc, obj, "compileTime", result.compileTime); yyjson_mut_obj_add_str(doc, obj, "compiler", result.compiler); yyjson_mut_obj_add_bool(doc, obj, "debugMode", result.debugMode); + + FFLibcResult libcResult; + if (ffDetectLibc(&libcResult)) + { + yyjson_mut_obj_add_null(doc, obj, "libc"); + } + else + { + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreateS(libcResult.name); + if (libcResult.version) + { + ffStrbufAppendC(&buf, ' '); + ffStrbufAppendS(&buf, libcResult.version); + } + yyjson_mut_obj_add_strbuf(doc, obj, "libc", &buf); + } +} + +void ffPrintVersionHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_VERSION_MODULE_NAME, "{1} {2}{3} ({5})", FF_VERSION_NUM_FORMAT_ARGS, (const char* []) { + "Project name", + "Version", + "Version tweak", + "Build type (debug or release)", + "Architecture", + "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)", + "Date time when compiling", + "Compiler used", + "Libc used" + }); } diff --git a/src/modules/version/version.h b/src/modules/version/version.h index bb1e4c15f7..3daaccd1c6 100644 --- a/src/modules/version/version.h +++ b/src/modules/version/version.h @@ -10,3 +10,4 @@ bool ffParseVersionCommandOptions(FFVersionOptions* options, const char* key, co void ffDestroyVersionOptions(FFVersionOptions* options); void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module); void ffGenerateVersionJson(FFVersionOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintVersionHelpFormat(void); diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 14c37153ac..81760efa2c 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -46,7 +46,7 @@ void ffPrintVulkan(FFVulkanOptions* options) void ffInitVulkanOptions(FFVulkanOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, ffGenerateVulkanJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, ffGenerateVulkanJson, ffPrintVulkanHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -136,3 +136,12 @@ void ffGenerateVulkanJson(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson_mut_d yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->vulkanDeviceId); } } + +void ffPrintVulkanHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_VULKAN_MODULE_NAME, "{2} - {1}", FF_VULKAN_NUM_FORMAT_ARGS, (const char* []) { + "Driver name", + "API version", + "Conformance version" + }); +} diff --git a/src/modules/vulkan/vulkan.h b/src/modules/vulkan/vulkan.h index a0b378394e..fad7884bf3 100644 --- a/src/modules/vulkan/vulkan.h +++ b/src/modules/vulkan/vulkan.h @@ -10,3 +10,4 @@ bool ffParseVulkanCommandOptions(FFVulkanOptions* options, const char* key, cons void ffDestroyVulkanOptions(FFVulkanOptions* options); void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module); void ffGenerateVulkanJson(FFVulkanOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintVulkanHelpFormat(void); diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index 947a1031e5..17213dfc56 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -44,7 +44,7 @@ void ffPrintWallpaper(FFWallpaperOptions* options) void ffInitWallpaperOptions(FFWallpaperOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, ffGenerateWallpaperJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, ffGenerateWallpaperJson, ffPrintWallpaperHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -91,3 +91,10 @@ void ffGenerateWallpaperJson(FF_MAYBE_UNUSED FFWallpaperOptions* options, yyjson } yyjson_mut_obj_add_strbuf(doc, module, "result", &fullpath); } + +void ffPrintWallpaperHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WALLPAPER_MODULE_NAME, "{1}", FF_WALLPAPER_NUM_FORMAT_ARGS, (const char* []) { + "Wallpaper image file" + }); +} diff --git a/src/modules/wallpaper/wallpaper.h b/src/modules/wallpaper/wallpaper.h index 3925784b27..a811cf515e 100644 --- a/src/modules/wallpaper/wallpaper.h +++ b/src/modules/wallpaper/wallpaper.h @@ -10,3 +10,4 @@ bool ffParseWallpaperCommandOptions(FFWallpaperOptions* options, const char* key void ffDestroyWallpaperOptions(FFWallpaperOptions* options); void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module); void ffGenerateWallpaperJson(FFWallpaperOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWallpaperHelpFormat(void); diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index ec25374b5d..2fdb578d33 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -33,7 +33,7 @@ void ffPrintWeather(FFWeatherOptions* options) void ffInitWeatherOptions(FFWeatherOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, ffGenerateWeatherJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, ffGenerateWeatherJson, ffPrintWeatherHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->location); @@ -124,3 +124,10 @@ void ffGenerateWeatherJson(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjso yyjson_mut_obj_add_strbuf(doc, module, "result", &result); } + +void ffPrintWeatherHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WEATHER_MODULE_NAME, "{1}", FF_WEATHER_NUM_FORMAT_ARGS, (const char* []) { + "Weather result" + }); +} diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h index a769402448..6fdff6f974 100644 --- a/src/modules/weather/weather.h +++ b/src/modules/weather/weather.h @@ -12,3 +12,4 @@ bool ffParseWeatherCommandOptions(FFWeatherOptions* options, const char* key, co void ffDestroyWeatherOptions(FFWeatherOptions* options); void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module); void ffGenerateWeatherJson(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWeatherHelpFormat(void); diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 449b82e67a..2268e830e0 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -72,7 +72,7 @@ void ffPrintWifi(FFWifiOptions* options) void ffInitWifiOptions(FFWifiOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, ffGenerateWifiJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, ffGenerateWifiJson, ffPrintWifiHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -153,3 +153,19 @@ void ffGenerateWifiJson(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut_doc* ffStrbufDestroy(&item->conn.security); } } + +void ffPrintWifiHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WIFI_MODULE_NAME, "{4} - {10}", FF_WIFI_NUM_FORMAT_ARGS, (const char* []) { + "Interface description", + "Interface status", + "Connection status", + "Connection SSID", + "Connection mac address", + "Connection protocol", + "Connection signal quality (percentage)", + "Connection RX rate", + "Connection TX rate", + "Connection Security algorithm" + }); +} diff --git a/src/modules/wifi/wifi.h b/src/modules/wifi/wifi.h index 2957f876d8..96ad129503 100644 --- a/src/modules/wifi/wifi.h +++ b/src/modules/wifi/wifi.h @@ -10,3 +10,4 @@ bool ffParseWifiCommandOptions(FFWifiOptions* options, const char* key, const ch void ffDestroyWifiOptions(FFWifiOptions* options); void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module); void ffGenerateWifiJson(FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWifiHelpFormat(void); diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 371b48deb8..dcfbf94ec3 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -43,7 +43,7 @@ void ffPrintWM(FFWMOptions* options) void ffInitWMOptions(FFWMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, ffGenerateWMJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, ffGenerateWMJson, ffPrintWMHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -93,3 +93,12 @@ void ffGenerateWMJson(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->wmPrettyName); yyjson_mut_obj_add_strbuf(doc, obj, "protocolName", &result->wmProtocolName); } + +void ffPrintWMHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WM_MODULE_NAME, "{2} ({3})", FF_WM_NUM_FORMAT_ARGS, (const char* []) { + "WM process name", + "WM pretty name", + "WM protocol name" + }); +} diff --git a/src/modules/wm/wm.h b/src/modules/wm/wm.h index fe960b6885..52f9275150 100644 --- a/src/modules/wm/wm.h +++ b/src/modules/wm/wm.h @@ -10,3 +10,4 @@ bool ffParseWMCommandOptions(FFWMOptions* options, const char* key, const char* void ffDestroyWMOptions(FFWMOptions* options); void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module); void ffGenerateWMJson(FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWMHelpFormat(void); diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 3560769223..d506d634c8 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -32,7 +32,7 @@ void ffPrintWMTheme(FFWMThemeOptions* options) void ffInitWMThemeOptions(FFWMThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, ffGenerateWMThemeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, ffGenerateWMThemeJson, ffPrintWMthemeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -79,3 +79,10 @@ void ffGenerateWMThemeJson(FF_MAYBE_UNUSED FFWMThemeOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, module, "result", &themeOrError); } + +void ffPrintWMthemeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WMTHEME_MODULE_NAME, "{1}", FF_WMTHEME_NUM_FORMAT_ARGS, (const char* []) { + "WM theme" + }); +} diff --git a/src/modules/wmtheme/wmtheme.h b/src/modules/wmtheme/wmtheme.h index e90f9e2530..0e9dd5b130 100644 --- a/src/modules/wmtheme/wmtheme.h +++ b/src/modules/wmtheme/wmtheme.h @@ -10,3 +10,4 @@ bool ffParseWMThemeCommandOptions(FFWMThemeOptions* options, const char* key, co void ffDestroyWMThemeOptions(FFWMThemeOptions* options); void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module); void ffGenerateWMThemeJson(FFWMThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWMthemeHelpFormat(void); diff --git a/src/util/FFlist.h b/src/util/FFlist.h index 4961adda3f..276a65e130 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -90,6 +90,11 @@ static inline void ffListDestroy(FFlist* list) list->data = NULL; } +static inline void ffListClear(FFlist* list) +{ + list->length = 0; +} + #define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \ assert(sizeof(itemType) == (listVar).elementSize); \ for(itemType* itemVarName = (itemType*)(listVar).data; \ diff --git a/src/util/apple/Info.plist.in b/src/util/apple/Info.plist.in new file mode 100644 index 0000000000..4fd959cfdb --- /dev/null +++ b/src/util/apple/Info.plist.in @@ -0,0 +1,14 @@ + + + + + CFBundleIdentifier + fastfetch + CFBundleName + @PROJECT_NAME@ + CFBundleShortVersionString + @PROJECT_VERSION@ + CFBundleDevelopmentRegion + English + + diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 2ce563d5ed..96b7651141 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -83,6 +83,29 @@ const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) return "TypeID is neither 'CFNumber' nor 'CFData'"; } +const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result) +{ + CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); + if(cf == NULL) + return "CFDictionaryGetValue() failed"; + + if(CFGetTypeID(cf) == CFNumberGetTypeID()) + { + if(!CFNumberGetValue((CFNumberRef)cf, kCFNumberSInt64Type, result)) + return "Number type is not SInt64"; + return NULL; + } + else if(CFGetTypeID(cf) == CFDataGetTypeID()) + { + if(CFDataGetLength((CFDataRef)cf) != sizeof(int64_t)) + return "Data length is not sizeof(int64_t)"; + CFDataGetBytes((CFDataRef)cf, CFRangeMake(0, sizeof(int64_t)), (uint8_t*)result); + return NULL; + } + + return "TypeID is neither 'CFNumber' nor 'CFData'"; +} + const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length) { CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index a8d9804a3f..2137766bb2 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -11,6 +11,7 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result); const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result); const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result); const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result); +const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result); const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length); const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result); diff --git a/src/util/apple/ddcci.h b/src/util/apple/ddcci.h deleted file mode 100644 index a0de174828..0000000000 --- a/src/util/apple/ddcci.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#ifndef FASTFETCH_INCLUDED_util_apple_ddcci_h - -#include - -// DDC/CI -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)); - -#endif diff --git a/src/util/stringUtils.h b/src/util/stringUtils.h index 80894ad26f..d3ff894c6d 100644 --- a/src/util/stringUtils.h +++ b/src/util/stringUtils.h @@ -34,6 +34,15 @@ static inline bool ffStrEndsWith(const char* str, const char* compareTo) return memcmp(str + strLength - compareToLength, compareTo, compareToLength) == 0; } +static inline bool ffStrEndsWithIgnCase(const char* str, const char* compareTo) +{ + size_t strLength = strlen(str); + size_t compareToLength = strlen(compareTo); + if (strLength < compareToLength) + return false; + return strncasecmp(str + strLength - compareToLength, compareTo, compareToLength) == 0; +} + static inline bool ffStrEquals(const char* str, const char* compareTo) { return strcmp(str, compareTo) == 0;