mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 09:58:03 +02:00
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37ec63d1bd | |||
| e7ecba4460 | |||
| e0c239729b | |||
| 6570a7accc | |||
| 0c4ec62cac | |||
| 5d11b65d53 | |||
| 8b40117c08 | |||
| b1f2bf3526 | |||
| d8452f71ed | |||
| 2a269bfd4c | |||
| cafe82b462 | |||
| db8ee8159d | |||
| f0765b1a13 | |||
| 93566cb73c | |||
| 6d0d093d62 | |||
| 54fe4ffece | |||
| 124bbb06f9 | |||
| f04a53337d | |||
| 514efab8eb | |||
| 232cd6659b | |||
| 7c93f9c82a | |||
| e5b6e3612a | |||
| 6cb15885c7 | |||
| e6d90c2081 | |||
| 679d868b4a | |||
| 72d240f325 | |||
| 2ca7e037ef | |||
| 5e9c31ac31 | |||
| bcb48774a0 | |||
| 9ff7969acf | |||
| 7fbd06a135 | |||
| bbb906ba10 | |||
| 2de674ec9a | |||
| b700d9ded5 | |||
| 359cb0a79a | |||
| 45f9de6cd2 | |||
| 233c481f7a | |||
| b677f1e902 | |||
| 8d82eedaef | |||
| 4dc27b365f | |||
| e5c3fa4023 | |||
| bdba78c45c | |||
| f95167e907 | |||
| 3908c39ce2 | |||
| 858d3749f4 | |||
| 51f36fa4b4 | |||
| bfe30eec79 | |||
| 4dd2f2d34b | |||
| 60431c0321 | |||
| 7b2b3405ae | |||
| 965ed4ba79 | |||
| 00603357ea | |||
| 5ea299a8d2 | |||
| 368a4c5a73 | |||
| 8df0a1c97e | |||
| 7098cd86cb | |||
| 681749ed54 | |||
| c4695b8cf1 | |||
| 1d12003555 | |||
| 16b10c162b | |||
| 51cfd4b5ed | |||
| a0452b8323 | |||
| ebf38e829d | |||
| 4c2af4071c | |||
| e3b8e94055 | |||
| 1d4b0236ac | |||
| da42108732 | |||
| 8b8efcdcce | |||
| 8bc4464b64 | |||
| 4361c5e787 | |||
| 558a90d4e0 | |||
| 881730d0bd | |||
| ac8fc63c28 | |||
| 8686820c1a | |||
| 39b3dc001a | |||
| ba60d7975c | |||
| 51a4f34bb5 | |||
| 01bb73b9e8 |
+1
-1
@@ -2,4 +2,4 @@
|
||||
check-filenames =
|
||||
builtin = clear,rare,usage,informal
|
||||
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*,./src/common/impl/genconfig.c
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement,Sistem,Lokal,Lokal,Sistem,Paket,Hava
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0
|
||||
uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0
|
||||
with:
|
||||
operating_system: dragonflybsd
|
||||
version: '6.4.2'
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0
|
||||
uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0
|
||||
with:
|
||||
operating_system: freebsd
|
||||
version: '15.1'
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0
|
||||
uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: inputs.arch == 'amd64'
|
||||
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
|
||||
with:
|
||||
languages: c
|
||||
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
if: inputs.arch == 'amd64'
|
||||
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0
|
||||
uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0
|
||||
with:
|
||||
operating_system: netbsd
|
||||
version: '10.1'
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0
|
||||
uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0
|
||||
with:
|
||||
operating_system: omnios
|
||||
version: 'r151058'
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Start VM
|
||||
uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0
|
||||
uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0
|
||||
with:
|
||||
operating_system: openbsd
|
||||
version: '7.9'
|
||||
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: submit signing request
|
||||
uses: signpath/github-action-submit-signing-request@b9d91eadd323de506c0c81cf0c7fe7438f3360fd # v2.2
|
||||
uses: signpath/github-action-submit-signing-request@c92b958760219087e01f8d67a1669ed57afe2627 # v2.3
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
|
||||
|
||||
@@ -12,3 +12,4 @@ fastfetch.kdev4
|
||||
*.user
|
||||
*.user.*
|
||||
*.swp
|
||||
*.log
|
||||
|
||||
+52
-9
@@ -1,3 +1,46 @@
|
||||
# Unreleased
|
||||
|
||||
Changes:
|
||||
* The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations.
|
||||
|
||||
Features:
|
||||
* Added module key localization support. (General)
|
||||
* Added a new option `--key-language <?lang>` (`display.key.language: "<?lang>"` in JSON config). When left empty, it defaults to the system locale.
|
||||
* See `fastfetch -h key-language` for all supported languages.
|
||||
* Improved Wi-Fi module
|
||||
* Added Wifi channel width detection, exposed via `{channel-width}` in custom format (reports 0 when not supported).
|
||||
* Improved Wifi channel frequency accuracy and fortified detection on Windows, macOS.
|
||||
* Added Wifi detection support on SunOS, Haiku.
|
||||
* Added Battery detection support on SunOS. (Battery, SunOS)
|
||||
* Added terminal font size detection support on Termux. (TerminalFont, Android)
|
||||
* Improved GTK theme/icons/font detection on standalone WMs such as Hyprland, sway, niri and i3. (Theme, Linux)
|
||||
* Improved fish completion scripts to print enum descriptions. (Completion)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO)
|
||||
* Some internal cleanups and optimizations.
|
||||
|
||||
# 2.67.1
|
||||
|
||||
Bugfixes:
|
||||
* Fixed a `Symbol not found` error when running on macOS 10.15. (#2499, Codec, macOS)
|
||||
* Fixed Alacritty font size never being parsed from the TOML config. (#2501, TerminalFont)
|
||||
* Fixed bright colors incorrectly being active when the terminal uses a light theme. (#2509, Display)
|
||||
* Fixed Ghostty terminal font detection (TerminalFont)
|
||||
* Now tries to load the config with the `.ghostty` extension. (#2500)
|
||||
* Fixed `font-family` fallback order. (#2510)
|
||||
* Some internal cleanups and optimizations.
|
||||
|
||||
Features:
|
||||
* Added a C23 compiler check so the build process gracefully exits during CMake configuration if the compiler is unsupported. (CMake)
|
||||
* Added compatibility workarounds for Apple Clang 16 to fix building on macOS 14. (CMake, macOS)
|
||||
* Reported real Android version codenames (e.g., "Baklava", "Vanilla Ice Cream") instead of "REL". (OS, Android)
|
||||
* Added Loadavg detection support on Haiku R1B6. (Loadavg, Haiku)
|
||||
* Enabled image logo support in the Zellij terminal multiplexer. (#2507, Logo)
|
||||
* Improved Locale detection on Windows (Locale, Windows)
|
||||
* Now respects `LC_ALL` and `LANG` environment variables if set for better compatibility with MSYS2/cygwin.
|
||||
* Appends the active system Code Page (e.g., `.UTF-8` or `.Windows-1252`) to the default system locale fallback.
|
||||
|
||||
# 2.67.0
|
||||
|
||||
Changes:
|
||||
@@ -31,12 +74,12 @@ Bugfixes:
|
||||
* Fixed invalid URL parsing in the PublicIP module. (PublicIP)
|
||||
* Correctly reported virtual GPUs on Windows. (#2461, GPU, Windows)
|
||||
* Added a size limit for network responses to prevent excessive memory usage and mitigate potential attacks. (PublicIP / Weather)
|
||||
* Fixed Ubuntu Studio Core detection (OS, Linux)
|
||||
* Fixed Ubuntu Studio Core detection. (OS, Linux)
|
||||
* Relaxed the HTTP response check so that both `HTTP/1.0` and `HTTP/1.1` responses are accepted when fetching data over the network. (PublicIP / Weather)
|
||||
* Various internal cleanups and optimizations:
|
||||
* Fixed multiple memory leaks (Separator, Camera, Codec, Display)
|
||||
* Added integer overflow checks to the string buffer implementation
|
||||
* Various code cleanups and compiler warning fixes
|
||||
* Fixed multiple memory leaks (Separator, Camera, Codec, Display).
|
||||
* Added integer overflow checks to the string buffer implementation.
|
||||
* Various code cleanups and compiler warning fixes.
|
||||
|
||||
Logos:
|
||||
* Removed Hypros, MagpieOS, Furreto, EmperorOS and Magix
|
||||
@@ -49,9 +92,9 @@ Changes:
|
||||
|
||||
Bugfixes:
|
||||
* Fixed compatibility with WSL 2.9.3 (#2433, WM, Linux)
|
||||
* Fixed accurate AMD GPU names are not queried in `driverSpecific` mode (GPU, Linux)
|
||||
* Fixed AMD GPU names not being queried accurately in `driverSpecific` mode (GPU, Linux)
|
||||
* Fixed GPU core counting for Apple Silicon GPU on Asahi Linux (GPU, Linux)
|
||||
* Some internal cleanups and optimizations
|
||||
* Some internal cleanups and optimizations.
|
||||
|
||||
Features:
|
||||
* Added Astra Linux version detection (OS, Linux)
|
||||
@@ -784,7 +827,7 @@ Features:
|
||||
* Added support for interface speed detection on SunOS (LocalIP, SunOS)
|
||||
* Added detection support for Xlibre (#1888, WM, Linux)
|
||||
* Improved the accuracy of color detection (Cursor, macOS)
|
||||
* Improved the proformance of `Nix` package manager detection on macOS by porting optimizations form Linux port (#1893, Packages, macOS)
|
||||
* Improved the performance of `Nix` package manager detection on macOS by porting optimizations from the Linux port (#1893, Packages, macOS)
|
||||
|
||||
Bugfixes:
|
||||
* Fixed custom object inheriting a key from the previous custom object if the key is blank (#1477)
|
||||
@@ -1295,7 +1338,7 @@ Features:
|
||||
* Change package manager name of NetBSD from `pkg` to `pkgsrc` (#1515, Packages, NetBSD)
|
||||
* Detect SOC name on RISCV (#1519, CPU, Linux)
|
||||
* Report marketing name of new QS8Es (CPU, Android)
|
||||
* Acquire acquire more os info from lsb-release if missing from os-release (#1521)
|
||||
* Acquire more OS info from lsb-release if missing from os-release (#1521)
|
||||
* CMake: add option `-DCUSTOM_LSB_RELEASE_PATH` to specify the path of `lsb-release` file
|
||||
* `-DCUSTOM_OS_RELEASE_PATH` has been supported since `v2.11.4`
|
||||
* Report more SOC names on Android (CPU, Android)
|
||||
@@ -1763,7 +1806,7 @@ Logos:
|
||||
|
||||
Bugfixes:
|
||||
* Fix bad Intel Arc GPU name detection, which was supposed to be fixed in the last version but the change was reverted accidentally (#1177, GPU, Linux)
|
||||
* Fix arm32 CPU name detection no longer work. Regression of 2.21.2 (CPU, Linux)
|
||||
* Fix arm32 CPU name detection no longer working. Regression of 2.21.2 (CPU, Linux)
|
||||
|
||||
# 2.21.2
|
||||
|
||||
|
||||
+33
-12
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
cmake_minimum_required(VERSION 3.21.0) # C_STANDARD
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.67.0
|
||||
VERSION 2.67.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -62,6 +62,7 @@ if(NOT PKG_CONFIG_FOUND)
|
||||
endif()
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(CheckFunctionExists)
|
||||
|
||||
if(LINUX)
|
||||
CHECK_INCLUDE_FILE("linux/version.h" HAVE_LINUX_VERSION_H)
|
||||
@@ -1022,7 +1023,7 @@ elseif(APPLE)
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/cpucache/cpucache_apple.c
|
||||
src/detection/cpuusage/cpuusage_apple.c
|
||||
src/detection/cursor/cursor_apple.m
|
||||
src/detection/cursor/cursor_apple.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_apple.c
|
||||
src/detection/physicaldisk/physicaldisk_apple.c
|
||||
@@ -1063,7 +1064,7 @@ elseif(APPLE)
|
||||
src/detection/wifi/wifi_apple.m
|
||||
src/detection/wm/wm_apple.m
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/wmtheme/wmtheme_apple.c
|
||||
src/detection/camera/camera_apple.m
|
||||
)
|
||||
# CMAKE_SYSTEM_PROCESSOR has been normalized before
|
||||
@@ -1168,7 +1169,7 @@ elseif(SunOS)
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_sunos.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/battery/battery_sunos.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/bootmgr/bootmgr_nosupport.c
|
||||
@@ -1234,7 +1235,7 @@ elseif(SunOS)
|
||||
src/detection/uptime/uptime_sunos.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wifi/wifi_sunos.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
@@ -1281,7 +1282,6 @@ elseif(Haiku)
|
||||
src/detection/keyboard/keyboard_haiku.cpp
|
||||
src/detection/libc/libc_nosupport.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/loadavg/loadavg_nosupport.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_haiku.cpp
|
||||
@@ -1305,12 +1305,19 @@ elseif(Haiku)
|
||||
src/detection/uptime/uptime_haiku.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_haiku.cpp
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wifi/wifi_haiku.cpp
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_haiku.cpp
|
||||
src/detection/camera/camera_nosupport.c
|
||||
)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} bsd)
|
||||
check_function_exists(getloadavg HAVE_GETLOADAVG)
|
||||
if(HAVE_GETLOADAVG)
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/loadavg/loadavg_sunos.c)
|
||||
else()
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/loadavg/loadavg_nosupport.c)
|
||||
endif()
|
||||
elseif(GNU)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/impl/dbus.c
|
||||
@@ -1428,7 +1435,6 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
include(CheckFunctionExists)
|
||||
if(NOT WIN32)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
endif()
|
||||
@@ -1469,10 +1475,24 @@ endforeach()
|
||||
include(CheckCSourceCompiles)
|
||||
check_c_source_compiles("int main(void){int arr[1];return _Countof(arr);}" COMPILER_SUPPORTS_COUNT_OF)
|
||||
if(COMPILER_SUPPORTS_COUNT_OF)
|
||||
message(STATUS "_Countof is supported by the compiler")
|
||||
message(STATUS "C2Y _Countof is supported by the compiler")
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_SUPPORTS_COUNT_OF=1)
|
||||
else()
|
||||
message(STATUS "_Countof is NOT supported by the compiler")
|
||||
message(STATUS "C2Y _Countof is NOT supported by the compiler")
|
||||
endif()
|
||||
|
||||
# Test C23 compiler support
|
||||
check_c_source_compiles("enum my_enum: long{MY_ENUM_ZERO}; void test(void*p){} int main(int,const char**){[[gnu::cleanup(test)]] void* x=nullptr; return (int)MY_ENUM_ZERO;}" COMPILER_SUPPORTS_C23)
|
||||
if(NOT COMPILER_SUPPORTS_C23)
|
||||
message(FATAL_ERROR "Compiler does not support C23. Please use a newer compiler.")
|
||||
endif()
|
||||
|
||||
# A hack for AppleClang 17, which supports most C23 features we use except for the `auto` keyword.
|
||||
# See https://github.com/Homebrew/homebrew-core/pull/297403
|
||||
check_c_source_compiles("int main(void){auto v = 12.34; return (int)v;}" COMPILER_SUPPORTS_AUTO)
|
||||
if(NOT COMPILER_SUPPORTS_AUTO)
|
||||
message(WARNING "Compiler does not support C23 'auto' keyword. A workaround will be applied.")
|
||||
target_compile_definitions(libfastfetch PUBLIC $<$<COMPILE_LANGUAGE:C>:auto=__auto_type>)
|
||||
endif()
|
||||
|
||||
if(yyjson_FOUND)
|
||||
@@ -1555,7 +1575,7 @@ elseif(Haiku)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
elseif(GNU)
|
||||
# On Hurd PATH_MAX is not defined. Set an arbitrary limit as workaround.
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE PATH_MAX=4096 O_PATH=0)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE PATH_MAX=4096 O_PATH=O_NORW)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
@@ -2006,6 +2026,7 @@ elseif(Haiku)
|
||||
PRIVATE "GL"
|
||||
PRIVATE "be"
|
||||
PRIVATE "gnu"
|
||||
PRIVATE "bsd"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ See the Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
* View all data that fastfetch detects: `fastfetch -s <module1>[:<module2>][:<module3>] --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate a minimal config file: `fastfetch [-s <module1>[:<module2>]] --gen-config [</path/to/config.jsonc>]`
|
||||
* Use: `--gen-config-full` to generate a full config file with all optional options
|
||||
* Use [The online configuration generator](https://fastfetch-cli.github.io/fastfetch-config/) to generate a full config file with all optional options
|
||||
|
||||
## Customization
|
||||
|
||||
@@ -335,10 +335,10 @@ If you find Fastfetch useful, please consider donating.
|
||||
|
||||
Give us a star to show your support!
|
||||
|
||||
<a href="https://star-history.com/#fastfetch-cli/fastfetch&Date">
|
||||
<a href="https://star-history.dera.page/#fastfetch-cli/fastfetch&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=fastfetch-cli/fastfetch&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://star-history.dera.page/svg?repos=fastfetch-cli/fastfetch&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://star-history.dera.page/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
<img alt="Star History Chart" src="https://star-history.dera.page/svg?repos=fastfetch-cli/fastfetch&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
+56
-24
@@ -63,46 +63,78 @@ echo '
|
||||
import json, subprocess, sys
|
||||
|
||||
|
||||
def escape_fish_dq(s: str) -> str:
|
||||
"""Escape special characters for Fish double quotes to prevent unexpected expansions. One slash in output needs four slashes in script"""
|
||||
return str(s).replace("\\\\", "\\\\\\\\").replace("\\"", "\\\\\\"").replace("$", "\\\\$")
|
||||
|
||||
|
||||
def main():
|
||||
data: dict[str, list[dict]] = json.loads(subprocess.check_output(["fastfetch", "--help-raw"]))
|
||||
|
||||
enum_functions = []
|
||||
complete_commands = []
|
||||
|
||||
for key in data:
|
||||
for flag in data[key]:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
long_name = flag.get("long", "")
|
||||
|
||||
# Handle pseudo flag logo-color-[1-9]
|
||||
if long_name == "logo-color-[1-9]":
|
||||
safe_desc_global = escape_fish_dq(flag.get("desc", ""))
|
||||
for i in range(1, 10):
|
||||
print(f"""complete -c fastfetch -d "{flag["desc"]}" -l "logo-color-{i}" -x -a "(__fastfetch_complete_color)" """)
|
||||
complete_commands.append(f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"logo-color-{i}\" -x -a \"(__fastfetch_complete_color)\"")
|
||||
continue
|
||||
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
command_prefix = f"""complete -c fastfetch -d "{flag["desc"]}" -l "{flag["long"]}\""""
|
||||
safe_desc_global = escape_fish_dq(flag.get("desc", ""))
|
||||
command_prefix = f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"{long_name}\""
|
||||
|
||||
if "short" in flag:
|
||||
command_prefix += f""" -o {flag["short"]}"""
|
||||
short_name = flag["short"]
|
||||
command_prefix += f" -o {short_name}"
|
||||
|
||||
if "arg" in flag:
|
||||
type: str = flag["arg"]["type"]
|
||||
if type == "bool":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"")
|
||||
elif type == "color":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"")
|
||||
elif type == "command":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"")
|
||||
elif type == "config":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"")
|
||||
elif type == "enum":
|
||||
temp: str = " ".join(flag["arg"]["enum"])
|
||||
print(f"{command_prefix} -x -a \"{temp}\"")
|
||||
elif type == "logo":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"")
|
||||
elif type == "structure":
|
||||
print(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"")
|
||||
elif type == "path":
|
||||
print(f"{command_prefix} -r -F")
|
||||
arg_type: str = flag["arg"]["type"]
|
||||
if arg_type == "bool":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"")
|
||||
elif arg_type == "color":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"")
|
||||
elif arg_type == "command":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"")
|
||||
elif arg_type == "config":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"")
|
||||
elif arg_type == "enum":
|
||||
# Sanitize flag name to create a valid Fish function name
|
||||
func_name = long_name.replace("-", "_").replace("[", "_").replace("]", "_")
|
||||
func_name = f"__fastfetch_complete_enum_{func_name}"
|
||||
|
||||
# Generate the enum function
|
||||
func_lines = [f"function {func_name}"]
|
||||
for enum_val, enum_desc in flag["arg"]["enum"].items():
|
||||
safe_val = escape_fish_dq(enum_val)
|
||||
safe_desc = escape_fish_dq(enum_desc)
|
||||
func_lines.append(f" echo -e \"{safe_val}\\t{safe_desc}\"")
|
||||
func_lines.append("end\n")
|
||||
enum_functions.append("\n".join(func_lines))
|
||||
|
||||
# Append complete command pointing to the new function
|
||||
complete_commands.append(f"{command_prefix} -x -a \"({func_name})\"")
|
||||
elif arg_type == "logo":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"")
|
||||
elif arg_type == "structure":
|
||||
complete_commands.append(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"")
|
||||
elif arg_type == "path":
|
||||
complete_commands.append(f"{command_prefix} -r -F")
|
||||
else:
|
||||
print(f"{command_prefix} -x")
|
||||
complete_commands.append(f"{command_prefix} -x")
|
||||
else:
|
||||
print(f"{command_prefix} -f")
|
||||
complete_commands.append(f"{command_prefix} -f")
|
||||
|
||||
# Print generated enum functions first, then complete rules
|
||||
print("\n".join(enum_functions))
|
||||
print("\n".join(complete_commands))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Vendored
+6
@@ -1,3 +1,9 @@
|
||||
fastfetch (2.67.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.67.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 06 Aug 2026 16:22:22 +0800
|
||||
|
||||
fastfetch (2.66.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.66.0
|
||||
|
||||
@@ -585,6 +585,38 @@
|
||||
"default": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "key-language",
|
||||
"desc": "Specify the language used for module keys",
|
||||
"remark": "Leave empty for auto-detection based on the system locale. Unsupported locales fall back to English",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"default": "en",
|
||||
"optional": true,
|
||||
"enum": {
|
||||
"en": "English",
|
||||
"ar": "Arabic",
|
||||
"cs": "Czech",
|
||||
"de": "German",
|
||||
"es": "Spanish",
|
||||
"fr": "French",
|
||||
"gl": "Galician",
|
||||
"he": "Hebrew",
|
||||
"id": "Indonesian",
|
||||
"it": "Italian",
|
||||
"ja": "Japanese",
|
||||
"ko": "Korean",
|
||||
"pl": "Polish",
|
||||
"pt": "Portuguese",
|
||||
"ru": "Russian",
|
||||
"tr": "Turkish",
|
||||
"uk": "Ukrainian",
|
||||
"vi": "Vietnamese",
|
||||
"zh_CN": "Simplified Chinese",
|
||||
"zh_TW": "Traditional Chinese"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "bright-color",
|
||||
"desc": "Specify whether keys, title, and ASCII logo should be printed in bright color",
|
||||
|
||||
+114
-4
@@ -1057,6 +1057,116 @@
|
||||
"description": "Left padding for keys",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
},
|
||||
"language": {
|
||||
"description": "Language used for module keys. `null` for auto detection based on system locale",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Auto detection based on system locale"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "en",
|
||||
"description": "English"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "ar",
|
||||
"description": "Arabic"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "cs",
|
||||
"description": "Czech"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "de",
|
||||
"description": "German"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "es",
|
||||
"description": "Spanish"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "fr",
|
||||
"description": "French"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "gl",
|
||||
"description": "Galician"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "he",
|
||||
"description": "Hebrew"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "id",
|
||||
"description": "Indonesian"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "it",
|
||||
"description": "Italian"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "ja",
|
||||
"description": "Japanese"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "ko",
|
||||
"description": "Korean"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pl",
|
||||
"description": "Polish"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pt",
|
||||
"description": "Portuguese"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "ru",
|
||||
"description": "Russian"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "tr",
|
||||
"description": "Turkish"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "uk",
|
||||
"description": "Ukrainian"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "vi",
|
||||
"description": "Vietnamese"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "zh_CN",
|
||||
"description": "Simplified Chinese"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "zh_TW",
|
||||
"description": "Traditional Chinese"
|
||||
}
|
||||
],
|
||||
"default": "en"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2585,8 +2695,8 @@
|
||||
},
|
||||
"waitTime": {
|
||||
"type": "integer",
|
||||
"description": "Wait time (in ms). Disk I/O = (totalBytesEnd - totalBytesStart) / waitTime",
|
||||
"default": 200,
|
||||
"description": "Wait time (in ms) used to measure the I/O rate (calculated in bytes/sec).\nAvoid setting this too low, as the kernel requires time to accurately update counters.\nIgnored if 'detectTotal' is true.",
|
||||
"default": 500,
|
||||
"minimum": 1
|
||||
},
|
||||
"key": {
|
||||
@@ -3486,8 +3596,8 @@
|
||||
},
|
||||
"waitTime": {
|
||||
"type": "integer",
|
||||
"description": "Wait time (in ms). Net I/O = (totalBytesEnd - totalBytesStart) / waitTime",
|
||||
"default": 200,
|
||||
"description": "Wait time (in ms) used to measure the I/O rate (calculated in bytes/sec).\nAvoid setting this too low, as the kernel requires time to accurately update counters.\nIgnored if 'detectTotal' is true.",
|
||||
"default": 500,
|
||||
"minimum": 1
|
||||
},
|
||||
"key": {
|
||||
|
||||
@@ -31,6 +31,10 @@ typedef struct FFPlatform {
|
||||
FFstrbuf userShell;
|
||||
|
||||
FFPlatformSysinfo sysinfo;
|
||||
|
||||
#if _WIN32
|
||||
uint32_t initCP; // The code page used by the console when the program started
|
||||
#endif
|
||||
} FFPlatform;
|
||||
|
||||
void ffPlatformInit(FFPlatform* platform);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "common/memrchr.h"
|
||||
#include "common/arrutil.h"
|
||||
|
||||
#ifdef FF_USE_SYSTEM_YYJSON
|
||||
#include <yyjson.h>
|
||||
@@ -628,3 +629,4 @@ static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
|
||||
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf);
|
||||
|
||||
#define FF_STRBUF_AUTO_DESTROY [[gnu::cleanup(ffStrbufDestroy)]] FFstrbuf
|
||||
#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) sizeof(str) - 1, .chars = str }
|
||||
|
||||
@@ -18,6 +18,7 @@ void ffPlatformInit(FFPlatform* platform) {
|
||||
|
||||
#ifdef _WIN32
|
||||
ffStrbufInit(&platform->sid);
|
||||
platform->initCP = 0;
|
||||
#endif
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
|
||||
@@ -83,6 +83,7 @@ void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free) {
|
||||
|
||||
// Round up to the next power of 2.
|
||||
// If the value is already a power of 2, it will be rounded up to the next power of 2.
|
||||
// allocate = __builtin_stdc_bit_ceil(allocate + 1); // Currently generates worse asm code
|
||||
allocate = 1U << (32 - __builtin_clz(allocate));
|
||||
}
|
||||
|
||||
|
||||
@@ -67,13 +67,13 @@ void ffPrepareCommandOption(FFdata* data) {
|
||||
char* moduleType = nullptr;
|
||||
size_t moduleLen = 0;
|
||||
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure)) {
|
||||
#define FF_IF_MODULE_MATCH(moduleNameConstant) if (moduleLen == strlen(moduleNameConstant) && ffStrEqualsIgnCase(moduleType, moduleNameConstant) && !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':'))
|
||||
#define FF_IF_MODULE_MATCH(moduleNameConstant) if (ffStrEqualsIgnCase(moduleType, moduleNameConstant) && !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':'))
|
||||
|
||||
switch (moduleType[0]) {
|
||||
#if !FF_MODULE_DISABLE_CPUUSAGE
|
||||
case 'C':
|
||||
case 'c':
|
||||
FF_IF_MODULE_MATCH(FF_CPUUSAGE_MODULE_NAME)
|
||||
FF_IF_MODULE_MATCH(ffCPUUsageModuleInfo.name)
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
#endif
|
||||
@@ -81,7 +81,7 @@ void ffPrepareCommandOption(FFdata* data) {
|
||||
#if !FF_MODULE_DISABLE_DISKIO
|
||||
case 'D':
|
||||
case 'd':
|
||||
FF_IF_MODULE_MATCH(FF_DISKIO_MODULE_NAME) {
|
||||
FF_IF_MODULE_MATCH(ffDiskIOModuleInfo.name) {
|
||||
[[gnu::cleanup(ffDestroyDiskIOOptions)]] FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
ffPrepareDiskIO(&options);
|
||||
@@ -92,7 +92,7 @@ void ffPrepareCommandOption(FFdata* data) {
|
||||
#if !FF_MODULE_DISABLE_NETIO
|
||||
case 'N':
|
||||
case 'n':
|
||||
FF_IF_MODULE_MATCH(FF_NETIO_MODULE_NAME) {
|
||||
FF_IF_MODULE_MATCH(ffNetIOModuleInfo.name) {
|
||||
[[gnu::cleanup(ffDestroyNetIOOptions)]] FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
ffPrepareNetIO(&options);
|
||||
@@ -103,7 +103,7 @@ void ffPrepareCommandOption(FFdata* data) {
|
||||
#if !FF_MODULE_DISABLE_PUBLICIP
|
||||
case 'P':
|
||||
case 'p':
|
||||
FF_IF_MODULE_MATCH(FF_PUBLICIP_MODULE_NAME) {
|
||||
FF_IF_MODULE_MATCH(ffPublicIPModuleInfo.name) {
|
||||
[[gnu::cleanup(ffDestroyPublicIpOptions)]] FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
@@ -114,7 +114,7 @@ void ffPrepareCommandOption(FFdata* data) {
|
||||
#if !FF_MODULE_DISABLE_WEATHER
|
||||
case 'W':
|
||||
case 'w':
|
||||
FF_IF_MODULE_MATCH(FF_WEATHER_MODULE_NAME) {
|
||||
FF_IF_MODULE_MATCH(ffWeatherModuleInfo.name) {
|
||||
[[gnu::cleanup(ffDestroyWeatherOptions)]] FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
|
||||
+5
-13
@@ -5,7 +5,6 @@
|
||||
#include "common/textModifier.h"
|
||||
#include "common/strutil.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "detection/terminaltheme/terminaltheme.h"
|
||||
#include "logo/logo.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -27,21 +26,10 @@ static void initState(FFstate* state) {
|
||||
state->logoWidth = 0;
|
||||
state->logoHeight = 0;
|
||||
state->keysHeight = 0;
|
||||
state->terminalLightTheme = false;
|
||||
state->titleFqdn = false;
|
||||
|
||||
ffPlatformInit(&state->platform);
|
||||
state->dynamicInterval = 0;
|
||||
|
||||
#if !FF_MODULE_DISABLE_TERMINALTHEME
|
||||
{
|
||||
// don't enable bright color if the terminal is in light mode
|
||||
FFTerminalThemeResult result;
|
||||
if (ffDetectTerminalTheme(&result, true /* forceEnv for performance */) && !result.bg.dark) {
|
||||
state->terminalLightTheme = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void defaultConfig(void) {
|
||||
@@ -51,7 +39,7 @@ static void defaultConfig(void) {
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static volatile UINT oldCp = CP_UTF8;
|
||||
static UINT oldCp = CP_UTF8;
|
||||
void resetConsoleCP(void) {
|
||||
if (oldCp != CP_UTF8) {
|
||||
SetConsoleOutputCP(oldCp);
|
||||
@@ -81,6 +69,10 @@ void ffInitInstance(void) {
|
||||
|
||||
defaultConfig();
|
||||
initState(&instance.state);
|
||||
|
||||
#ifdef _WIN32
|
||||
instance.state.platform.initCP = oldCp;
|
||||
#endif
|
||||
}
|
||||
|
||||
static volatile bool ffDisableLinewrap = false;
|
||||
|
||||
@@ -136,9 +136,9 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) {
|
||||
#if !FF_MODULE_DISABLE_CPUUSAGE
|
||||
case 'c':
|
||||
case 'C': {
|
||||
if (ffStrEqualsIgnCase(type, FF_CPUUSAGE_MODULE_NAME)) {
|
||||
if (ffStrEqualsIgnCase(type, ffCPUUsageModuleInfo.name)) {
|
||||
ffPrepareCPUUsage();
|
||||
} else if (ffStrEqualsIgnCase(type, FF_COMMAND_MODULE_NAME)) {
|
||||
} else if (ffStrEqualsIgnCase(type, ffCommandModuleInfo.name)) {
|
||||
[[gnu::cleanup(ffDestroyCommandOptions)]] FFCommandOptions options;
|
||||
ffInitCommandOptions(&options);
|
||||
if (module) {
|
||||
@@ -153,7 +153,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) {
|
||||
#if !FF_MODULE_DISABLE_DISKIO
|
||||
case 'd':
|
||||
case 'D': {
|
||||
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME)) {
|
||||
if (ffStrEqualsIgnCase(type, ffDiskIOModuleInfo.name)) {
|
||||
[[gnu::cleanup(ffDestroyDiskIOOptions)]] FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
if (module) {
|
||||
@@ -168,7 +168,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) {
|
||||
#if !FF_MODULE_DISABLE_NETIO
|
||||
case 'n':
|
||||
case 'N': {
|
||||
if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) {
|
||||
if (ffStrEqualsIgnCase(type, ffNetIOModuleInfo.name)) {
|
||||
[[gnu::cleanup(ffDestroyNetIOOptions)]] FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
if (module) {
|
||||
@@ -183,7 +183,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) {
|
||||
#if !FF_MODULE_DISABLE_PUBLICIP
|
||||
case 'p':
|
||||
case 'P': {
|
||||
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME)) {
|
||||
if (ffStrEqualsIgnCase(type, ffPublicIPModuleInfo.name)) {
|
||||
[[gnu::cleanup(ffDestroyPublicIpOptions)]] FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
if (module) {
|
||||
@@ -198,7 +198,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) {
|
||||
#if !FF_MODULE_DISABLE_WEATHER
|
||||
case 'w':
|
||||
case 'W': {
|
||||
if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME)) {
|
||||
if (ffStrEqualsIgnCase(type, ffWeatherModuleInfo.name)) {
|
||||
[[gnu::cleanup(ffDestroyWeatherOptions)]] FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
if (module) {
|
||||
|
||||
@@ -178,3 +178,83 @@ void* ffLibraryGetModule(const wchar_t* libraryFileName) {
|
||||
return module;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct LibraryIterateDynamicLibsBundle {
|
||||
FFLibraryIterateCallback callback;
|
||||
void* userData;
|
||||
};
|
||||
|
||||
#if _WIN32
|
||||
|
||||
static void ffLibraryIterateDynamicLibsCallback(PLDR_DATA_TABLE_ENTRY DataTableEntry, PVOID Context, BOOLEAN* StopEnumeration) {
|
||||
if (DataTableEntry->FullDllName.Buffer == nullptr || DataTableEntry->FullDllName.Buffer[0] == L'\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PATH_MAX * 3];
|
||||
ULONG outBytes;
|
||||
if (NT_SUCCESS(RtlUnicodeToUTF8N(path, sizeof(path), &outBytes, DataTableEntry->FullDllName.Buffer, DataTableEntry->FullDllName.Length))) {
|
||||
path[outBytes] = '\0';
|
||||
struct LibraryIterateDynamicLibsBundle* bundle = (struct LibraryIterateDynamicLibsBundle*) Context;
|
||||
*StopEnumeration = !bundle->callback(path, bundle->userData);
|
||||
}
|
||||
}
|
||||
|
||||
bool ffLibraryIterateDynamicLibs(FFLibraryIterateCallback callback, void* userData) {
|
||||
struct LibraryIterateDynamicLibsBundle bundle = {
|
||||
.callback = callback,
|
||||
.userData = userData,
|
||||
};
|
||||
return NT_SUCCESS(LdrEnumerateLoadedModules(FALSE, ffLibraryIterateDynamicLibsCallback, &bundle));
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#include <mach-o/dyld.h>
|
||||
|
||||
bool ffLibraryIterateDynamicLibs(FFLibraryIterateCallback callback, void* userData) {
|
||||
uint32_t imageCount = _dyld_image_count();
|
||||
for (uint32_t i = 0; i < imageCount; ++i) {
|
||||
const char* name = _dyld_get_image_name(i);
|
||||
if (name == nullptr || name[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!callback(name, userData)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif __has_include(<link.h>)
|
||||
#include <link.h>
|
||||
|
||||
static int ffLibraryIterateDynamicLibsCallback(struct dl_phdr_info* info, size_t, void* data) {
|
||||
if (info->dlpi_name == nullptr || info->dlpi_name[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct LibraryIterateDynamicLibsBundle* bundle = (struct LibraryIterateDynamicLibsBundle*) data;
|
||||
return !bundle->callback(info->dlpi_name, bundle->userData);
|
||||
}
|
||||
|
||||
bool ffLibraryIterateDynamicLibs(bool (*callback)(const char* name, void* userData), void* userData) {
|
||||
dl_iterate_phdr(
|
||||
ffLibraryIterateDynamicLibsCallback,
|
||||
&(struct LibraryIterateDynamicLibsBundle) {
|
||||
.callback = callback,
|
||||
.userData = userData,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool ffLibraryIterateDynamicLibs(FFLibraryIterateCallback, void*) {
|
||||
// Not implemented for this platform
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,6 +48,41 @@ static void argvToCmdline(char* const argv[], FFstrbuf* result) {
|
||||
}
|
||||
}
|
||||
|
||||
static wchar_t* createChildEnvironment(void) {
|
||||
auto pparams = ffGetPeb()->ProcessParameters;
|
||||
const wchar_t* readStart = pparams->Environment;
|
||||
|
||||
if (!readStart) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RtlAcquirePebLock();
|
||||
wchar_t* result = malloc(pparams->EnvironmentSize + sizeof(L"LANG=C.UTF-8"));
|
||||
|
||||
const wchar_t* entry = readStart;
|
||||
wchar_t* writeStart = result;
|
||||
|
||||
// Copy all environment variables except LANG
|
||||
while (*entry) {
|
||||
assert((const uint8_t*) entry <= (const uint8_t*) pparams->Environment + pparams->EnvironmentSize);
|
||||
size_t entryLength = wcslen(entry);
|
||||
if (entryLength >= strlen("LANG=") && memcmp(entry, L"LANG=", strlen("LANG=") * sizeof(wchar_t)) == 0) {
|
||||
memcpy(writeStart, readStart, (size_t) (entry - readStart) * sizeof(wchar_t));
|
||||
writeStart += (size_t) (entry - readStart);
|
||||
readStart = entry + entryLength + 1;
|
||||
}
|
||||
entry += entryLength + 1;
|
||||
}
|
||||
// Copy the remaining environment variables
|
||||
memcpy(writeStart, readStart, (size_t) (entry - readStart) * sizeof(wchar_t));
|
||||
writeStart += (size_t) (entry - readStart);
|
||||
// Add LANG=C.UTF-8 and double null terminator
|
||||
memcpy(writeStart, L"LANG=C.UTF-8\0", sizeof(L"LANG=C.UTF-8\0"));
|
||||
|
||||
RtlReleasePebLock();
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle) {
|
||||
const int32_t timeout = instance.config.general.processingTimeout;
|
||||
|
||||
@@ -108,17 +143,18 @@ const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle*
|
||||
}
|
||||
}
|
||||
|
||||
FF_AUTO_FREE wchar_t* environment = createChildEnvironment();
|
||||
BOOL success = CreateProcessW(
|
||||
nullptr, // application name
|
||||
cmdline, // command line
|
||||
nullptr, // process security attributes
|
||||
nullptr, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
nullptr, // use parent's environment
|
||||
nullptr, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
nullptr, // application name
|
||||
cmdline, // command line
|
||||
nullptr, // process security attributes
|
||||
nullptr, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
CREATE_UNICODE_ENVIRONMENT, // creation flags
|
||||
environment, // child environment
|
||||
nullptr, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
);
|
||||
|
||||
NtClose(hChildPipeWrite);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "fastfetch.h" // IWYU pragma: keep
|
||||
|
||||
#ifndef FF_DISABLE_DLOPEN
|
||||
|
||||
@@ -111,3 +111,8 @@ void* ffLibraryLoadMulti(const char* path, int maxVersion, ...);
|
||||
#if _WIN32
|
||||
void* ffLibraryGetModule(const wchar_t* libraryFileName);
|
||||
#endif
|
||||
|
||||
// Return false to stop iterating, true to continue
|
||||
typedef bool (*FFLibraryIterateCallback)(const char* name, void* userData);
|
||||
// Iterate over all loaded dynamic libraries. Returns true on success, false on failure.
|
||||
bool ffLibraryIterateDynamicLibs(FFLibraryIterateCallback callback, void* userData);
|
||||
|
||||
@@ -18,10 +18,35 @@ typedef struct FFModuleFormatArgList {
|
||||
|
||||
#define FF_FORMAT_ARG_LIST(list) { .args = list, .count = sizeof(list) / sizeof(FFModuleFormatArg) }
|
||||
|
||||
typedef struct FFModuleDisplayName {
|
||||
const char* en; // English
|
||||
|
||||
const char* ar; // Arabic
|
||||
const char* cs; // Czech
|
||||
const char* de; // German
|
||||
const char* es; // Spanish
|
||||
const char* fr; // French
|
||||
const char* gl; // Galician
|
||||
const char* he; // Hebrew
|
||||
const char* id; // Indonesian
|
||||
const char* it; // Italian
|
||||
const char* ja; // Japanese
|
||||
const char* ko; // Korean
|
||||
const char* pl; // Polish
|
||||
const char* pt; // (Brazilian) Portuguese
|
||||
const char* ru; // Russian
|
||||
const char* tr; // Turkish
|
||||
const char* uk; // Ukrainian
|
||||
const char* vi; // Vietnamese
|
||||
const char* zh_CN; // Simplified Chinese
|
||||
const char* zh_TW; // Traditional Chinese
|
||||
} FFModuleDisplayName;
|
||||
|
||||
// Must be the first field of FFModuleOptions
|
||||
typedef struct FFModuleBaseInfo {
|
||||
const char* name;
|
||||
const char* description;
|
||||
FFModuleDisplayName displayName;
|
||||
// A dirty polymorphic implementation in C.
|
||||
// This is UB, because `void*` is not compatible with `FF*Options*`.
|
||||
// However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer
|
||||
@@ -94,3 +119,5 @@ static inline void ffOptionDestroyModuleArg(FFModuleArgs* args) {
|
||||
}
|
||||
|
||||
enum { FF_OPTION_MAX_SIZE = 1 << 8 }; // Maximum size of a single option value, used for static allocation
|
||||
|
||||
#define FF_MODULE_GET_DISPLAY_NAME(moduleName) (*(const char**) ((uint8_t*) &ff ## moduleName ## ModuleInfo.displayName + instance.config.display.keyLanguage))
|
||||
|
||||
+20
-1
@@ -169,7 +169,7 @@ NTSTATUS NTAPI NtQuerySystemEnvironmentValueEx(
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI RtlGUIDFromString(IN PCUNICODE_STRING GuidString, OUT GUID* Guid);
|
||||
NTSTATUS NTAPI RtlStringFromGUIDEx(IN GUID* Guid, OUT PCUNICODE_STRING GuidString, _In_ BOOLEAN AllocateGuidString);
|
||||
NTSTATUS NTAPI RtlStringFromGUIDEx(IN const GUID* Guid, OUT PUNICODE_STRING GuidString, IN BOOLEAN AllocateGuidString);
|
||||
|
||||
typedef struct _SYSTEM_SECUREBOOT_INFORMATION {
|
||||
BOOLEAN SecureBootEnabled;
|
||||
@@ -1279,6 +1279,22 @@ NTSYSAPI NTSTATUS NTAPI LdrGetProcedureAddress(
|
||||
_In_opt_ ULONG ProcedureNumber,
|
||||
_Out_ PVOID* ProcedureAddress);
|
||||
|
||||
typedef _Function_class_(LDR_LOADED_MODULE_ENUMERATION_CALLBACK_FUNCTION)
|
||||
VOID NTAPI LDR_LOADED_MODULE_ENUMERATION_CALLBACK_FUNCTION(
|
||||
_In_ PLDR_DATA_TABLE_ENTRY DataTableEntry,
|
||||
_In_opt_ PVOID Context,
|
||||
_Inout_ BOOLEAN* StopEnumeration
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrEnumerateLoadedModules(
|
||||
_In_ BOOLEAN ReservedFlag,
|
||||
_In_ LDR_LOADED_MODULE_ENUMERATION_CALLBACK_FUNCTION* EnumProc,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
typedef enum _SECTION_INHERIT {
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
@@ -1323,3 +1339,6 @@ NTSYSAPI NTSTATUS NTAPI NtCancelIoFileEx(
|
||||
NTSYSAPI NTSTATUS NTAPI NtTerminateProcess(
|
||||
_In_opt_ HANDLE ProcessHandle,
|
||||
_In_ NTSTATUS ExitStatus);
|
||||
|
||||
NTSYSAPI NTSTATUS NTAPI RtlAcquirePebLock(VOID);
|
||||
NTSYSAPI NTSTATUS NTAPI RtlReleasePebLock(VOID);
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "battery.h"
|
||||
|
||||
#include <kstat.h>
|
||||
|
||||
static inline void kstatFreeWrap(kstat_ctl_t** pkc) {
|
||||
assert(pkc);
|
||||
if (*pkc) {
|
||||
kstat_close(*pkc);
|
||||
}
|
||||
}
|
||||
|
||||
static bool getUint32(kstat_t* ksp, const char* name, uint32_t* value) {
|
||||
kstat_named_t* stat = kstat_data_lookup(ksp, name);
|
||||
if (!stat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (stat->data_type) {
|
||||
case KSTAT_DATA_UINT32:
|
||||
*value = stat->value.ui32;
|
||||
return true;
|
||||
case KSTAT_DATA_INT32:
|
||||
if (stat->value.i32 >= 0) {
|
||||
*value = (uint32_t) stat->value.i32;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#ifdef _INT64_TYPE
|
||||
case KSTAT_DATA_UINT64:
|
||||
if (stat->value.ui64 <= UINT32_MAX) {
|
||||
*value = (uint32_t) stat->value.ui64;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case KSTAT_DATA_INT64:
|
||||
if (stat->value.i64 >= 0 && (uint64_t) stat->value.i64 <= UINT32_MAX) {
|
||||
*value = (uint32_t) stat->value.i64;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectBattery([[maybe_unused]] FFBatteryOptions* options, FFlist* results) {
|
||||
// https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/powertop/common/battery.c
|
||||
[[gnu::cleanup(kstatFreeWrap)]] kstat_ctl_t* kc = kstat_open();
|
||||
if (!kc) {
|
||||
return "kstat_open() failed";
|
||||
}
|
||||
|
||||
// illumos exposes battery information through either of these modules.
|
||||
const char* modules[] = { "battery", "acpi_drv" };
|
||||
kstat_t* bif = nullptr;
|
||||
kstat_t* bst = nullptr;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(modules); ++i) {
|
||||
bif = kstat_lookup(kc, modules[i], 0, "battery BIF0");
|
||||
bst = kstat_lookup(kc, modules[i], 0, "battery BST0");
|
||||
if (bif && bst) {
|
||||
break;
|
||||
}
|
||||
bif = nullptr;
|
||||
bst = nullptr;
|
||||
}
|
||||
|
||||
if (!bif || !bst || kstat_read(kc, bif, nullptr) < 0 || kstat_read(kc, bst, nullptr) < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t lastCapacity, remainingCapacity, rate, state;
|
||||
if (!getUint32(bif, "bif_last_cap", &lastCapacity) ||
|
||||
!getUint32(bst, "bst_rem_cap", &remainingCapacity) ||
|
||||
!getUint32(bst, "bst_state", &state)) {
|
||||
return "kstat_data_lookup() failed";
|
||||
}
|
||||
|
||||
if (lastCapacity == 0 || remainingCapacity == UINT32_MAX) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FFBatteryResult* battery = FF_LIST_ADD(FFBatteryResult, *results);
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
battery->status = FF_BATTERY_STATUS_NONE;
|
||||
battery->capacity = (double) remainingCapacity * 100.0 / (double) lastCapacity;
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
battery->timeRemaining = -1;
|
||||
|
||||
// illumos BST state: bit 0 discharging, bit 1 charging, bit 2 critical.
|
||||
if (state & (1u << 0)) {
|
||||
battery->status |= FF_BATTERY_STATUS_DISCHARGING;
|
||||
}
|
||||
if (state & (1u << 1)) {
|
||||
battery->status |= FF_BATTERY_STATUS_CHARGING;
|
||||
}
|
||||
if (state & (1u << 2)) {
|
||||
battery->status |= FF_BATTERY_STATUS_CRITICAL;
|
||||
}
|
||||
|
||||
if ((state & (1u << 0)) && getUint32(bst, "bst_rate", &rate) && rate > 0 && rate != UINT32_MAX) {
|
||||
battery->timeRemaining = (int32_t) (((uint64_t) remainingCapacity * 3600) / rate);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -19,12 +19,8 @@ const char* ffDetectCamera(FFlist* result)
|
||||
AVCaptureDeviceType deviceType = nullptr;
|
||||
|
||||
#ifdef MAC_OS_VERSION_14_0
|
||||
// Strangely `@available(macOS 14.0, *)` doesn't work here (#1594)
|
||||
if (@available(macOS 14.0, *))
|
||||
{
|
||||
if (&AVCaptureDeviceTypeExternal)
|
||||
deviceType = AVCaptureDeviceTypeExternal;
|
||||
}
|
||||
if (&AVCaptureDeviceTypeExternal)
|
||||
deviceType = AVCaptureDeviceTypeExternal;
|
||||
#endif
|
||||
if (deviceType == nullptr)
|
||||
deviceType = AVCaptureDeviceTypeExternalUnknown;
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#include <VideoToolbox/VideoToolbox.h>
|
||||
#include "common/apple/cf_helpers.h"
|
||||
|
||||
#ifdef MAC_OS_VERSION_11_0
|
||||
[[clang::weak_import]] VT_EXPORT void VTRegisterSupplementalVideoDecoderIfAvailable(CMVideoCodecType codecType);
|
||||
#endif
|
||||
|
||||
static const struct {
|
||||
CMVideoCodecType codec;
|
||||
FFCodecType type;
|
||||
@@ -70,9 +74,11 @@ static FFCodecType ffCodecDetectDecoders() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (__builtin_available(macOS 11.0, *)) {
|
||||
#ifdef MAC_OS_VERSION_11_0
|
||||
if (VTRegisterSupplementalVideoDecoderIfAvailable) {
|
||||
VTRegisterSupplementalVideoDecoderIfAvailable(codec.codec);
|
||||
}
|
||||
#endif
|
||||
bool supported = VTIsHardwareDecodeSupported(codec.codec);
|
||||
if (!supported) {
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "cursor.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
|
||||
static bool appendColor(FFstrbuf* str, CFDictionaryRef dict) {
|
||||
double r, g, b, a;
|
||||
if (
|
||||
ffCfDictGetDouble(dict, CFSTR("red"), &r) ||
|
||||
ffCfDictGetDouble(dict, CFSTR("green"), &g) ||
|
||||
ffCfDictGetDouble(dict, CFSTR("blue"), &b) ||
|
||||
ffCfDictGetDouble(dict, CFSTR("alpha"), &a)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
r = r * 255 + .5;
|
||||
g = g * 255 + .5;
|
||||
b = b * 255 + .5;
|
||||
a = a * 255 + .5;
|
||||
|
||||
uint32_t color = ((uint32_t) r << 24) | ((uint32_t) g << 16) | ((uint32_t) b << 8) | ((uint32_t) a);
|
||||
|
||||
// clang-format off
|
||||
switch (color)
|
||||
{
|
||||
case 0x000000FF: ffStrbufAppendS(str, "Black"); break;
|
||||
case 0x0433FFFF: ffStrbufAppendS(str, "Blue"); break;
|
||||
case 0xAA7942FF: ffStrbufAppendS(str, "Brown"); break;
|
||||
case 0x00FDFFFF: ffStrbufAppendS(str, "Cyan"); break;
|
||||
case 0x00F900FF: ffStrbufAppendS(str, "Green"); break;
|
||||
case 0xFF40FFFF: ffStrbufAppendS(str, "Magenta"); break;
|
||||
case 0xFF9300FF: ffStrbufAppendS(str, "Orange"); break;
|
||||
case 0x942192FF: ffStrbufAppendS(str, "Purple"); break;
|
||||
case 0xFF2600FF: ffStrbufAppendS(str, "Red"); break;
|
||||
case 0xFFFB00FF: ffStrbufAppendS(str, "Yellow"); break;
|
||||
case 0xFFFFFFFF: ffStrbufAppendS(str, "White"); break;
|
||||
case 0x00000000: ffStrbufAppendS(str, "Transparent"); break;
|
||||
default: ffStrbufAppendF(str, "#%08X", color); break;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffDetectCursor(FFCursorResult* result) {
|
||||
// Read via cfprefsd (equivalent to `defaults read com.apple.universalaccess <key>`)
|
||||
ffStrbufAppendS(&result->theme, "Fill - ");
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef color = CFPreferencesCopyAppValue(CFSTR("cursorFill"), CFSTR("com.apple.universalaccess"));
|
||||
if (!color || CFGetTypeID(color) != CFDictionaryGetTypeID() || !appendColor(&result->theme, (CFDictionaryRef) color)) {
|
||||
ffStrbufAppendS(&result->theme, "Black");
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&result->theme, ", Outline - ");
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef color = CFPreferencesCopyAppValue(CFSTR("cursorOutline"), CFSTR("com.apple.universalaccess"));
|
||||
if (!color || CFGetTypeID(color) != CFDictionaryGetTypeID() || !appendColor(&result->theme, (CFDictionaryRef) color)) {
|
||||
ffStrbufAppendS(&result->theme, "White");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef mouseDriverCursorSize = CFPreferencesCopyAppValue(CFSTR("mouseDriverCursorSize"), CFSTR("com.apple.universalaccess"));
|
||||
double size = 32;
|
||||
if (mouseDriverCursorSize && ffCfNumGetDouble(mouseDriverCursorSize, &size) == nullptr) {
|
||||
ffStrbufAppendUInt(&result->size, (uint32_t) (size * 32 + 0.5));
|
||||
} else {
|
||||
ffStrbufAppendS(&result->size, "32");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#include "cursor.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
static void appendColor(FFstrbuf* str, NSDictionary* dict)
|
||||
{
|
||||
uint32_t r = (uint32_t) (((NSNumber*) dict[@"red"]).doubleValue * 255 + .5);
|
||||
uint32_t g = (uint32_t) (((NSNumber*) dict[@"green"]).doubleValue * 255 + .5);
|
||||
uint32_t b = (uint32_t) (((NSNumber*) dict[@"blue"]).doubleValue * 255 + .5);
|
||||
uint32_t a = (uint32_t) (((NSNumber*) dict[@"alpha"]).doubleValue * 255 + .5);
|
||||
uint32_t color = (r << 24) | (g << 16) | (b << 8) | a;
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case 0x000000FF: ffStrbufAppendS(str, "Black"); return;
|
||||
case 0x0433FFFF: ffStrbufAppendS(str, "Blue"); return;
|
||||
case 0xAA7942FF: ffStrbufAppendS(str, "Brown"); return;
|
||||
case 0x00FDFFFF: ffStrbufAppendS(str, "Cyan"); return;
|
||||
case 0x00F900FF: ffStrbufAppendS(str, "Green"); return;
|
||||
case 0xFF40FFFF: ffStrbufAppendS(str, "Magenta"); return;
|
||||
case 0xFF9300FF: ffStrbufAppendS(str, "Orange"); return;
|
||||
case 0x942192FF: ffStrbufAppendS(str, "Purple"); return;
|
||||
case 0xFF2600FF: ffStrbufAppendS(str, "Red"); return;
|
||||
case 0xFFFB00FF: ffStrbufAppendS(str, "Yellow"); return;
|
||||
case 0xFFFFFFFF: ffStrbufAppendS(str, "White"); return;
|
||||
case 0x00000000: ffStrbufAppendS(str, "Transparent"); return;
|
||||
default: ffStrbufAppendF(str, "#%08X", color); return;
|
||||
}
|
||||
}
|
||||
|
||||
void ffDetectCursor(FFCursorResult* result)
|
||||
{
|
||||
NSError* error;
|
||||
NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.apple.universalaccess.plist", instance.state.platform.homeDir.chars];
|
||||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
|
||||
error:&error];
|
||||
if(error)
|
||||
{
|
||||
ffStrbufAppendS(&result->error, error.localizedDescription.UTF8String);
|
||||
return;
|
||||
}
|
||||
|
||||
NSDictionary* color;
|
||||
|
||||
ffStrbufAppendS(&result->theme, "Fill - ");
|
||||
if ((color = dict[@"cursorFill"]))
|
||||
appendColor(&result->theme, color);
|
||||
else
|
||||
ffStrbufAppendS(&result->theme, "Black");
|
||||
|
||||
ffStrbufAppendS(&result->theme, ", Outline - ");
|
||||
|
||||
if ((color = dict[@"cursorOutline"]))
|
||||
appendColor(&result->theme, color);
|
||||
else
|
||||
ffStrbufAppendS(&result->theme, "White");
|
||||
|
||||
NSNumber* mouseDriverCursorSize = dict[@"mouseDriverCursorSize"];
|
||||
if (mouseDriverCursorSize)
|
||||
ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32 + 0.5));
|
||||
else
|
||||
ffStrbufAppendS(&result->size, "32");
|
||||
}
|
||||
@@ -72,8 +72,7 @@ const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) {
|
||||
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 */;
|
||||
*currValue = (*currValue - *prevValue) * 1000 / (time2 - time1); // Calculate per second
|
||||
|
||||
// For next function call
|
||||
*prevValue = temp;
|
||||
|
||||
@@ -14,74 +14,68 @@
|
||||
#define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005)
|
||||
#endif
|
||||
|
||||
const char* ffGpuDetectDriverVersion(FFlist* gpus)
|
||||
{
|
||||
if (@available(macOS 10.7, *))
|
||||
{
|
||||
NSMutableArray* arr = NSMutableArray.new;
|
||||
FF_LIST_FOR_EACH(FFGPUResult, x, *gpus)
|
||||
[arr addObject:@(x->driver.chars)];
|
||||
|
||||
NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)arr, (__bridge CFArrayRef)@[@"CFBundleVersion"]));
|
||||
FF_LIST_FOR_EACH(FFGPUResult, x, *gpus)
|
||||
{
|
||||
NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"];
|
||||
if (version)
|
||||
{
|
||||
ffStrbufAppendC(&x->driver, ' ');
|
||||
ffStrbufAppendS(&x->driver, version.UTF8String);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
const char* ffGpuDetectDriverVersion(FFlist* gpus) {
|
||||
NSMutableArray* arr = NSMutableArray.new;
|
||||
FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) {
|
||||
[arr addObject:@(x->driver.chars)];
|
||||
}
|
||||
return "Unsupported macOS version";
|
||||
|
||||
NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef) arr, (__bridge CFArrayRef) @[ @"CFBundleVersion" ]));
|
||||
FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) {
|
||||
NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"];
|
||||
if (version) {
|
||||
ffStrbufAppendC(&x->driver, ' ');
|
||||
ffStrbufAppendS(&x->driver, version.UTF8String);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
{
|
||||
if (@available(macOS 10.13, *))
|
||||
{
|
||||
for (id<MTLDevice> device in MTLCopyAllDevices())
|
||||
{
|
||||
FFGPUResult* gpu = nullptr;
|
||||
FF_LIST_FOR_EACH(FFGPUResult, x, *gpus)
|
||||
{
|
||||
if (x->deviceId == device.registryID)
|
||||
{
|
||||
gpu = x;
|
||||
break;
|
||||
}
|
||||
const char* ffGpuDetectMetal(FFlist* gpus) {
|
||||
// Metal.framework is statically linked into the application,
|
||||
// so `MTLCopyAllDevices` is always available, or the application will not start.
|
||||
for (id<MTLDevice> device in MTLCopyAllDevices()) {
|
||||
FFGPUResult* gpu = nullptr;
|
||||
FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) {
|
||||
if (x->deviceId == device.registryID) {
|
||||
gpu = x;
|
||||
break;
|
||||
}
|
||||
if (!gpu) continue;
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2");
|
||||
else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
|
||||
#else // MAC_OS_X_VERSION_10_15
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
|
||||
if ([device supportsFamily:MTLGPUFamilyMetal4])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 4");
|
||||
else if ([device supportsFamily:MTLGPUFamilyMetal3])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
|
||||
#pragma clang diagnostic pop
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon3])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3");
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon2])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2");
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
|
||||
|
||||
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->index = (uint32_t) device.locationNumber;
|
||||
|
||||
if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0)
|
||||
gpu->shared.total = device.recommendedMaxWorkingSetSize;
|
||||
#endif
|
||||
}
|
||||
return nullptr;
|
||||
if (!gpu) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2");
|
||||
} else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
|
||||
}
|
||||
#else // MAC_OS_X_VERSION_10_15
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
|
||||
if ([device supportsFamily:MTLGPUFamilyMetal4]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 4");
|
||||
} else if ([device supportsFamily:MTLGPUFamilyMetal3]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon3]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3");
|
||||
} else if ([device supportsFamily:MTLGPUFamilyCommon2]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2");
|
||||
} else if ([device supportsFamily:MTLGPUFamilyCommon1]) {
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
|
||||
}
|
||||
|
||||
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->index = (uint32_t) device.locationNumber;
|
||||
|
||||
if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) {
|
||||
gpu->shared.total = device.recommendedMaxWorkingSetSize;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return "Metal API is not supported by this macOS version";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+56
-43
@@ -62,50 +62,63 @@ static void detectGTKFromSettings(FFGTKResult* result) {
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
|
||||
|
||||
if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4)) {
|
||||
themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, nullptr, testXfconfWallpaperPropKey).strValue;
|
||||
} else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON)) {
|
||||
themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
} else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE)) {
|
||||
themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", nullptr, "picture-filename", FF_VARIANT_TYPE_STRING).strValue;
|
||||
} else if (
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_NEBIDE)) {
|
||||
themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
} else if (
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_ENLIGHTENMENT)) {
|
||||
ffEnlightenmentSettings settings = {};
|
||||
if (ffSettingsGetEnlightenmentProperty(&settings)) {
|
||||
themeName = settings.theme;
|
||||
iconsName = settings.icon_theme;
|
||||
fontName = settings.font;
|
||||
cursorTheme = settings.use_e_cursor ? "Enlightenment" : "Application";
|
||||
cursorSize = settings.cursor_size;
|
||||
wallpaper = settings.desktop_default_background;
|
||||
if (wmde->dePrettyName.length > 0) {
|
||||
if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4)) {
|
||||
themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, nullptr, testXfconfWallpaperPropKey).strValue;
|
||||
} else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON)) {
|
||||
themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
} else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE)) {
|
||||
themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", nullptr, "picture-filename", FF_VARIANT_TYPE_STRING).strValue;
|
||||
} else if (
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_NEBIDE)) {
|
||||
themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
} else if (
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_ENLIGHTENMENT)) {
|
||||
ffEnlightenmentSettings settings = {};
|
||||
if (ffSettingsGetEnlightenmentProperty(&settings)) {
|
||||
themeName = settings.theme;
|
||||
iconsName = settings.icon_theme;
|
||||
fontName = settings.font;
|
||||
cursorTheme = settings.use_e_cursor ? "Enlightenment" : "Application";
|
||||
cursorSize = settings.cursor_size;
|
||||
wallpaper = settings.desktop_default_background;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Standalone WMs (Hyprland, sway, niri, i3, ...) report no DE and have no settings
|
||||
// daemon, but GTK apps on them still read org.gnome.desktop.interface.
|
||||
// Read via DConf, not GSettings: GSettings synthesises the schema default for keys
|
||||
// the user never set, DConf returns nothing. Runs last; applyGTKSettings() only
|
||||
// fills still-empty fields, so config files always win.
|
||||
themeName = ffSettingsGetDConf("/org/gnome/desktop/interface/gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetDConf("/org/gnome/desktop/interface/icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetDConf("/org/gnome/desktop/interface/font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetDConf("/org/gnome/desktop/interface/cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetDConf("/org/gnome/desktop/interface/cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
}
|
||||
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "detection/loadavg/loadavg.h"
|
||||
|
||||
#include <sys/loadavg.h>
|
||||
#if __has_include(<sys/loadavg.h>)
|
||||
#include <sys/loadavg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
const char* ffDetectLoadavg(double result[3]) {
|
||||
return getloadavg(result, 3) == 3 ? nullptr : "getloadavg() failed";
|
||||
|
||||
@@ -1,16 +1,87 @@
|
||||
#include "detection/locale/locale.h"
|
||||
#include "common/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winnls.h>
|
||||
|
||||
const char* ffDetectLocale(FFstrbuf* result) {
|
||||
ffStrbufAppendS(result, getenv("LC_ALL"));
|
||||
if (result->length > 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ffStrbufAppendS(result, getenv("LANG")); // Available in MSYS2 and Cygwin
|
||||
if (result->length > 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wchar_t name[LOCALE_NAME_MAX_LENGTH];
|
||||
int size = GetUserDefaultLocaleName(name, LOCALE_NAME_MAX_LENGTH);
|
||||
if (size <= 1) { // including '\0'
|
||||
return "GetUserDefaultLocaleName() failed";
|
||||
}
|
||||
ffStrbufAppendNWS(result, (uint32_t) size - 1, name);
|
||||
if (result->length > 2 && result->chars[2] == '-') { // Windows uses '-' instead of '_'
|
||||
result->chars[2] = '_';
|
||||
}
|
||||
|
||||
ffStrbufSetNWS(result, (uint32_t) size - 1, name);
|
||||
uint32_t codePage = instance.state.platform.initCP;
|
||||
if (__builtin_expect(codePage != 0, true)) {
|
||||
ffStrbufAppendC(result, '.');
|
||||
|
||||
switch (codePage) {
|
||||
case CP_UTF8:
|
||||
ffStrbufAppendS(result, "UTF-8");
|
||||
break;
|
||||
case CP_UTF7:
|
||||
ffStrbufAppendS(result, "UTF-7");
|
||||
break;
|
||||
case 1200:
|
||||
ffStrbufAppendS(result, "UTF-16LE");
|
||||
break;
|
||||
case 1201:
|
||||
ffStrbufAppendS(result, "UTF-16BE");
|
||||
break;
|
||||
case 936:
|
||||
ffStrbufAppendS(result, "GBK");
|
||||
break;
|
||||
case 54936:
|
||||
ffStrbufAppendS(result, "GB18030");
|
||||
break;
|
||||
case 950:
|
||||
ffStrbufAppendS(result, "BIG5");
|
||||
break;
|
||||
case 932:
|
||||
ffStrbufAppendS(result, "Shift_JIS");
|
||||
break;
|
||||
case 949:
|
||||
ffStrbufAppendS(result, "EUC-KR");
|
||||
break;
|
||||
case 20932:
|
||||
ffStrbufAppendS(result, "EUC-JP");
|
||||
break;
|
||||
|
||||
case 20866:
|
||||
ffStrbufAppendS(result, "KOI8-R");
|
||||
break;
|
||||
case 21866:
|
||||
ffStrbufAppendS(result, "KOI8-U");
|
||||
break;
|
||||
case 20127:
|
||||
ffStrbufAppendS(result, "US-ASCII");
|
||||
break;
|
||||
|
||||
case 874:
|
||||
case 1250 ... 1258:
|
||||
ffStrbufAppendS(result, "Windows-");
|
||||
ffStrbufAppendUInt(result, codePage);
|
||||
break;
|
||||
|
||||
default:
|
||||
ffStrbufAppendS(result, "CP");
|
||||
ffStrbufAppendUInt(result, codePage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -70,8 +70,7 @@ const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options) {
|
||||
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 */;
|
||||
*currValue = (*currValue - *prevValue) * 1000 / (time2 - time1); // Calculate per second
|
||||
*prevValue = temp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,39 @@ void ffDetectOSImpl(FFOSResult* os) {
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &os->version);
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &os->versionID);
|
||||
ffStrbufSet(&os->versionID, &os->version);
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.build.version.codename", &os->codename);
|
||||
unsigned major = 0;
|
||||
for (const char* p = os->version.chars; *p >= '0' && *p <= '9'; ++p) {
|
||||
major = major * 10 + (unsigned) (*p - '0');
|
||||
}
|
||||
|
||||
const char* codename = NULL;
|
||||
// https://en.wikipedia.org/wiki/Android_version_history
|
||||
// Android 5 is the oldest version supported by Termux
|
||||
// clang-format off
|
||||
switch (major) {
|
||||
case 17: codename = "Cinnamon Bun"; break;
|
||||
case 16: codename = "Baklava"; break;
|
||||
case 15: codename = "Vanilla Ice Cream"; break;
|
||||
case 14: codename = "Upside Down Cake"; break;
|
||||
case 13: codename = "Tiramisu"; break;
|
||||
case 12: codename = "Snow Cone"; break;
|
||||
case 11: codename = "Red Velvet Cake"; break;
|
||||
case 10: codename = "Quince Tart"; break;
|
||||
case 9: codename = "Pie"; break;
|
||||
case 8: codename = "Oreo"; break;
|
||||
case 7: codename = "Nougat"; break;
|
||||
case 6: codename = "Marshmallow"; break;
|
||||
case 5: codename = "Lollipop"; break;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
if (codename) {
|
||||
ffStrbufSetStatic(&os->codename, codename);
|
||||
} else {
|
||||
ffSettingsGetAndroidProperty("ro.build.version.codename", &os->codename);
|
||||
}
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.build.id", &os->buildID);
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ static void detectAlacritty(FFTerminalFontResult* terminalFont) {
|
||||
};
|
||||
|
||||
// alacritty parses config files in this order
|
||||
if (ffParsePropFileConfigValues("alacritty/alacritty.toml", 2, fontQueryToml)) {
|
||||
if (ffParsePropFileConfigValues("alacritty/alacritty.toml", 3, fontQueryToml)) {
|
||||
break;
|
||||
}
|
||||
if (ffParsePropFileConfigValues("alacritty.toml", 2, fontQueryToml)) {
|
||||
if (ffParsePropFileConfigValues("alacritty.toml", 3, fontQueryToml)) {
|
||||
break;
|
||||
}
|
||||
if (ffParsePropFileConfigValues(".alacritty.toml", 2, fontQueryToml)) {
|
||||
if (ffParsePropFileConfigValues(".alacritty.toml", 3, fontQueryToml)) {
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
@@ -69,7 +69,7 @@ static void detectAlacritty(FFTerminalFontResult* terminalFont) {
|
||||
ffFontInitMoveValues(&terminalFont->font, &fontFamily, &fontSize, &fontStyle);
|
||||
}
|
||||
|
||||
static void parseGhosttyConfig(const FFstrbuf* path, FFstrbuf* fontName, FFstrbuf* fontNameFallback, FFstrbuf* fontSize, FFlist* configFiles /* list of FFstrbuf */) {
|
||||
static void parseGhosttyConfig(FFstrbuf* path, FFstrbuf* fontName, FFstrbuf* fontNameFallback, FFstrbuf* fontSize, FFlist* configFiles /* list of FFstrbuf */) {
|
||||
// Maximum number of `config-file` directives to follow, guarding against runaway includes
|
||||
enum { FF_GHOSTTY_MAX_CONFIG_FILES = 16 };
|
||||
|
||||
@@ -79,7 +79,18 @@ static void parseGhosttyConfig(const FFstrbuf* path, FFstrbuf* fontName, FFstrbu
|
||||
FF_STRBUF_AUTO_DESTROY temp = ffStrbufCreate();
|
||||
if (!ffAppendFileBuffer(path->chars, &buffer)) {
|
||||
FF_DEBUG("cannot read config: %s", path->chars);
|
||||
return;
|
||||
if (ffStrbufEndsWithS(path, ".ghostty")) {
|
||||
FF_DEBUG("Trying to load config without .ghostty extension");
|
||||
path->chars[path->length - strlen(".ghostty")] = '\0';
|
||||
bool ok = ffAppendFileBuffer(path->chars, &buffer);
|
||||
path->chars[path->length - strlen(".ghostty")] = '.';
|
||||
if (!ok) {
|
||||
FF_DEBUG("cannot read config: %s", path->chars);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char* line = nullptr;
|
||||
@@ -87,13 +98,17 @@ static void parseGhosttyConfig(const FFstrbuf* path, FFstrbuf* fontName, FFstrbu
|
||||
while (ffStrbufGetline(&line, &len, &buffer)) {
|
||||
if (ffParsePropLine(line, "font-family =", &temp)) {
|
||||
FF_DEBUG("found font-family='%s' in %s", temp.chars, path->chars);
|
||||
// Latter overrides former; former becomes the fallback font
|
||||
if (fontName->length > 0) {
|
||||
ffStrbufDestroy(fontNameFallback);
|
||||
ffStrbufInitMove(fontNameFallback, fontName);
|
||||
// Ghostty appends to a fallback list; the first entry is the primary font.
|
||||
// An empty value resets the list.
|
||||
if (temp.length == 0) {
|
||||
ffStrbufClear(fontName);
|
||||
ffStrbufClear(fontNameFallback);
|
||||
} else if (fontName->length == 0) {
|
||||
ffStrbufSet(fontName, &temp);
|
||||
} else if (fontNameFallback->length == 0) {
|
||||
ffStrbufSet(fontNameFallback, &temp);
|
||||
}
|
||||
ffStrbufDestroy(fontName);
|
||||
ffStrbufInitMove(fontName, &temp);
|
||||
ffStrbufClear(&temp);
|
||||
} else if (ffParsePropLine(line, "font-size =", &temp)) {
|
||||
FF_DEBUG("found font-size='%s' in %s", temp.chars, path->chars);
|
||||
// Latter overrides former
|
||||
@@ -394,7 +409,7 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
|
||||
} else if (ffStrbufStartsWithIgnCaseS(&terminal->processName, "contour")) {
|
||||
detectContour(&terminal->exe, terminalFont);
|
||||
} else if (ffStrbufStartsWithIgnCaseS(&terminal->processName, "ghostty")) {
|
||||
detectGhostty(terminalFont, "com.mitchellh.ghostty/config", "ghostty/config");
|
||||
detectGhostty(terminalFont, "com.mitchellh.ghostty/config.ghostty", "ghostty/config.ghostty");
|
||||
} else if (ffStrbufStartsWithIgnCaseS(&terminal->processName, "Muxy")) {
|
||||
detectGhostty(terminalFont, "Muxy/ghostty.conf", "muxy/ghostty.conf");
|
||||
} else if (ffStrbufStartsWithIgnCaseS(&terminal->processName, "rio")) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "terminalfont.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
#ifdef FF_HAVE_FREETYPE
|
||||
#include "common/library.h"
|
||||
@@ -10,10 +11,17 @@
|
||||
#endif
|
||||
|
||||
#define FF_TERMUX_FONT_PATH FASTFETCH_TARGET_DIR_HOME "/.termux/font.ttf"
|
||||
#define FF_TERMUX_PREF_PATH "/data/data/com.termux/shared_prefs/com.termux_preferences.xml"
|
||||
|
||||
const char* detectTermux(FFTerminalFontResult* terminalFont) {
|
||||
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
|
||||
// SharedPreferences XML: <string name="fontsize">14</string>, in px
|
||||
if (ffParsePropFile(FF_TERMUX_PREF_PATH, "<string name=\"fontsize\">", &fontSize)) {
|
||||
ffStrbufAppendS(&fontSize, "px");
|
||||
}
|
||||
|
||||
if (!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE)) {
|
||||
ffFontInitCopy(&terminalFont->font, "monospace");
|
||||
ffFontInitValues(&terminalFont->font, "monospace", fontSize.length ? fontSize.chars : nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -39,7 +47,7 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ffFontInitCopy(&terminalFont->font, face->family_name);
|
||||
ffFontInitValues(&terminalFont->font, face->family_name, fontSize.length ? fontSize.chars : nullptr);
|
||||
|
||||
exit:
|
||||
if (face) {
|
||||
@@ -53,7 +61,7 @@ exit:
|
||||
|
||||
#else
|
||||
|
||||
FF_UNUSED(terminalFont);
|
||||
ffFontInitValues(&terminalFont->font, "monospace", fontSize.length ? fontSize.chars : nullptr);
|
||||
return "Fastfetch was built without freetype2 support";
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,20 @@
|
||||
#include "common/apple/osascript.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
const char* ffDetectWallpaper(FFstrbuf* result)
|
||||
{
|
||||
{
|
||||
// Reliable for user-picked static images.
|
||||
NSURL* url = [NSWorkspace.sharedWorkspace desktopImageURLForScreen:NSScreen.mainScreen];
|
||||
if (url.fileURL && ![url.path isEqualToString:@"/System/Library/CoreServices/DefaultDesktop.heic"] /* dynamic wallpapers */)
|
||||
{
|
||||
ffStrbufSetS(result, url.path.UTF8String);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// For Sonoma
|
||||
// https://github.com/JohnCoates/Aerial/issues/1332
|
||||
|
||||
@@ -18,7 +18,8 @@ struct FFWifiConnection {
|
||||
double rxRate;
|
||||
double txRate;
|
||||
uint16_t channel;
|
||||
uint16_t frequency; // MHz
|
||||
uint16_t channelWidth; // MHz
|
||||
uint16_t frequency; // MHz
|
||||
};
|
||||
|
||||
typedef struct FFWifiResult {
|
||||
@@ -60,3 +61,18 @@ static inline uint16_t ffWifiFreqToChannel(uint16_t frequency) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint16_t ffWifiChannelToFreq(uint16_t channel) {
|
||||
// Inverse of ffWifiFreqToChannel for the common 2.4 GHz and 5 GHz bands.
|
||||
// 4.9 GHz and 6 GHz channels overlap numerically, so they are not handled here.
|
||||
if (channel == 14) {
|
||||
return 2484;
|
||||
}
|
||||
if (channel >= 1 && channel <= 13) {
|
||||
return (uint16_t) (2407 + 5 * channel);
|
||||
}
|
||||
if (channel >= 36 && channel <= 177) { // 5 GHz: 5000 + 5*channel covers 36..177
|
||||
return (uint16_t) (5000 + 5 * channel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
ffStrbufAppendJsonVal(&item->inf.status, yyjson_obj_get(root, "supplicant_state"));
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
#include "wifi.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/strutil.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
|
||||
#import <CoreWLAN/CoreWLAN.h>
|
||||
#import <IOKit/IOKitLib.h>
|
||||
#import <IOKit/kext/KextManager.h>
|
||||
|
||||
static inline double rssiToSignalQuality(int rssi)
|
||||
{
|
||||
return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2);
|
||||
static inline double rssiToSignalQuality(int rssi) {
|
||||
return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0
|
||||
: (rssi + 100) * 2);
|
||||
}
|
||||
|
||||
@interface CWNetworkProfile()
|
||||
@property(readonly, retain, nullable) NSArray<NSDictionary *> *bssidList;
|
||||
@interface CWNetworkProfile ()
|
||||
@property (readonly, retain, nullable) NSArray<NSDictionary*>* bssidList;
|
||||
@end
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
const char* ffDetectWifi(FFlist* result) {
|
||||
NSArray<CWInterface*>* interfaces = CWWiFiClient.sharedWiFiClient.interfaces;
|
||||
if (!interfaces)
|
||||
if (!interfaces) {
|
||||
return "CWWiFiClient.sharedWiFiClient.interfaces is nil";
|
||||
}
|
||||
|
||||
for (CWInterface* inf in interfaces)
|
||||
{
|
||||
for (CWInterface* inf in interfaces) {
|
||||
FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result);
|
||||
ffStrbufInit(&item->inf.description);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
@@ -33,37 +35,42 @@ const char* ffDetectWifi(FFlist* result)
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String);
|
||||
ffStrbufSetS(&item->inf.description, inf.interfaceName.UTF8String);
|
||||
ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off");
|
||||
if(!inf.powerOn)
|
||||
|
||||
if (!inf.powerOn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetStatic(&item->conn.status, inf.interfaceMode != kCWInterfaceModeNone ? "Active" : "Inactive");
|
||||
if(inf.interfaceMode == kCWInterfaceModeNone)
|
||||
if (inf.interfaceMode == kCWInterfaceModeNone) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY ipconfig = ffStrbufCreate();
|
||||
|
||||
CWNetworkProfile* networkProfile = inf.configuration.networkProfiles.firstObject;
|
||||
|
||||
if (inf.ssid) // https://developer.apple.com/forums/thread/732431
|
||||
if (inf.ssid) { // https://developer.apple.com/forums/thread/732431
|
||||
ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String);
|
||||
else if (networkProfile.ssid)
|
||||
} else if (networkProfile.ssid) {
|
||||
ffStrbufSetStatic(&item->conn.ssid, inf.configuration.networkProfiles.firstObject.ssid.UTF8String);
|
||||
else
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.ssid, "<redacted>"); // https://developer.apple.com/forums/thread/732431
|
||||
}
|
||||
|
||||
if (inf.bssid)
|
||||
if (inf.bssid) {
|
||||
ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String);
|
||||
else if (networkProfile.bssidList)
|
||||
} else if (networkProfile.bssidList) {
|
||||
ffStrbufSetStatic(&item->conn.bssid, [networkProfile.bssidList.firstObject[@"BSSID"] UTF8String]);
|
||||
else
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.bssid, "<redacted>");
|
||||
}
|
||||
|
||||
switch(inf.activePHYMode)
|
||||
{
|
||||
switch (inf.activePHYMode) {
|
||||
case kCWPHYModeNone:
|
||||
ffStrbufSetStatic(&item->conn.protocol, "none");
|
||||
break;
|
||||
@@ -89,15 +96,15 @@ const char* ffDetectWifi(FFlist* result)
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)");
|
||||
break;
|
||||
default:
|
||||
if (inf.activePHYMode < 8)
|
||||
if (inf.activePHYMode < 8) {
|
||||
ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
item->conn.signalQuality = rssiToSignalQuality((int) inf.rssiValue);
|
||||
item->conn.txRate = inf.transmitRate;
|
||||
|
||||
switch(inf.security)
|
||||
{
|
||||
switch (inf.security) {
|
||||
case kCWSecurityNone:
|
||||
ffStrbufSetStatic(&item->conn.security, "Insecure");
|
||||
break;
|
||||
@@ -152,12 +159,33 @@ const char* ffDetectWifi(FFlist* result)
|
||||
}
|
||||
|
||||
item->conn.channel = (uint16_t) inf.wlanChannel.channelNumber;
|
||||
switch (inf.wlanChannel.channelBand)
|
||||
{
|
||||
case kCWChannelBand2GHz: item->conn.frequency = 2400; break;
|
||||
case kCWChannelBand5GHz: item->conn.frequency = 5400; break;
|
||||
case 3 /*kCWChannelBand6GHz*/: item->conn.frequency = 6400; break;
|
||||
default: item->conn.frequency = 0; break;
|
||||
switch (inf.wlanChannel.channelWidth) {
|
||||
case kCWChannelWidth20MHz: item->conn.channelWidth = 20; break;
|
||||
case kCWChannelWidth40MHz: item->conn.channelWidth = 40; break;
|
||||
case kCWChannelWidth80MHz: item->conn.channelWidth = 80; break;
|
||||
case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break;
|
||||
default: item->conn.channelWidth = 0; break;
|
||||
}
|
||||
|
||||
FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars));
|
||||
FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency;
|
||||
// Note: IO80211ChannelFrequency is only available when the interface is connected
|
||||
while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) {
|
||||
io_object_t parentService = IO_OBJECT_NULL;
|
||||
if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) {
|
||||
IOObjectRelease(service);
|
||||
service = parentService;
|
||||
} else {
|
||||
IOObjectRelease(service);
|
||||
service = IO_OBJECT_NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (frequency) {
|
||||
int64_t value;
|
||||
if (ffCfNumGetInt64(frequency, &value) == nil) {
|
||||
item->conn.frequency = (uint16_t) value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
char ssid[IEEE80211_NWID_LEN + 1] = {};
|
||||
@@ -80,6 +81,16 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.channel = curchan.ic_ieee;
|
||||
item->conn.frequency = curchan.ic_freq;
|
||||
|
||||
// Determine channel width from channel flags
|
||||
if (curchan.ic_flags & IEEE80211_CHAN_VHT160)
|
||||
item->conn.channelWidth = 160;
|
||||
else if (curchan.ic_flags & IEEE80211_CHAN_VHT80)
|
||||
item->conn.channelWidth = 80;
|
||||
else if (curchan.ic_flags & IEEE80211_CHAN_HT40)
|
||||
item->conn.channelWidth = 40;
|
||||
else
|
||||
item->conn.channelWidth = 20;
|
||||
|
||||
#ifdef IEEE80211_IS_CHAN_HE // for future use
|
||||
if (IEEE80211_IS_CHAN_HE(&curchan)) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
extern "C" {
|
||||
#include "wifi.h"
|
||||
}
|
||||
|
||||
#include <NetworkDevice.h>
|
||||
#include <NetworkInterface.h>
|
||||
#include <NetworkRoster.h>
|
||||
|
||||
static void initWifiResult(FFWifiResult* item, const char* name) {
|
||||
ffStrbufInitS(&item->inf.description, name);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
ffStrbufInit(&item->conn.status);
|
||||
ffStrbufInit(&item->conn.ssid);
|
||||
ffStrbufInit(&item->conn.bssid);
|
||||
ffStrbufInit(&item->conn.protocol);
|
||||
ffStrbufInit(&item->conn.security);
|
||||
item->conn.signalQuality = -DBL_MAX;
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
}
|
||||
|
||||
static void setWifiSecurity(FFstrbuf* security, const wireless_network& network) {
|
||||
switch (network.authentication_mode) {
|
||||
case B_NETWORK_AUTHENTICATION_NONE:
|
||||
if (network.flags & B_NETWORK_IS_ENCRYPTED) {
|
||||
ffStrbufSetStatic(security, "Encrypted");
|
||||
} else {
|
||||
ffStrbufSetStatic(security, "Insecure");
|
||||
}
|
||||
break;
|
||||
case B_NETWORK_AUTHENTICATION_WEP:
|
||||
ffStrbufSetStatic(security, "WEP");
|
||||
break;
|
||||
case B_NETWORK_AUTHENTICATION_WPA:
|
||||
ffStrbufSetStatic(security, "WPA");
|
||||
break;
|
||||
case B_NETWORK_AUTHENTICATION_WPA2:
|
||||
ffStrbufSetStatic(security, "WPA2");
|
||||
break;
|
||||
case B_NETWORK_AUTHENTICATION_EAP:
|
||||
ffStrbufSetStatic(security, "WPA Enterprise");
|
||||
break;
|
||||
default:
|
||||
ffStrbufSetF(security, "Unknown (%lu)", (unsigned long) network.authentication_mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void setWifiBssid(FFstrbuf* bssid, const wireless_network& network) {
|
||||
const uint8* address = network.address.LinkLevelAddress();
|
||||
if (address == nullptr || network.address.LinkLevelAddressLength() < 6) {
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufSetF(bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
address[0], address[1], address[2], address[3], address[4], address[5]);
|
||||
}
|
||||
|
||||
const char* ffDetectWifi(FFlist* result) {
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
BNetworkInterface interface;
|
||||
uint32 cookie = 0;
|
||||
|
||||
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
|
||||
if (!interface.Exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BNetworkDevice device(interface.Name());
|
||||
if (!device.Exists() || !device.IsWireless()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result);
|
||||
initWifiResult(item, interface.Name());
|
||||
|
||||
ffStrbufSetStatic(&item->inf.status, interface.HasLink() ? "Up" : "Down");
|
||||
if (!interface.HasLink() || !device.HasLink()) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not connected");
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetStatic(&item->conn.status, "Connected");
|
||||
|
||||
uint32 networkCookie = 0;
|
||||
wireless_network network = {};
|
||||
if (device.GetNextAssociatedNetwork(networkCookie, network) != B_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetNS(&item->conn.ssid, (uint32_t) strnlen(network.name, sizeof(network.name)), network.name);
|
||||
setWifiBssid(&item->conn.bssid, network);
|
||||
item->conn.signalQuality = network.signal_strength > 100 ? 100 : network.signal_strength;
|
||||
setWifiSecurity(&item->conn.security, network);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -212,8 +212,9 @@ static bool ffWifiNlInit(FFWifiNlContext* ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFstrbuf* protocol) {
|
||||
static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFstrbuf* protocol, uint16_t* channelWidth) {
|
||||
double rate = -DBL_MAX;
|
||||
uint16_t width = 0;
|
||||
size_t remaining = ffWifiNlAttrPayload(rateAttr);
|
||||
|
||||
for (const struct nlattr* info = (const struct nlattr*) ffWifiNlAttrData(rateAttr);
|
||||
@@ -223,6 +224,40 @@ static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFst
|
||||
size_t payload = ffWifiNlAttrPayload(info);
|
||||
|
||||
switch (type) {
|
||||
case NL80211_RATE_INFO_40_MHZ_WIDTH:
|
||||
width = 40;
|
||||
break;
|
||||
case NL80211_RATE_INFO_80_MHZ_WIDTH:
|
||||
case NL80211_RATE_INFO_80P80_MHZ_WIDTH:
|
||||
width = 80;
|
||||
break;
|
||||
case NL80211_RATE_INFO_160_MHZ_WIDTH:
|
||||
width = 160;
|
||||
break;
|
||||
case 18 /* NL80211_RATE_INFO_320_MHZ_WIDTH */:
|
||||
width = 320;
|
||||
break;
|
||||
case NL80211_RATE_INFO_10_MHZ_WIDTH:
|
||||
width = 10;
|
||||
break;
|
||||
case NL80211_RATE_INFO_5_MHZ_WIDTH:
|
||||
width = 5;
|
||||
break;
|
||||
case 25 /* NL80211_RATE_INFO_1_MHZ_WIDTH */:
|
||||
width = 1;
|
||||
break;
|
||||
case 26 /* NL80211_RATE_INFO_2_MHZ_WIDTH */:
|
||||
width = 2;
|
||||
break;
|
||||
case 27 /* NL80211_RATE_INFO_4_MHZ_WIDTH */:
|
||||
width = 4;
|
||||
break;
|
||||
case 28 /* NL80211_RATE_INFO_8_MHZ_WIDTH */:
|
||||
width = 8;
|
||||
break;
|
||||
case 29 /* NL80211_RATE_INFO_16_MHZ_WIDTH */:
|
||||
width = 16;
|
||||
break;
|
||||
case 30 /* NL80211_RATE_INFO_UHR_MCS */:
|
||||
ffStrbufSetStatic(protocol, "802.11bn (Wi-Fi 8)");
|
||||
break;
|
||||
@@ -254,9 +289,126 @@ static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFst
|
||||
}
|
||||
}
|
||||
|
||||
if (rate != -DBL_MAX && *channelWidth == 0) {
|
||||
*channelWidth = width;
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static uint16_t ffWifiChannelWidthToMhz(uint32_t width) {
|
||||
switch (width) {
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
return 20;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
return 40;
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
return 80;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
return 160;
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
return 5;
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
return 10;
|
||||
case NL80211_CHAN_WIDTH_1:
|
||||
return 1;
|
||||
case NL80211_CHAN_WIDTH_2:
|
||||
return 2;
|
||||
case NL80211_CHAN_WIDTH_4:
|
||||
return 4;
|
||||
case NL80211_CHAN_WIDTH_8:
|
||||
return 8;
|
||||
case NL80211_CHAN_WIDTH_16:
|
||||
return 16;
|
||||
case 13 /* NL80211_CHAN_WIDTH_320 */:
|
||||
return 320;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ffWifiFetchInterfaceInfo(FFWifiNlContext* ctx, FFWifiResult* item, uint32_t ifIndex) {
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct genlmsghdr genl;
|
||||
char attrs[32];
|
||||
} req = {
|
||||
.nlh = {
|
||||
.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr)),
|
||||
.nlmsg_type = ctx->nl80211FamilyId,
|
||||
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
|
||||
.nlmsg_seq = ++ctx->seq,
|
||||
.nlmsg_pid = ctx->portId,
|
||||
},
|
||||
.genl = {
|
||||
.cmd = NL80211_CMD_GET_INTERFACE,
|
||||
.version = 0,
|
||||
},
|
||||
};
|
||||
|
||||
if (!ffWifiNlAppendAttr(&req.nlh, sizeof(req), NL80211_ATTR_IFINDEX, &ifIndex, sizeof(ifIndex))) {
|
||||
FF_DEBUG("Failed to build nl80211 interface request");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_nl addr = {
|
||||
.nl_family = AF_NETLINK,
|
||||
};
|
||||
|
||||
ssize_t sent = sendto(ctx->sockFd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*) &addr, sizeof(addr));
|
||||
if (sent != (ssize_t) req.nlh.nlmsg_len) {
|
||||
FF_DEBUG("Failed to send nl80211 interface request");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t buffer[8192];
|
||||
while (true) {
|
||||
ssize_t received = recvfrom(ctx->sockFd, buffer, sizeof(buffer), 0, nullptr, nullptr);
|
||||
if (received < 0) {
|
||||
FF_DEBUG("Failed to receive nl80211 interface reply: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const struct nlmsghdr* nlh = (const struct nlmsghdr*) buffer;
|
||||
NLMSG_OK(nlh, received);
|
||||
nlh = NLMSG_NEXT(nlh, received)) {
|
||||
if (nlh->nlmsg_seq != req.nlh.nlmsg_seq) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nlh->nlmsg_type == NLMSG_ERROR) {
|
||||
const struct nlmsgerr* err = (const struct nlmsgerr*) NLMSG_DATA(nlh);
|
||||
if (err->error != 0) {
|
||||
FF_DEBUG("nl80211 interface request failed: %s", strerror(-err->error));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nlh->nlmsg_type != ctx->nl80211FamilyId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const struct genlmsghdr* genl = (const struct genlmsghdr*) NLMSG_DATA(nlh);
|
||||
size_t attrRemaining = nlh->nlmsg_len - NLMSG_HDRLEN - GENL_HDRLEN;
|
||||
for (const struct nlattr* attr = (const struct nlattr*) ((const char*) genl + GENL_HDRLEN);
|
||||
ffWifiNlAttrOk(attr, attrRemaining);
|
||||
attr = ffWifiNlAttrNext(attr, &attrRemaining)) {
|
||||
if ((attr->nla_type & NLA_TYPE_MASK) != NL80211_ATTR_CHANNEL_WIDTH ||
|
||||
ffWifiNlAttrPayload(attr) < sizeof(uint32_t)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
item->conn.channelWidth = ffWifiChannelWidthToMhz(*(const uint32_t*) ffWifiNlAttrData(attr));
|
||||
return item->conn.channelWidth != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ffWifiApplySecurityFlags(FFWifiResult* item, const FFWifiSecurityFlags* sec) {
|
||||
ffStrbufClear(&item->conn.security);
|
||||
|
||||
@@ -566,13 +718,13 @@ static void ffWifiParseStationInfo(const struct nlattr* staInfoAttr, FFWifiResul
|
||||
if (type == NL80211_STA_INFO_SIGNAL && payload >= sizeof(uint8_t) && item->conn.signalQuality == -DBL_MAX) {
|
||||
int rssi = (int8_t) *(const uint8_t*) ffWifiNlAttrData(attr);
|
||||
item->conn.signalQuality = rssiToSignalQuality(rssi);
|
||||
} else if (type == NL80211_STA_INFO_TX_BITRATE && item->conn.txRate == -DBL_MAX) {
|
||||
double tx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol);
|
||||
} else if (type == NL80211_STA_INFO_TX_BITRATE && (item->conn.txRate == -DBL_MAX || item->conn.channelWidth == 0)) {
|
||||
double tx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol, &item->conn.channelWidth);
|
||||
if (tx != -DBL_MAX) {
|
||||
item->conn.txRate = tx;
|
||||
}
|
||||
} else if (type == NL80211_STA_INFO_RX_BITRATE && item->conn.rxRate == -DBL_MAX) {
|
||||
double rx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol);
|
||||
} else if (type == NL80211_STA_INFO_RX_BITRATE && (item->conn.rxRate == -DBL_MAX || item->conn.channelWidth == 0)) {
|
||||
double rx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol, &item->conn.channelWidth);
|
||||
if (rx != -DBL_MAX) {
|
||||
item->conn.rxRate = rx;
|
||||
}
|
||||
@@ -680,6 +832,7 @@ static const char* detectWithNetlink(FFWifiNlContext* ctx, FFWifiResult* item, u
|
||||
if (ffWifiFetchScanInfo(ctx, item, ifIndex)) {
|
||||
FF_DEBUG("found associated BSS: %s", item->conn.ssid.chars);
|
||||
ffStrbufSetStatic(&item->conn.status, "connected");
|
||||
ffWifiFetchInterfaceInfo(ctx, item, ifIndex);
|
||||
ffWifiFetchStationInfo(ctx, item, ifIndex);
|
||||
if (!item->conn.protocol.length && item->conn.txRate != -DBL_MAX) {
|
||||
FF_DEBUG("nl80211 station info did not include MCS family fields");
|
||||
@@ -923,6 +1076,7 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
char operstate;
|
||||
|
||||
@@ -47,6 +47,7 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
char ssid[IEEE80211_NWID_LEN + 1] = {};
|
||||
@@ -91,6 +92,16 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq);
|
||||
item->conn.frequency = curchan.ic_freq;
|
||||
|
||||
// Determine channel width from channel flags
|
||||
if (curchan.ic_flags & IEEE80211_CHAN_VHT160)
|
||||
item->conn.channelWidth = 160;
|
||||
else if (curchan.ic_flags & IEEE80211_CHAN_VHT80)
|
||||
item->conn.channelWidth = 80;
|
||||
else if (curchan.ic_flags & IEEE80211_CHAN_HT40)
|
||||
item->conn.channelWidth = 40;
|
||||
else
|
||||
item->conn.channelWidth = 20;
|
||||
|
||||
#ifdef IEEE80211_IS_CHAN_HE // for future use
|
||||
if (IEEE80211_IS_CHAN_HE(&curchan)) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "wifi.h"
|
||||
#include "common/io.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -17,12 +16,20 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
if_freenameindex(infs);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
for (struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == nullptr); ++i) {
|
||||
if (!ffStrStartsWith(i->if_name, "iwm")) {
|
||||
continue;
|
||||
struct ieee80211_nodereq nr = {};
|
||||
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
|
||||
|
||||
int err = 0;
|
||||
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
|
||||
err = errno;
|
||||
if (err == ENXIO || err == ENODEV || err == EINVAL || err == ENOTTY) {
|
||||
continue; // Not a Wi-Fi interface
|
||||
}
|
||||
}
|
||||
|
||||
FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result);
|
||||
@@ -37,11 +44,9 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0; // not exposed by ieee80211_nodereq
|
||||
item->conn.frequency = 0;
|
||||
|
||||
struct ieee80211_nodereq nr = {};
|
||||
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
|
||||
|
||||
struct ifreq ifr = {};
|
||||
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
@@ -50,31 +55,34 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
|
||||
}
|
||||
|
||||
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nr.nr_nwid_len > 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid);
|
||||
} else {
|
||||
if (err != 0 || nr.nr_nwid_len == 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid);
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2], nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]);
|
||||
|
||||
item->conn.channel = nr.nr_channel;
|
||||
if (item->conn.channel == 0) {
|
||||
struct ieee80211chanreq chreq = {};
|
||||
strlcpy(chreq.i_name, i->if_name, sizeof(chreq.i_name));
|
||||
if (ioctl(sock, SIOCG80211CHANNEL, &chreq) >= 0) {
|
||||
item->conn.channel = chreq.i_channel;
|
||||
}
|
||||
}
|
||||
item->conn.frequency = ffWifiChannelToFreq(item->conn.channel);
|
||||
|
||||
if (nr.nr_max_rssi) {
|
||||
item->conn.signalQuality = ((float) nr.nr_rssi / nr.nr_max_rssi) * 100.0;
|
||||
item->conn.signalQuality = ((double) nr.nr_rssi / (double) nr.nr_max_rssi) * 100.0;
|
||||
}
|
||||
|
||||
if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
} else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
|
||||
// VHT implies HT, so test VHT first
|
||||
if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
} else if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) {
|
||||
@@ -85,15 +93,22 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) {
|
||||
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) {
|
||||
if (wpa.i_akms & IEEE80211_WPA_AKM_SAE) {
|
||||
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) {
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA2/WPA3");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA3");
|
||||
}
|
||||
} else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) {
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA2");
|
||||
} else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1) {
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.security, "Unknown");
|
||||
}
|
||||
} else {
|
||||
struct ieee80211_nwkey nwkey = {};
|
||||
strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) {
|
||||
if (nwkey.i_wepon) {
|
||||
ffStrbufSetStatic(&item->conn.security, "WEP");
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
#include "wifi.h"
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stropts.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <inet/wifi_ioctl.h>
|
||||
|
||||
static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wldp_t* buffer) {
|
||||
memset(buffer, 0, MAX_BUF_LEN);
|
||||
buffer->wldp_type = NET_802_11;
|
||||
buffer->wldp_id = id;
|
||||
|
||||
struct strioctl request = {
|
||||
.ic_cmd = WLAN_GET_PARAM,
|
||||
.ic_timout = 0,
|
||||
.ic_len = MAX_BUF_LEN,
|
||||
.ic_dp = (char*) buffer,
|
||||
};
|
||||
|
||||
if (ioctl(fd, I_STR, &request) != 0 || buffer->wldp_result != WL_SUCCESS || buffer->wldp_length < WIFI_BUF_OFFSET + valueSize || buffer->wldp_length > MAX_BUF_LEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(value, buffer->wldp_buf, valueSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) {
|
||||
switch (subtype) {
|
||||
case WL_FHSS:
|
||||
ffStrbufSetStatic(protocol, "802.11 (FHSS)");
|
||||
break;
|
||||
case WL_DSSS:
|
||||
ffStrbufSetStatic(protocol, "802.11 (DSSS)");
|
||||
break;
|
||||
case WL_IRBASE:
|
||||
ffStrbufSetStatic(protocol, "802.11 (IR)");
|
||||
break;
|
||||
case WL_OFDM:
|
||||
ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11a");
|
||||
break;
|
||||
case WL_HRDS:
|
||||
ffStrbufSetStatic(protocol, "802.11b");
|
||||
break;
|
||||
case WL_ERP:
|
||||
ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAuthMode, uint32_t authMode) {
|
||||
switch (encryption) {
|
||||
case WL_NOENCRYPTION:
|
||||
ffStrbufSetStatic(security, "Insecure");
|
||||
break;
|
||||
case WL_ENC_WEP:
|
||||
ffStrbufSetStatic(security, "WEP");
|
||||
break;
|
||||
case WL_ENC_WPA:
|
||||
ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA");
|
||||
break;
|
||||
default:
|
||||
ffStrbufSetStatic(security, "Unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectWifi(FFlist* result) {
|
||||
// https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/cmd-inet/usr.sbin/wificonfig/wificonfig.c
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi");
|
||||
if (!directory) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN);
|
||||
if (!bufferMemory) {
|
||||
return "malloc() failed";
|
||||
}
|
||||
wldp_t* buffer = (wldp_t*) bufferMemory;
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(directory)) != nullptr) {
|
||||
size_t nameLength = strlen(entry->d_name);
|
||||
if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') {
|
||||
continue;
|
||||
}
|
||||
|
||||
char devicePath[PATH_MAX];
|
||||
int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name);
|
||||
if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
if (!isastream(fd)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result);
|
||||
ffStrbufInitS(&item->inf.description, entry->d_name);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
ffStrbufInit(&item->conn.status);
|
||||
ffStrbufInit(&item->conn.ssid);
|
||||
ffStrbufInit(&item->conn.bssid);
|
||||
ffStrbufInit(&item->conn.protocol);
|
||||
ffStrbufInit(&item->conn.security);
|
||||
item->conn.signalQuality = -DBL_MAX;
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
wl_radio_t radio;
|
||||
if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) {
|
||||
ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->inf.status, "Unknown");
|
||||
}
|
||||
|
||||
wl_linkstatus_t linkStatus;
|
||||
if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Unknown");
|
||||
continue;
|
||||
}
|
||||
if (linkStatus != WL_CONNECTED) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not connected");
|
||||
continue;
|
||||
}
|
||||
ffStrbufSetStatic(&item->conn.status, "Connected");
|
||||
|
||||
wl_essid_t essid;
|
||||
if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length > 0 && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) {
|
||||
ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid);
|
||||
}
|
||||
|
||||
wl_bssid_t bssid;
|
||||
if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) {
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", (uint8_t) bssid[0], (uint8_t) bssid[1], (uint8_t) bssid[2], (uint8_t) bssid[3], (uint8_t) bssid[4], (uint8_t) bssid[5]);
|
||||
}
|
||||
|
||||
wl_rssi_t rssi;
|
||||
if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) {
|
||||
item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0;
|
||||
}
|
||||
|
||||
wl_phy_conf_t phy;
|
||||
if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) {
|
||||
uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype;
|
||||
switch (subtype) {
|
||||
case WL_FHSS:
|
||||
item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel;
|
||||
setWifiProtocol(&item->conn.protocol, subtype, false);
|
||||
break;
|
||||
case WL_DSSS:
|
||||
item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel;
|
||||
setWifiProtocol(&item->conn.protocol, subtype, false);
|
||||
break;
|
||||
case WL_OFDM:
|
||||
item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency;
|
||||
item->conn.channel = ffWifiFreqToChannel(item->conn.frequency);
|
||||
setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled);
|
||||
break;
|
||||
case WL_ERP:
|
||||
item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel;
|
||||
setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled);
|
||||
break;
|
||||
default:
|
||||
setWifiProtocol(&item->conn.protocol, subtype, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wl_encryption_t encryption;
|
||||
wl_authmode_t authMode;
|
||||
bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer);
|
||||
bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer);
|
||||
if (haveEncryption) {
|
||||
setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -5,41 +5,59 @@
|
||||
#include <windows.h>
|
||||
#include <wlanapi.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
|
||||
static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result) {
|
||||
switch (state) {
|
||||
case wlan_interface_state_not_ready:
|
||||
ffStrbufAppendS(result, "Not ready");
|
||||
ffStrbufSetStatic(result, "Not ready");
|
||||
break;
|
||||
case wlan_interface_state_connected:
|
||||
ffStrbufAppendS(result, "Connected");
|
||||
ffStrbufSetStatic(result, "Connected");
|
||||
break;
|
||||
case wlan_interface_state_ad_hoc_network_formed:
|
||||
ffStrbufAppendS(result, "Ad hoc network formed");
|
||||
ffStrbufSetStatic(result, "Ad hoc network formed");
|
||||
break;
|
||||
case wlan_interface_state_disconnecting:
|
||||
ffStrbufAppendS(result, "Disconnecting");
|
||||
ffStrbufSetStatic(result, "Disconnecting");
|
||||
break;
|
||||
case wlan_interface_state_disconnected:
|
||||
ffStrbufAppendS(result, "Disconnected");
|
||||
ffStrbufSetStatic(result, "Disconnected");
|
||||
break;
|
||||
case wlan_interface_state_associating:
|
||||
ffStrbufAppendS(result, "Associating");
|
||||
ffStrbufSetStatic(result, "Associating");
|
||||
break;
|
||||
case wlan_interface_state_discovering:
|
||||
ffStrbufAppendS(result, "Discovering");
|
||||
ffStrbufSetStatic(result, "Discovering");
|
||||
break;
|
||||
case wlan_interface_state_authenticating:
|
||||
ffStrbufAppendS(result, "Authenticating");
|
||||
ffStrbufSetStatic(result, "Authenticating");
|
||||
break;
|
||||
default:
|
||||
ffStrbufAppendS(result, "Unknown");
|
||||
ffStrbufSetStatic(result, "Unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO {
|
||||
UCHAR ucLinkID;
|
||||
ULONG ulChannelCenterFrequencyMhz;
|
||||
ULONG ulBandwidth;
|
||||
LONG lRssi;
|
||||
WLAN_RATE_SET wlanRateSet;
|
||||
} WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO, *PWLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO;
|
||||
|
||||
typedef struct _WLAN_REALTIME_CONNECTION_QUALITY {
|
||||
DOT11_PHY_TYPE dot11PhyType;
|
||||
ULONG ulLinkQuality;
|
||||
ULONG ulRxRate;
|
||||
ULONG ulTxRate;
|
||||
BOOL bIsMLOConnection;
|
||||
ULONG ulNumLinks;
|
||||
// Array of size ulNumLinks
|
||||
WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO linksInfo[];
|
||||
} WLAN_REALTIME_CONNECTION_QUALITY, *PWLAN_REALTIME_CONNECTION_QUALITY;
|
||||
|
||||
enum { wlan_intf_opcode_realtime_connection_quality = 19 };
|
||||
|
||||
const char* ffDetectWifi(FFlist* result) {
|
||||
FF_LIBRARY_LOAD_MESSAGE(wlanapi, "wlanapi" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle)
|
||||
@@ -54,7 +72,7 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
WLAN_INTERFACE_INFO_LIST* ifList = nullptr;
|
||||
const char* error = nullptr;
|
||||
|
||||
if (ffWlanOpenHandle(2, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) {
|
||||
if (ffWlanOpenHandle(2 /*maxClientVersion*/, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) {
|
||||
error = "WlanOpenHandle() failed";
|
||||
goto exit;
|
||||
}
|
||||
@@ -79,6 +97,7 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.channelWidth = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
convertIfStateToString(ifInfo->isState, &item->inf.status);
|
||||
@@ -200,17 +219,44 @@ const char* ffDetectWifi(FFlist* result) {
|
||||
ffStrbufAppendS(&item->conn.security, "Insecure");
|
||||
}
|
||||
|
||||
WLAN_BSS_LIST* bssList = nullptr;
|
||||
if (ffWlanGetNetworkBssList(hClient,
|
||||
WLAN_REALTIME_CONNECTION_QUALITY* connectionQuality = nullptr;
|
||||
bufSize = 0;
|
||||
if (ffWlanQueryInterface(hClient,
|
||||
&ifInfo->InterfaceGuid,
|
||||
&connInfo->wlanAssociationAttributes.dot11Ssid,
|
||||
connInfo->wlanAssociationAttributes.dot11BssType,
|
||||
connInfo->wlanSecurityAttributes.bSecurityEnabled,
|
||||
wlan_intf_opcode_realtime_connection_quality,
|
||||
nullptr,
|
||||
&bssList) == ERROR_SUCCESS &&
|
||||
bssList->dwNumberOfItems > 0) {
|
||||
item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000);
|
||||
ffWlanFreeMemory(bssList);
|
||||
&bufSize,
|
||||
(PVOID*) &connectionQuality,
|
||||
&opCode) == ERROR_SUCCESS) {
|
||||
const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* bestLink = nullptr;
|
||||
for (ULONG linkIndex = 0; linkIndex < connectionQuality->ulNumLinks; ++linkIndex) {
|
||||
const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* link = &connectionQuality->linksInfo[linkIndex];
|
||||
if (!bestLink || link->lRssi > bestLink->lRssi) {
|
||||
bestLink = link;
|
||||
}
|
||||
}
|
||||
if (bestLink) {
|
||||
item->conn.channelWidth = (uint16_t) bestLink->ulBandwidth;
|
||||
item->conn.frequency = (uint16_t) bestLink->ulChannelCenterFrequencyMhz;
|
||||
}
|
||||
}
|
||||
if (connectionQuality) {
|
||||
ffWlanFreeMemory(connectionQuality);
|
||||
}
|
||||
|
||||
if (item->conn.frequency == 0) {
|
||||
WLAN_BSS_LIST* bssList = nullptr;
|
||||
if (ffWlanGetNetworkBssList(hClient,
|
||||
&ifInfo->InterfaceGuid,
|
||||
&connInfo->wlanAssociationAttributes.dot11Ssid,
|
||||
connInfo->wlanAssociationAttributes.dot11BssType,
|
||||
connInfo->wlanSecurityAttributes.bSecurityEnabled,
|
||||
nullptr,
|
||||
&bssList) == ERROR_SUCCESS &&
|
||||
bssList->dwNumberOfItems > 0) {
|
||||
item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000);
|
||||
ffWlanFreeMemory(bssList);
|
||||
}
|
||||
}
|
||||
|
||||
ffWlanFreeMemory(connInfo);
|
||||
@@ -238,5 +284,3 @@ exit:
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "fastfetch.h"
|
||||
#include "wmtheme.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
|
||||
bool ffDetectWmTheme(FFstrbuf* themeOrError) {
|
||||
// Read via cfprefsd instead of the raw plist file to keep cache consistency with the system
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef wmThemeColor = CFPreferencesCopyAppValue(CFSTR("AppleAccentColor"), kCFPreferencesAnyApplication);
|
||||
int32_t accentColor = -2; // -2: not set; -1 is Graphite
|
||||
if (wmThemeColor && ffCfNumGetInt(wmThemeColor, &accentColor) == nullptr) {
|
||||
switch (accentColor) {
|
||||
case -1:
|
||||
ffStrbufAppendS(themeOrError, "Graphite");
|
||||
break;
|
||||
case 0:
|
||||
ffStrbufAppendS(themeOrError, "Red");
|
||||
break;
|
||||
case 1:
|
||||
ffStrbufAppendS(themeOrError, "Orange");
|
||||
break;
|
||||
case 2:
|
||||
ffStrbufAppendS(themeOrError, "Yellow");
|
||||
break;
|
||||
case 3:
|
||||
ffStrbufAppendS(themeOrError, "Green");
|
||||
break;
|
||||
case 4:
|
||||
ffStrbufAppendS(themeOrError, "Blue");
|
||||
break;
|
||||
case 5:
|
||||
ffStrbufAppendS(themeOrError, "Purple");
|
||||
break;
|
||||
case 6:
|
||||
ffStrbufAppendS(themeOrError, "Pink");
|
||||
break;
|
||||
default:
|
||||
ffStrbufAppendS(themeOrError, "Unknown");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ffStrbufAppendS(themeOrError, "Multicolor");
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY style = ffStrbufCreate();
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef wmTheme = CFPreferencesCopyAppValue(CFSTR("AppleInterfaceStyle"), kCFPreferencesAnyApplication);
|
||||
if (wmTheme && ffCfStrGetString(wmTheme, &style) == nullptr) {
|
||||
ffStrbufAppendF(themeOrError, " (%s)", style.chars);
|
||||
} else {
|
||||
ffStrbufAppendS(themeOrError, " (Light)");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "wmtheme.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
bool ffDetectWmTheme(FFstrbuf* themeOrError)
|
||||
{
|
||||
NSError* error;
|
||||
NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/.GlobalPreferences.plist", instance.state.platform.homeDir.chars];
|
||||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
|
||||
error:&error];
|
||||
if(error)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, error.localizedDescription.UTF8String);
|
||||
return false;
|
||||
}
|
||||
|
||||
NSNumber* wmThemeColor = dict[@"AppleAccentColor"];
|
||||
if(!wmThemeColor)
|
||||
ffStrbufAppendS(themeOrError, "Multicolor");
|
||||
else
|
||||
{
|
||||
switch(wmThemeColor.intValue)
|
||||
{
|
||||
case -1: ffStrbufAppendS(themeOrError, "Graphite"); break;
|
||||
case 0: ffStrbufAppendS(themeOrError, "Red"); break;
|
||||
case 1: ffStrbufAppendS(themeOrError, "Orange"); break;
|
||||
case 2: ffStrbufAppendS(themeOrError, "Yellow"); break;
|
||||
case 3: ffStrbufAppendS(themeOrError, "Green"); break;
|
||||
case 4: ffStrbufAppendS(themeOrError, "Blue"); break;
|
||||
case 5: ffStrbufAppendS(themeOrError, "Purple"); break;
|
||||
case 6: ffStrbufAppendS(themeOrError, "Pink"); break;
|
||||
default: ffStrbufAppendS(themeOrError, "Unknown"); break;
|
||||
}
|
||||
}
|
||||
|
||||
NSString* wmTheme = dict[@"AppleInterfaceStyle"];
|
||||
ffStrbufAppendF(themeOrError, " (%s)", wmTheme ? wmTheme.UTF8String : "Light");
|
||||
return true;
|
||||
}
|
||||
@@ -31,7 +31,6 @@ typedef struct FFstate {
|
||||
uint32_t logoWidth;
|
||||
uint32_t logoHeight;
|
||||
uint32_t keysHeight;
|
||||
bool terminalLightTheme;
|
||||
bool titleFqdn;
|
||||
uint32_t dynamicInterval;
|
||||
FFPlatform platform;
|
||||
|
||||
@@ -996,7 +996,7 @@ bool ffLogoPrintImageIfExists(FFLogoType type, bool printError) {
|
||||
}
|
||||
|
||||
const char* term = getenv("TERM");
|
||||
if ((term && ffStrEquals(term, "screen")) || getenv("ZELLIJ")) {
|
||||
if (term && ffStrEquals(term, "screen")) {
|
||||
if (printError) {
|
||||
fputs("Logo: Image logo is not supported in terminal multiplexers\n", stderr);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
if (options->moduleArgs.key.length == 0) {
|
||||
if (result->modelName.length > 0) {
|
||||
ffStrbufSetF(&key, "%s (%s)", FF_BATTERY_MODULE_NAME, result->modelName.chars);
|
||||
ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Battery), result->modelName.chars);
|
||||
} else {
|
||||
ffStrbufSetS(&key, FF_BATTERY_MODULE_NAME);
|
||||
ffStrbufSetS(&key, FF_MODULE_GET_DISPLAY_NAME(Battery));
|
||||
}
|
||||
} else {
|
||||
ffStrbufClear(&key);
|
||||
@@ -170,11 +170,11 @@ bool ffPrintBattery(FFBatteryOptions* options) {
|
||||
const char* error = ffDetectBattery(options, &results);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
if (results.length == 0) {
|
||||
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,8 +297,30 @@ void ffDestroyBatteryOptions(FFBatteryOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBatteryModuleInfo = {
|
||||
.name = FF_BATTERY_MODULE_NAME,
|
||||
.name = "Battery",
|
||||
.description = "Print battery information",
|
||||
.displayName = {
|
||||
.en = "Battery",
|
||||
.ar = "البطارية",
|
||||
.cs = "Baterie",
|
||||
.de = "Akku",
|
||||
.es = "Batería",
|
||||
.fr = "Batterie",
|
||||
.gl = "Batería",
|
||||
.he = "סוללה",
|
||||
.id = "Baterai",
|
||||
.it = "Batteria",
|
||||
.ja = "バッテリー",
|
||||
.ko = "배터리",
|
||||
.pl = "Bateria",
|
||||
.pt = "Bateria",
|
||||
.ru = "Батарея",
|
||||
.tr = "Pil",
|
||||
.uk = "Батарея",
|
||||
.vi = "Pin",
|
||||
.zh_CN = "电池",
|
||||
.zh_TW = "電池",
|
||||
},
|
||||
.initOptions = (void*) ffInitBatteryOptions,
|
||||
.destroyOptions = (void*) ffDestroyBatteryOptions,
|
||||
.parseJsonObject = (void*) ffParseBatteryJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BATTERY_MODULE_NAME "Battery"
|
||||
|
||||
bool ffPrintBattery(FFBatteryOptions* options);
|
||||
void ffInitBatteryOptions(FFBatteryOptions* options);
|
||||
void ffDestroyBatteryOptions(FFBatteryOptions* options);
|
||||
|
||||
+27
-5
@@ -18,12 +18,12 @@ bool ffPrintBios(FFBiosOptions* options) {
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (bios.version.length == 0) {
|
||||
ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "bios_version is not set.");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "bios_version is not set.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ bool ffPrintBios(FFBiosOptions* options) {
|
||||
ffStrbufSetStatic(&bios.type, "Legacy");
|
||||
}
|
||||
|
||||
ffStrbufSetF(&key, FF_BIOS_MODULE_NAME " (%s)", bios.type.chars);
|
||||
ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Bios), bios.type.chars);
|
||||
} else {
|
||||
ffStrbufClear(&key);
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
|
||||
@@ -80,7 +80,7 @@ void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,8 +130,30 @@ void ffDestroyBiosOptions(FFBiosOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBiosModuleInfo = {
|
||||
.name = FF_BIOS_MODULE_NAME,
|
||||
.name = "BIOS",
|
||||
.description = "Print first-stage bootloader information (name, version, release date, etc.)",
|
||||
.displayName = {
|
||||
.en = "BIOS",
|
||||
.ar = "BIOS",
|
||||
.cs = "BIOS",
|
||||
.de = "BIOS",
|
||||
.es = "BIOS",
|
||||
.fr = "BIOS",
|
||||
.gl = "BIOS",
|
||||
.he = "BIOS",
|
||||
.id = "BIOS",
|
||||
.it = "BIOS",
|
||||
.ja = "BIOS",
|
||||
.ko = "BIOS",
|
||||
.pl = "BIOS",
|
||||
.pt = "BIOS",
|
||||
.ru = "BIOS",
|
||||
.tr = "BIOS",
|
||||
.uk = "BIOS",
|
||||
.vi = "BIOS",
|
||||
.zh_CN = "BIOS",
|
||||
.zh_TW = "BIOS",
|
||||
},
|
||||
.initOptions = (void*) ffInitBiosOptions,
|
||||
.destroyOptions = (void*) ffDestroyBiosOptions,
|
||||
.parseJsonObject = (void*) ffParseBiosJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BIOS_MODULE_NAME "BIOS"
|
||||
|
||||
bool ffPrintBios(FFBiosOptions* options);
|
||||
void ffInitBiosOptions(FFBiosOptions* options);
|
||||
void ffDestroyBiosOptions(FFBiosOptions* options);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* device, uint8_t index) {
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
bool showBatteryLevel = device->battery > 0 && device->battery <= 100;
|
||||
@@ -44,7 +44,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de
|
||||
ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs);
|
||||
}
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(device->name, "name"),
|
||||
FF_ARG(device->address, "address"),
|
||||
FF_ARG(device->type, "type"),
|
||||
@@ -60,12 +60,12 @@ bool ffPrintBluetooth(FFBluetoothOptions* options) {
|
||||
const char* error = ffDetectBluetooth(options, &devices);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (devices.length == 0) {
|
||||
ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module)
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,8 +151,30 @@ void ffDestroyBluetoothOptions(FFBluetoothOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBluetoothModuleInfo = {
|
||||
.name = FF_BLUETOOTH_MODULE_NAME,
|
||||
.name = "Bluetooth",
|
||||
.description = "List connected Bluetooth devices",
|
||||
.displayName = {
|
||||
.en = "Bluetooth",
|
||||
.ar = "بلوتوث",
|
||||
.cs = "Bluetooth",
|
||||
.de = "Bluetooth",
|
||||
.es = "Bluetooth",
|
||||
.fr = "Bluetooth",
|
||||
.gl = "Bluetooth",
|
||||
.he = "בלוטות'",
|
||||
.id = "Bluetooth",
|
||||
.it = "Bluetooth",
|
||||
.ja = "ブルートゥース",
|
||||
.ko = "블루투스",
|
||||
.pl = "Bluetooth",
|
||||
.pt = "Bluetooth",
|
||||
.ru = "Bluetooth",
|
||||
.tr = "Bluetooth",
|
||||
.uk = "Bluetooth",
|
||||
.vi = "Bluetooth",
|
||||
.zh_CN = "蓝牙设备",
|
||||
.zh_TW = "藍牙裝置",
|
||||
},
|
||||
.initOptions = (void*) ffInitBluetoothOptions,
|
||||
.destroyOptions = (void*) ffDestroyBluetoothOptions,
|
||||
.parseJsonObject = (void*) ffParseBluetoothJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BLUETOOTH_MODULE_NAME "Bluetooth"
|
||||
|
||||
bool ffPrintBluetooth(FFBluetoothOptions* options);
|
||||
void ffInitBluetoothOptions(FFBluetoothOptions* options);
|
||||
void ffDestroyBluetoothOptions(FFBluetoothOptions* options);
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include "detection/bluetoothradio/bluetoothradio.h"
|
||||
#include "modules/bluetoothradio/bluetoothradio.h"
|
||||
|
||||
#define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio"
|
||||
|
||||
static void destroyBluetoothRadios(FFlist* radios) {
|
||||
FF_LIST_FOR_EACH (FFBluetoothRadioResult, radio, *radios) {
|
||||
ffStrbufDestroy(&radio->name);
|
||||
@@ -18,7 +16,7 @@ static void destroyBluetoothRadios(FFlist* radios) {
|
||||
static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) {
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
if (options->moduleArgs.key.length == 0) {
|
||||
ffStrbufAppendF(&key, "%s (%s)", FF_BLUETOOTHRADIO_DISPLAY_NAME, radio->name.chars);
|
||||
ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), radio->name.chars);
|
||||
} else {
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
|
||||
FF_ARG(index, "index"),
|
||||
@@ -101,7 +99,7 @@ bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) {
|
||||
const char* error = ffDetectBluetoothRadio(&radios);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -117,9 +115,9 @@ bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) {
|
||||
|
||||
if (index == 0) {
|
||||
if (radios.length > 0) {
|
||||
ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled");
|
||||
} else {
|
||||
ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected");
|
||||
}
|
||||
destroyBluetoothRadios(&radios);
|
||||
return false;
|
||||
@@ -137,7 +135,7 @@ void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_va
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +188,30 @@ void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBluetoothRadioModuleInfo = {
|
||||
.name = FF_BLUETOOTHRADIO_MODULE_NAME,
|
||||
.name = "BluetoothRadio",
|
||||
.description = "List Bluetooth radios (supported versions, vendors, etc.)",
|
||||
.displayName = {
|
||||
.en = "Bluetooth Radio",
|
||||
.ar = "راديو بلوتوث",
|
||||
.cs = "Bluetooth rádio",
|
||||
.de = "Bluetooth-Adapter",
|
||||
.es = "Adaptador Bluetooth",
|
||||
.fr = "Adaptateur Bluetooth",
|
||||
.gl = "Adaptador Bluetooth",
|
||||
.he = "רדיו בלוטות'",
|
||||
.id = "Radio Bluetooth",
|
||||
.it = "Adattatore Bluetooth",
|
||||
.ja = "ブルートゥースアダプター",
|
||||
.ko = "블루투스 어댑터",
|
||||
.pl = "Adapter Bluetooth",
|
||||
.pt = "Adaptador Bluetooth",
|
||||
.ru = "Bluetooth-адаптер",
|
||||
.tr = "Bluetooth Radyosu",
|
||||
.uk = "Радіомодуль Bluetooth",
|
||||
.vi = "Radio Bluetooth",
|
||||
.zh_CN = "蓝牙适配器",
|
||||
.zh_TW = "藍牙配接器",
|
||||
},
|
||||
.initOptions = (void*) ffInitBluetoothRadioOptions,
|
||||
.destroyOptions = (void*) ffDestroyBluetoothRadioOptions,
|
||||
.parseJsonObject = (void*) ffParseBluetoothRadioJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio"
|
||||
|
||||
bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options);
|
||||
void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options);
|
||||
void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options);
|
||||
|
||||
@@ -14,24 +14,24 @@ bool ffPrintBoard(FFBoardOptions* options) {
|
||||
|
||||
const char* error = ffDetectBoard(&result);
|
||||
if (error) {
|
||||
ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (result.name.length == 0) {
|
||||
ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "board_name is not set.");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "board_name is not set.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufWriteTo(&result.name, stdout);
|
||||
if (result.version.length) {
|
||||
printf(" (%s)", result.version.chars);
|
||||
}
|
||||
putchar('\n');
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(result.name, "name"),
|
||||
FF_ARG(result.vendor, "vendor"),
|
||||
FF_ARG(result.version, "version"),
|
||||
@@ -56,7 +56,7 @@ void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,8 +108,30 @@ void ffDestroyBoardOptions(FFBoardOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBoardModuleInfo = {
|
||||
.name = FF_BOARD_MODULE_NAME,
|
||||
.name = "Board",
|
||||
.description = "Print motherboard name and other information",
|
||||
.displayName = {
|
||||
.en = "Board",
|
||||
.ar = "اللوحة الأم",
|
||||
.cs = "Základní deska",
|
||||
.de = "Mainboard",
|
||||
.es = "Placa base",
|
||||
.fr = "Carte mère",
|
||||
.gl = "Placa base",
|
||||
.he = "לוח אם",
|
||||
.id = "Papan Induk",
|
||||
.it = "Scheda madre",
|
||||
.ja = "マザーボード",
|
||||
.ko = "메인보드",
|
||||
.pl = "Płyta główna",
|
||||
.pt = "Placa-mãe",
|
||||
.ru = "Материнская плата",
|
||||
.tr = "Anakart",
|
||||
.uk = "Материнська плата",
|
||||
.vi = "Bo mạch chủ",
|
||||
.zh_CN = "主板",
|
||||
.zh_TW = "主機板",
|
||||
},
|
||||
.initOptions = (void*) ffInitBoardOptions,
|
||||
.destroyOptions = (void*) ffDestroyBoardOptions,
|
||||
.parseJsonObject = (void*) ffParseBoardJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BOARD_MODULE_NAME "Board"
|
||||
|
||||
bool ffPrintBoard(FFBoardOptions* options);
|
||||
void ffInitBoardOptions(FFBoardOptions* options);
|
||||
void ffDestroyBoardOptions(FFBoardOptions* options);
|
||||
|
||||
@@ -14,7 +14,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) {
|
||||
const char* error = ffDetectBootmgr(&bootmgr);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
goto exit;
|
||||
} else {
|
||||
FF_STRBUF_AUTO_DESTROY firmwareName = ffStrbufCreateCopy(&bootmgr.firmware);
|
||||
@@ -25,7 +25,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) {
|
||||
#endif
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufWriteTo(&bootmgr.name, stdout);
|
||||
if (firmwareName.length > 0) {
|
||||
printf(" - %s\n", firmwareName.chars);
|
||||
@@ -33,7 +33,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) {
|
||||
putchar('\n');
|
||||
}
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(bootmgr.name, "name"),
|
||||
FF_ARG(bootmgr.firmware, "firmware-path"),
|
||||
FF_ARG(firmwareName, "firmware-name"),
|
||||
@@ -59,7 +59,7 @@ void ffParseBootmgrJsonObject(FFBootmgrOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,8 +103,30 @@ void ffDestroyBootmgrOptions(FFBootmgrOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBootmgrModuleInfo = {
|
||||
.name = FF_BOOTMGR_MODULE_NAME,
|
||||
.name = "Bootmgr",
|
||||
.description = "Print second-stage bootloader information (name, firmware, etc.)",
|
||||
.displayName = {
|
||||
.en = "Boot Manager",
|
||||
.ar = "مدير الإقلاع",
|
||||
.cs = "Správce spouštění",
|
||||
.de = "Boot-Manager",
|
||||
.es = "Gestor de arranque",
|
||||
.fr = "Gestionnaire de démarrage",
|
||||
.gl = "Xestor de arranque",
|
||||
.he = "מנהל אתחול",
|
||||
.id = "Manajer Boot",
|
||||
.it = "Gestore di avvio",
|
||||
.ja = "ブートマネージャー",
|
||||
.ko = "부트 매니저",
|
||||
.pl = "Menedżer rozruchu",
|
||||
.pt = "Gerenciador de inicialização",
|
||||
.ru = "Менеджер загрузки",
|
||||
.tr = "Önyükleme Yöneticisi",
|
||||
.uk = "Менеджер завантаження",
|
||||
.vi = "Trình quản lý khởi động",
|
||||
.zh_CN = "启动管理器",
|
||||
.zh_TW = "啟動管理器",
|
||||
},
|
||||
.initOptions = (void*) ffInitBootmgrOptions,
|
||||
.destroyOptions = (void*) ffDestroyBootmgrOptions,
|
||||
.parseJsonObject = (void*) ffParseBootmgrJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BOOTMGR_MODULE_NAME "Bootmgr"
|
||||
|
||||
bool ffPrintBootmgr(FFBootmgrOptions* options);
|
||||
void ffInitBootmgrOptions(FFBootmgrOptions* options);
|
||||
void ffDestroyBootmgrOptions(FFBootmgrOptions* options);
|
||||
|
||||
@@ -16,7 +16,7 @@ void ffParseBreakJsonObject([[maybe_unused]] FFBreakOptions* options, [[maybe_un
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BREAK_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Break), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,30 @@ void ffDestroyBreakOptions([[maybe_unused]] FFBreakOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBreakModuleInfo = {
|
||||
.name = FF_BREAK_MODULE_NAME,
|
||||
.name = "Break",
|
||||
.description = "Print an empty line",
|
||||
.displayName = {
|
||||
.en = "Break",
|
||||
.ar = "فاصل",
|
||||
.cs = "Konec řádku",
|
||||
.de = "Umbruch",
|
||||
.es = "Salto de línea",
|
||||
.fr = "Saut de ligne",
|
||||
.gl = "Salto de liña",
|
||||
.he = "מעבר שורה",
|
||||
.id = "Baris Baru",
|
||||
.it = "Interruzione",
|
||||
.ja = "改行",
|
||||
.ko = "줄 바꿈",
|
||||
.pl = "Przerwa",
|
||||
.pt = "Quebra",
|
||||
.ru = "Разрыв",
|
||||
.tr = "Satır Sonu",
|
||||
.uk = "Розрив рядка",
|
||||
.vi = "Xuống dòng",
|
||||
.zh_CN = "换行",
|
||||
.zh_TW = "換行",
|
||||
},
|
||||
.initOptions = (void*) ffInitBreakOptions,
|
||||
.destroyOptions = (void*) ffDestroyBreakOptions,
|
||||
.parseJsonObject = (void*) ffParseBreakJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BREAK_MODULE_NAME "Break"
|
||||
|
||||
bool ffPrintBreak(FFBreakOptions* options);
|
||||
void ffInitBreakOptions(FFBreakOptions* options);
|
||||
void ffDestroyBreakOptions(FFBreakOptions* options);
|
||||
|
||||
@@ -11,12 +11,12 @@ bool ffPrintBrightness(FFBrightnessOptions* options) {
|
||||
const char* error = ffDetectBrightness(options, &result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.length == 0) {
|
||||
ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result is detected.");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result is detected.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ bool ffPrintBrightness(FFBrightnessOptions* options) {
|
||||
ffPercentAppendNum(&str, percent, options->percent, false, &options->moduleArgs);
|
||||
}
|
||||
|
||||
ffPrintLogoAndKey(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufPutTo(&str, stdout);
|
||||
return true;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ bool ffPrintBrightness(FFBrightnessOptions* options) {
|
||||
uint32_t index = 0;
|
||||
FF_LIST_FOR_EACH (FFBrightnessResult, item, result) {
|
||||
if (options->moduleArgs.key.length == 0) {
|
||||
ffStrbufAppendF(&key, "%s (%s)", FF_BRIGHTNESS_MODULE_NAME, item->name.chars);
|
||||
ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Brightness), item->name.chars);
|
||||
} else {
|
||||
uint32_t moduleIndex = result.length == 1 ? 0 : index + 1;
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
|
||||
@@ -130,7 +130,7 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +190,30 @@ void ffDestroyBrightnessOptions(FFBrightnessOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBrightnessModuleInfo = {
|
||||
.name = FF_BRIGHTNESS_MODULE_NAME,
|
||||
.name = "Brightness",
|
||||
.description = "Print the current brightness level of your monitors",
|
||||
.displayName = {
|
||||
.en = "Brightness",
|
||||
.ar = "السطوع",
|
||||
.cs = "Jas",
|
||||
.de = "Helligkeit",
|
||||
.es = "Brillo",
|
||||
.fr = "Luminosité",
|
||||
.gl = "Brillo",
|
||||
.he = "בהירות",
|
||||
.id = "Kecerahan",
|
||||
.it = "Luminosità",
|
||||
.ja = "明るさ",
|
||||
.ko = "밝기",
|
||||
.pl = "Jasność",
|
||||
.pt = "Brilho",
|
||||
.ru = "Яркость",
|
||||
.tr = "Parlaklık",
|
||||
.uk = "Яскравість",
|
||||
.vi = "Độ sáng",
|
||||
.zh_CN = "亮度",
|
||||
.zh_TW = "亮度",
|
||||
},
|
||||
.initOptions = (void*) ffInitBrightnessOptions,
|
||||
.destroyOptions = (void*) ffDestroyBrightnessOptions,
|
||||
.parseJsonObject = (void*) ffParseBrightnessJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BRIGHTNESS_MODULE_NAME "Brightness"
|
||||
|
||||
bool ffPrintBrightness(FFBrightnessOptions* options);
|
||||
void ffInitBrightnessOptions(FFBrightnessOptions* options);
|
||||
void ffDestroyBrightnessOptions(FFBrightnessOptions* options);
|
||||
|
||||
@@ -10,9 +10,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (options->moduleArgs.key.length == 0) {
|
||||
if (result->name.length > 0) {
|
||||
ffStrbufSetF(&buffer, "%s (%s)", FF_BTRFS_MODULE_NAME, result->name.chars);
|
||||
ffStrbufSetF(&buffer, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Btrfs), result->name.chars);
|
||||
} else {
|
||||
ffStrbufSetS(&buffer, FF_BTRFS_MODULE_NAME);
|
||||
ffStrbufSetS(&buffer, FF_MODULE_GET_DISPLAY_NAME(Btrfs));
|
||||
}
|
||||
} else {
|
||||
ffStrbufClear(&buffer);
|
||||
@@ -100,11 +100,11 @@ bool ffPrintBtrfs(FFBtrfsOptions* options) {
|
||||
const char* error = ffDetectBtrfs(&results);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
if (results.length == 0) {
|
||||
ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No btrfs drive found");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No btrfs drive found");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ void ffParseBtrfsJsonObject(FFBtrfsOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,8 +198,30 @@ void ffDestroyBtrfsOptions(FFBtrfsOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffBtrfsModuleInfo = {
|
||||
.name = FF_BTRFS_MODULE_NAME,
|
||||
.name = "Btrfs",
|
||||
.description = "Print Linux BTRFS volumes",
|
||||
.displayName = {
|
||||
.en = "BTRFS",
|
||||
.ar = "BTRFS",
|
||||
.cs = "BTRFS",
|
||||
.de = "BTRFS",
|
||||
.es = "BTRFS",
|
||||
.fr = "BTRFS",
|
||||
.gl = "BTRFS",
|
||||
.he = "BTRFS",
|
||||
.id = "BTRFS",
|
||||
.it = "BTRFS",
|
||||
.ja = "BTRFS",
|
||||
.ko = "BTRFS",
|
||||
.pl = "BTRFS",
|
||||
.pt = "BTRFS",
|
||||
.ru = "BTRFS",
|
||||
.tr = "BTRFS",
|
||||
.uk = "BTRFS",
|
||||
.vi = "BTRFS",
|
||||
.zh_CN = "BTRFS",
|
||||
.zh_TW = "BTRFS",
|
||||
},
|
||||
.initOptions = (void*) ffInitBtrfsOptions,
|
||||
.destroyOptions = (void*) ffDestroyBtrfsOptions,
|
||||
.parseJsonObject = (void*) ffParseBtrfsJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_BTRFS_MODULE_NAME "Btrfs"
|
||||
|
||||
bool ffPrintBtrfs(FFBtrfsOptions* options);
|
||||
void ffInitBtrfsOptions(FFBtrfsOptions* options);
|
||||
void ffDestroyBtrfsOptions(FFBtrfsOptions* options);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
static void printDevice(FFCameraOptions* options, const FFCameraResult* device, uint8_t index) {
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
ffStrbufWriteTo(&device->name, stdout);
|
||||
if (device->colorspace.length > 0) {
|
||||
@@ -19,7 +19,7 @@ static void printDevice(FFCameraOptions* options, const FFCameraResult* device,
|
||||
putchar('\n');
|
||||
}
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) {
|
||||
FF_ARG(device->name, "name"),
|
||||
FF_ARG(device->vendor, "vendor"),
|
||||
FF_ARG(device->colorspace, "colorspace"),
|
||||
@@ -35,12 +35,12 @@ bool ffPrintCamera(FFCameraOptions* options) {
|
||||
const char* error = ffDetectCamera(&result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.length == 0) {
|
||||
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +115,30 @@ void ffDestroyCameraOptions(FFCameraOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCameraModuleInfo = {
|
||||
.name = FF_CAMERA_MODULE_NAME,
|
||||
.name = "Camera",
|
||||
.description = "Print available cameras",
|
||||
.displayName = {
|
||||
.en = "Camera",
|
||||
.ar = "الكاميرا",
|
||||
.cs = "Kamera",
|
||||
.de = "Kamera",
|
||||
.es = "Cámara",
|
||||
.fr = "Caméra",
|
||||
.gl = "Cámara",
|
||||
.he = "מצלמה",
|
||||
.id = "Kamera",
|
||||
.it = "Fotocamera",
|
||||
.ja = "カメラ",
|
||||
.ko = "카메라",
|
||||
.pl = "Kamera",
|
||||
.pt = "Câmera",
|
||||
.ru = "Камера",
|
||||
.tr = "Kamera",
|
||||
.uk = "Камера",
|
||||
.vi = "Máy ảnh",
|
||||
.zh_CN = "摄像头",
|
||||
.zh_TW = "攝像頭",
|
||||
},
|
||||
.initOptions = (void*) ffInitCameraOptions,
|
||||
.destroyOptions = (void*) ffDestroyCameraOptions,
|
||||
.parseJsonObject = (void*) ffParseCameraJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CAMERA_MODULE_NAME "Camera"
|
||||
|
||||
bool ffPrintCamera(FFCameraOptions* options);
|
||||
void ffInitCameraOptions(FFCameraOptions* options);
|
||||
void ffDestroyCameraOptions(FFCameraOptions* options);
|
||||
|
||||
@@ -16,24 +16,24 @@ bool ffPrintChassis(FFChassisOptions* options) {
|
||||
const char* error = ffDetectChassis(&result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (result.type.length == 0) {
|
||||
ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "chassis_type is not set by O.E.M.");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "chassis_type is not set by O.E.M.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufWriteTo(&result.type, stdout);
|
||||
if (result.version.length) {
|
||||
printf(" (%s)", result.version.chars);
|
||||
}
|
||||
putchar('\n');
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(result.type, "type"),
|
||||
FF_ARG(result.vendor, "vendor"),
|
||||
FF_ARG(result.version, "version"),
|
||||
@@ -58,7 +58,7 @@ void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,8 +110,30 @@ void ffDestroyChassisOptions(FFChassisOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffChassisModuleInfo = {
|
||||
.name = FF_CHASSIS_MODULE_NAME,
|
||||
.name = "Chassis",
|
||||
.description = "Print chassis type information (desktop, laptop, etc.)",
|
||||
.displayName = {
|
||||
.en = "Chassis",
|
||||
.ar = "الهيكل",
|
||||
.cs = "Skříň",
|
||||
.de = "Gehäuse",
|
||||
.es = "Chasis",
|
||||
.fr = "Châssis",
|
||||
.gl = "Chasis",
|
||||
.he = "מארז",
|
||||
.id = "Casing",
|
||||
.it = "Telaio",
|
||||
.ja = "シャーシ",
|
||||
.ko = "섀시",
|
||||
.pl = "Obudowa",
|
||||
.pt = "Chassi",
|
||||
.ru = "Корпус",
|
||||
.tr = "Kasa",
|
||||
.uk = "Корпус",
|
||||
.vi = "Vỏ máy",
|
||||
.zh_CN = "机箱",
|
||||
.zh_TW = "機箱",
|
||||
},
|
||||
.initOptions = (void*) ffInitChassisOptions,
|
||||
.destroyOptions = (void*) ffDestroyChassisOptions,
|
||||
.parseJsonObject = (void*) ffParseChassisJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CHASSIS_MODULE_NAME "Chassis"
|
||||
|
||||
bool ffPrintChassis(FFChassisOptions* options);
|
||||
void ffInitChassisOptions(FFChassisOptions* options);
|
||||
void ffDestroyChassisOptions(FFChassisOptions* options);
|
||||
|
||||
@@ -51,9 +51,9 @@ static void printCodecLine(const FFCodecOptions* options, uint8_t index, FFstrbu
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
if (options->moduleArgs.key.length == 0) {
|
||||
if (gpu->length > 0) {
|
||||
ffStrbufSetF(&key, "%s (%s - %s)", FF_CODEC_MODULE_NAME, direction, gpu->chars);
|
||||
ffStrbufSetF(&key, "%s (%s - %s)", FF_MODULE_GET_DISPLAY_NAME(Codec), direction, gpu->chars);
|
||||
} else {
|
||||
ffStrbufSetF(&key, "%s (%s)", FF_CODEC_MODULE_NAME, direction);
|
||||
ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Codec), direction);
|
||||
}
|
||||
} else {
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]){
|
||||
@@ -100,12 +100,12 @@ bool ffPrintCodec(FFCodecOptions* options) {
|
||||
const char* error = ffDetectCodec(options, &result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.length == 0) {
|
||||
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -174,14 +174,14 @@ void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) {
|
||||
{},
|
||||
});
|
||||
if (error) {
|
||||
ffPrintError(FF_CODEC_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
} else {
|
||||
options->showType = (FFCodecShowType) value;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,8 +251,30 @@ void ffDestroyCodecOptions(FFCodecOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCodecModuleInfo = {
|
||||
.name = FF_CODEC_MODULE_NAME,
|
||||
.name = "Codec",
|
||||
.description = "Print hardware video acceleration codec types (decode / encode)",
|
||||
.displayName = {
|
||||
.en = "Codec",
|
||||
.ar = "الترميز",
|
||||
.cs = "Kodek",
|
||||
.de = "Codec",
|
||||
.es = "Códec",
|
||||
.fr = "Codec",
|
||||
.gl = "Códec",
|
||||
.he = "קודק",
|
||||
.id = "Kodek",
|
||||
.it = "Codec",
|
||||
.ja = "コーデック",
|
||||
.ko = "코덱",
|
||||
.pl = "Kodek",
|
||||
.pt = "Codec",
|
||||
.ru = "Кодек",
|
||||
.tr = "Kodek",
|
||||
.uk = "Кодек",
|
||||
.vi = "Codec",
|
||||
.zh_CN = "编解码器",
|
||||
.zh_TW = "編解碼器",
|
||||
},
|
||||
.initOptions = (void*) ffInitCodecOptions,
|
||||
.destroyOptions = (void*) ffDestroyCodecOptions,
|
||||
.parseJsonObject = (void*) ffParseCodecJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CODEC_MODULE_NAME "Codec"
|
||||
|
||||
bool ffPrintCodec(FFCodecOptions* options);
|
||||
void ffInitCodecOptions(FFCodecOptions* options);
|
||||
void ffDestroyCodecOptions(FFCodecOptions* options);
|
||||
|
||||
+33
-11
@@ -37,7 +37,7 @@ bool ffPrintColors(FFColorsOptions* options) {
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
flag = true;
|
||||
|
||||
if (options->paddingLeft > 0) {
|
||||
@@ -122,7 +122,7 @@ bool ffPrintColors(FFColorsOptions* options) {
|
||||
if (flag) {
|
||||
ffLogoPrintLine();
|
||||
} else {
|
||||
ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
flag = true;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ bool ffPrintColors(FFColorsOptions* options) {
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Nothing to print");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Nothing to print");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) {
|
||||
{},
|
||||
});
|
||||
if (error) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
} else {
|
||||
options->symbol = (FFColorsSymbol) value;
|
||||
}
|
||||
@@ -178,7 +178,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) {
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "block")) {
|
||||
if (!yyjson_is_obj(val)) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key));
|
||||
} else {
|
||||
yyjson_val* width = yyjson_obj_get(val, "width");
|
||||
if (width) {
|
||||
@@ -188,14 +188,14 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) {
|
||||
yyjson_val* range = yyjson_obj_get(val, "range");
|
||||
if (range) {
|
||||
if (!yyjson_is_arr(range) || yyjson_arr_size(range) != 2) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key));
|
||||
} else {
|
||||
uint8_t start = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 0));
|
||||
uint8_t end = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 1));
|
||||
if (start > end) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key));
|
||||
} else if (end > 15) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key));
|
||||
} else {
|
||||
options->block.range[0] = start;
|
||||
options->block.range[1] = end;
|
||||
@@ -215,14 +215,14 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) {
|
||||
{},
|
||||
});
|
||||
if (error) {
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
} else {
|
||||
options->brightness = (FFColorsBrightness) value;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,8 +295,30 @@ void ffDestroyColorsOptions(FFColorsOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffColorsModuleInfo = {
|
||||
.name = FF_COLORS_MODULE_NAME,
|
||||
.name = "Colors",
|
||||
.description = "Display the terminal's 16-color palette",
|
||||
.displayName = {
|
||||
.en = "Colors",
|
||||
.ar = "الألوان",
|
||||
.cs = "Barvy",
|
||||
.de = "Farben",
|
||||
.es = "Colores",
|
||||
.fr = "Couleurs",
|
||||
.gl = "Cores",
|
||||
.he = "צבעים",
|
||||
.id = "Warna",
|
||||
.it = "Colori",
|
||||
.ja = "色",
|
||||
.ko = "색상",
|
||||
.pl = "Kolory",
|
||||
.pt = "Cores",
|
||||
.ru = "Цвета",
|
||||
.tr = "Renkler",
|
||||
.uk = "Кольори",
|
||||
.vi = "Màu sắc",
|
||||
.zh_CN = "颜色",
|
||||
.zh_TW = "顏色",
|
||||
},
|
||||
.initOptions = (void*) ffInitColorsOptions,
|
||||
.destroyOptions = (void*) ffDestroyColorsOptions,
|
||||
.parseJsonObject = (void*) ffParseColorsJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_COLORS_MODULE_NAME "Colors"
|
||||
|
||||
bool ffPrintColors(FFColorsOptions* options);
|
||||
void ffInitColorsOptions(FFColorsOptions* options);
|
||||
void ffDestroyColorsOptions(FFColorsOptions* options);
|
||||
|
||||
@@ -8,12 +8,12 @@ bool ffPrintCommand(FFCommandOptions* options) {
|
||||
const char* error = ffDetectCommand(options, &result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!result.length) {
|
||||
ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result generated");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result generated");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -23,18 +23,18 @@ bool ffPrintCommand(FFCommandOptions* options) {
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &result)) {
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Command), ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
puts(line);
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(line, "result") }));
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Command), ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(line, "result") }));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result") }));
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result") }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +153,30 @@ void ffDestroyCommandOptions(FFCommandOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCommandModuleInfo = {
|
||||
.name = FF_COMMAND_MODULE_NAME,
|
||||
.name = "Command",
|
||||
.description = "Run custom shell scripts",
|
||||
.displayName = {
|
||||
.en = "Command",
|
||||
.ar = "الأمر",
|
||||
.cs = "Příkaz",
|
||||
.de = "Befehl",
|
||||
.es = "Comando",
|
||||
.fr = "Commande",
|
||||
.gl = "Comando",
|
||||
.he = "פקודה",
|
||||
.id = "Perintah",
|
||||
.it = "Comando",
|
||||
.ja = "コマンド",
|
||||
.ko = "명령어",
|
||||
.pl = "Polecenie",
|
||||
.pt = "Comando",
|
||||
.ru = "Команда",
|
||||
.tr = "Komut",
|
||||
.uk = "Команда",
|
||||
.vi = "Lệnh",
|
||||
.zh_CN = "命令",
|
||||
.zh_TW = "命令",
|
||||
},
|
||||
.initOptions = (void*) ffInitCommandOptions,
|
||||
.destroyOptions = (void*) ffDestroyCommandOptions,
|
||||
.parseJsonObject = (void*) ffParseCommandJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_COMMAND_MODULE_NAME "Command"
|
||||
|
||||
bool ffPrepareCommand(FFCommandOptions* options);
|
||||
|
||||
bool ffPrintCommand(FFCommandOptions* options);
|
||||
|
||||
+29
-7
@@ -23,9 +23,9 @@ bool ffPrintCPU(FFCPUOptions* options) {
|
||||
const char* error = ffDetectCPU(options, &cpu);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
} else if (cpu.vendor.length == 0 && cpu.name.length == 0 && cpu.coresOnline <= 1) {
|
||||
ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No CPU detected");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No CPU detected");
|
||||
} else {
|
||||
FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate();
|
||||
if (options->showPeCoreCount) {
|
||||
@@ -43,7 +43,7 @@ bool ffPrintCPU(FFCPUOptions* options) {
|
||||
}
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate();
|
||||
|
||||
@@ -85,7 +85,7 @@ bool ffPrintCPU(FFCPUOptions* options) {
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
|
||||
ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(cpu.name, "name"),
|
||||
FF_ARG(cpu.vendor, "vendor"),
|
||||
FF_ARG(cpu.coresPhysical, "cores-physical"),
|
||||
@@ -131,7 +131,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) {
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "freqNdigits")) {
|
||||
ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,8 +251,30 @@ void ffDestroyCPUOptions(FFCPUOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCPUModuleInfo = {
|
||||
.name = FF_CPU_MODULE_NAME,
|
||||
.name = "CPU",
|
||||
.description = "Print CPU name, frequency, etc.",
|
||||
.displayName = {
|
||||
.en = "CPU",
|
||||
.ar = "المعالج",
|
||||
.cs = "CPU",
|
||||
.de = "CPU",
|
||||
.es = "CPU",
|
||||
.fr = "CPU",
|
||||
.gl = "CPU",
|
||||
.he = "מעבד",
|
||||
.id = "CPU",
|
||||
.it = "CPU",
|
||||
.ja = "CPU",
|
||||
.ko = "CPU",
|
||||
.pl = "CPU",
|
||||
.pt = "CPU",
|
||||
.ru = "Процессор",
|
||||
.tr = "CPU",
|
||||
.uk = "CPU",
|
||||
.vi = "CPU",
|
||||
.zh_CN = "CPU",
|
||||
.zh_TW = "CPU",
|
||||
},
|
||||
.initOptions = (void*) ffInitCPUOptions,
|
||||
.destroyOptions = (void*) ffDestroyCPUOptions,
|
||||
.parseJsonObject = (void*) ffParseCPUJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CPU_MODULE_NAME "CPU"
|
||||
|
||||
bool ffPrintCPU(FFCPUOptions* options);
|
||||
void ffInitCPUOptions(FFCPUOptions* options);
|
||||
void ffDestroyCPUOptions(FFCPUOptions* options);
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include "detection/cpucache/cpucache.h"
|
||||
#include "modules/cpucache/cpucache.h"
|
||||
|
||||
#define FF_CPUCACHE_DISPLAY_NAME "CPU Cache"
|
||||
|
||||
static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOptions* options) {
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
@@ -16,7 +14,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption
|
||||
ffStrbufClear(&key);
|
||||
levelStr[1] = (char) ('1' + i);
|
||||
if (options->moduleArgs.key.length == 0) {
|
||||
ffStrbufAppendF(&key, "%s (%s)", FF_CPUCACHE_DISPLAY_NAME, levelStr);
|
||||
ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(CPUCache), levelStr);
|
||||
} else {
|
||||
uint32_t index = i + 1;
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
|
||||
@@ -88,12 +86,12 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio
|
||||
}
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
} else {
|
||||
FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate();
|
||||
ffSizeAppendNum(sum, &buffer2);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(buffer, "result"),
|
||||
FF_ARG(buffer2, "sum"),
|
||||
}));
|
||||
@@ -114,7 +112,7 @@ bool ffPrintCPUCache(FFCPUCacheOptions* options) {
|
||||
const char* error = ffDetectCPUCache(&result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -147,7 +145,7 @@ void ffParseCPUCacheJsonObject(FFCPUCacheOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,8 +221,30 @@ void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCPUCacheModuleInfo = {
|
||||
.name = FF_CPUCACHE_MODULE_NAME,
|
||||
.name = "CPUCache",
|
||||
.description = "Print CPU cache sizes",
|
||||
.displayName = {
|
||||
.en = "CPU Cache",
|
||||
.ar = "ذاكرة المعالج المؤقتة",
|
||||
.cs = "Mezipaměť CPU",
|
||||
.de = "CPU-Cache",
|
||||
.es = "Caché de la CPU",
|
||||
.fr = "Cache CPU",
|
||||
.gl = "Caché da CPU",
|
||||
.he = "מטמון מעבד",
|
||||
.id = "Cache CPU",
|
||||
.it = "Cache CPU",
|
||||
.ja = "CPUキャッシュ",
|
||||
.ko = "CPU 캐시",
|
||||
.pl = "Pamięć podręczna CPU",
|
||||
.pt = "Cache da CPU",
|
||||
.ru = "Кэш процессора",
|
||||
.tr = "CPU Önbelleği",
|
||||
.uk = "Кеш ЦП",
|
||||
.vi = "Bộ nhớ đệm CPU",
|
||||
.zh_CN = "CPU缓存",
|
||||
.zh_TW = "CPU快取記憶體",
|
||||
},
|
||||
.initOptions = (void*) ffInitCPUCacheOptions,
|
||||
.destroyOptions = (void*) ffDestroyCPUCacheOptions,
|
||||
.parseJsonObject = (void*) ffParseCPUCacheJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CPUCACHE_MODULE_NAME "CPUCache"
|
||||
|
||||
bool ffPrintCPUCache(FFCPUCacheOptions* options);
|
||||
void ffInitCPUCacheOptions(FFCPUCacheOptions* options);
|
||||
void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options);
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
#include "detection/cpuusage/cpuusage.h"
|
||||
#include "modules/cpuusage/cpuusage.h"
|
||||
|
||||
#define FF_CPUUSAGE_DISPLAY_NAME "CPU Usage"
|
||||
|
||||
bool ffPrintCPUUsage(FFCPUUsageOptions* options) {
|
||||
FF_LIST_AUTO_DESTROY percentages = ffListCreate();
|
||||
const char* error = ffGetCpuUsageResult(options, &percentages);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -54,7 +52,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options) {
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate();
|
||||
if (!options->separate) {
|
||||
@@ -102,7 +100,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options) {
|
||||
ffPercentAppendBar(&maxBar, maxValue, options->percent, &options->moduleArgs);
|
||||
}
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(avgNum, "avg"),
|
||||
FF_ARG(maxNum, "max"),
|
||||
FF_ARG(maxIndex, "max-index"),
|
||||
@@ -139,7 +137,7 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,8 +179,30 @@ void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCPUUsageModuleInfo = {
|
||||
.name = FF_CPUUSAGE_MODULE_NAME,
|
||||
.name = "CPUUsage",
|
||||
.description = "Print CPU usage. Collecting data takes some time",
|
||||
.displayName = {
|
||||
.en = "CPU Usage",
|
||||
.ar = "استخدام المعالج",
|
||||
.cs = "Využití CPU",
|
||||
.de = "CPU-Auslastung",
|
||||
.es = "Uso de la CPU",
|
||||
.fr = "Utilisation du CPU",
|
||||
.gl = "Uso da CPU",
|
||||
.he = "שימוש במעבד",
|
||||
.id = "Penggunaan CPU",
|
||||
.it = "Utilizzo della CPU",
|
||||
.ja = "CPU使用率",
|
||||
.ko = "CPU 사용량",
|
||||
.pl = "Użycie CPU",
|
||||
.pt = "Uso da CPU",
|
||||
.ru = "Использование процессора",
|
||||
.tr = "CPU Kullanımı",
|
||||
.uk = "Використання ЦП",
|
||||
.vi = "Mức sử dụng CPU",
|
||||
.zh_CN = "CPU使用率",
|
||||
.zh_TW = "CPU使用率",
|
||||
},
|
||||
.initOptions = (void*) ffInitCPUUsageOptions,
|
||||
.destroyOptions = (void*) ffDestroyCPUUsageOptions,
|
||||
.parseJsonObject = (void*) ffParseCPUUsageJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CPUUSAGE_MODULE_NAME "CPUUsage"
|
||||
|
||||
void ffPrepareCPUUsage();
|
||||
|
||||
bool ffPrintCPUUsage(FFCPUUsageOptions* options);
|
||||
|
||||
@@ -14,7 +14,7 @@ bool ffPrintCursor(FFCursorOptions* options) {
|
||||
ffDetectCursor(&result);
|
||||
|
||||
if (result.error.length) {
|
||||
ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result.error.chars);
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result.error.chars);
|
||||
} else {
|
||||
ffStrbufRemoveIgnCaseEndS(&result.theme, "cursors");
|
||||
ffStrbufRemoveIgnCaseEndS(&result.theme, "cursor");
|
||||
@@ -25,7 +25,7 @@ bool ffPrintCursor(FFCursorOptions* options) {
|
||||
}
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufWriteTo(&result.theme, stdout);
|
||||
|
||||
if (result.size.length > 0 && !ffStrbufEqualS(&result.size, "0")) {
|
||||
@@ -34,7 +34,7 @@ bool ffPrintCursor(FFCursorOptions* options) {
|
||||
|
||||
putchar('\n');
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
|
||||
FF_ARG(result.theme, "theme"),
|
||||
FF_ARG(result.size, "size"),
|
||||
}));
|
||||
@@ -58,7 +58,7 @@ void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +100,30 @@ void ffDestroyCursorOptions(FFCursorOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCursorModuleInfo = {
|
||||
.name = FF_CURSOR_MODULE_NAME,
|
||||
.name = "Cursor",
|
||||
.description = "Print cursor style name",
|
||||
.displayName = {
|
||||
.en = "Cursor",
|
||||
.ar = "المؤشر",
|
||||
.cs = "Kurzor",
|
||||
.de = "Mauszeiger",
|
||||
.es = "Cursor",
|
||||
.fr = "Curseur",
|
||||
.gl = "Cursor",
|
||||
.he = "סמן",
|
||||
.id = "Kursor",
|
||||
.it = "Cursore",
|
||||
.ja = "カーソル",
|
||||
.ko = "커서",
|
||||
.pl = "Kursor",
|
||||
.pt = "Cursor",
|
||||
.ru = "Курсор",
|
||||
.tr = "İmleç",
|
||||
.uk = "Курсор",
|
||||
.vi = "Con trỏ",
|
||||
.zh_CN = "光标",
|
||||
.zh_TW = "游標",
|
||||
},
|
||||
.initOptions = (void*) ffInitCursorOptions,
|
||||
.destroyOptions = (void*) ffDestroyCursorOptions,
|
||||
.parseJsonObject = (void*) ffParseCursorJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CURSOR_MODULE_NAME "Cursor"
|
||||
|
||||
bool ffPrintCursor(FFCursorOptions* options);
|
||||
void ffInitCursorOptions(FFCursorOptions* options);
|
||||
void ffDestroyCursorOptions(FFCursorOptions* options);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "modules/custom/custom.h"
|
||||
|
||||
bool ffPrintCustom(FFCustomOptions* options) {
|
||||
ffPrintFormat(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {}));
|
||||
ffPrintFormat(FF_MODULE_GET_DISPLAY_NAME(Custom), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {}));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void ffParseCustomJsonObject(FFCustomOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Custom), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,29 @@ void ffDestroyCustomOptions(FFCustomOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCustomModuleInfo = {
|
||||
.name = FF_CUSTOM_MODULE_NAME,
|
||||
.name = "Custom",
|
||||
.description = "Print a custom string, with or without key",
|
||||
.displayName = {
|
||||
.en = "Custom",
|
||||
.ar = "مخصص",
|
||||
.cs = "Vlastní",
|
||||
.de = "Benutzerdefiniert",
|
||||
.es = "Personalizado",
|
||||
.fr = "Personnalisé",
|
||||
.he = "מותאם אישית",
|
||||
.id = "Kustom",
|
||||
.it = "Personalizzato",
|
||||
.ja = "カスタム",
|
||||
.ko = "사용자 정의",
|
||||
.pl = "Niestandardowy",
|
||||
.pt = "Personalizado",
|
||||
.ru = "Пользовательский",
|
||||
.tr = "Özel",
|
||||
.uk = "Власний",
|
||||
.vi = "Tùy chỉnh",
|
||||
.zh_CN = "自定义",
|
||||
.zh_TW = "自訂",
|
||||
},
|
||||
.initOptions = (void*) ffInitCustomOptions,
|
||||
.destroyOptions = (void*) ffDestroyCustomOptions,
|
||||
.parseJsonObject = (void*) ffParseCustomJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_CUSTOM_MODULE_NAME "Custom"
|
||||
|
||||
bool ffPrintCustom(FFCustomOptions* options);
|
||||
void ffInitCustomOptions(FFCustomOptions* options);
|
||||
void ffDestroyCustomOptions(FFCustomOptions* options);
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format
|
||||
|
||||
#define FF_DATETIME_DISPLAY_NAME "Date & Time"
|
||||
|
||||
typedef struct FFDateTimeResult {
|
||||
// Examples for 21.02.2022 - 15:18:37
|
||||
uint16_t year; // 2022
|
||||
@@ -67,7 +65,7 @@ static void printDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) {
|
||||
strftime(result.amPm, sizeof(result.amPm), "%p", tm);
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(
|
||||
FF_DATETIME_DISPLAY_NAME,
|
||||
FF_MODULE_GET_DISPLAY_NAME(DateTime),
|
||||
0,
|
||||
moduleArgs,
|
||||
FF_PRINT_TYPE_DEFAULT,
|
||||
@@ -112,11 +110,11 @@ bool ffPrintDateTime(FFDateTimeOptions* options) {
|
||||
char buffer[32];
|
||||
if (strftime(buffer, ARRAY_SIZE(buffer), "%F %T", tm) == 0) // yyyy-MM-dd HH:mm:ss
|
||||
{
|
||||
ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "strftime() failed");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "strftime() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
ffPrintLogoAndKey(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
puts(buffer);
|
||||
return true;
|
||||
@@ -130,7 +128,7 @@ void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,8 +150,30 @@ void ffDestroyDateTimeOptions(FFDateTimeOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffDateTimeModuleInfo = {
|
||||
.name = FF_DATETIME_MODULE_NAME,
|
||||
.name = "DateTime",
|
||||
.description = "Print the current date and time",
|
||||
.displayName = {
|
||||
.en = "Date & Time",
|
||||
.ar = "التاريخ والوقت",
|
||||
.cs = "Datum a čas",
|
||||
.de = "Datum & Uhrzeit",
|
||||
.es = "Fecha y hora",
|
||||
.fr = "Date et heure",
|
||||
.gl = "Data e hora",
|
||||
.he = "תאריך ושעה",
|
||||
.id = "Tanggal & Waktu",
|
||||
.it = "Data e ora",
|
||||
.ja = "日付と時刻",
|
||||
.ko = "날짜/시간",
|
||||
.pl = "Data i godzina",
|
||||
.pt = "Data e hora",
|
||||
.ru = "Дата и время",
|
||||
.tr = "Tarih ve Saat",
|
||||
.uk = "Дата й час",
|
||||
.vi = "Ngày giờ",
|
||||
.zh_CN = "日期时间",
|
||||
.zh_TW = "日期時間",
|
||||
},
|
||||
.initOptions = (void*) ffInitDateTimeOptions,
|
||||
.destroyOptions = (void*) ffDestroyDateTimeOptions,
|
||||
.parseJsonObject = (void*) ffParseDateTimeJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_DATETIME_MODULE_NAME "DateTime"
|
||||
|
||||
bool ffPrintDateTime(FFDateTimeOptions* options);
|
||||
void ffInitDateTimeOptions(FFDateTimeOptions* options);
|
||||
void ffDestroyDateTimeOptions(FFDateTimeOptions* options);
|
||||
|
||||
+28
-6
@@ -9,7 +9,7 @@ bool ffPrintDE(FFDEOptions* options) {
|
||||
const FFDisplayServerResult* result = ffConnectDisplayServer();
|
||||
|
||||
if (result->dePrettyName.length == 0) {
|
||||
ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No DE found");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No DE found");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ bool ffPrintDE(FFDEOptions* options) {
|
||||
ffDetectDEVersion(&result->dePrettyName, &version, options);
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
ffStrbufWriteTo(&result->dePrettyName, stdout);
|
||||
|
||||
@@ -28,7 +28,7 @@ bool ffPrintDE(FFDEOptions* options) {
|
||||
|
||||
putchar('\n');
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->deProcessName, "process-name"), FF_ARG(result->dePrettyName, "pretty-name"), FF_ARG(version, "version") }));
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->deProcessName, "process-name"), FF_ARG(result->dePrettyName, "pretty-name"), FF_ARG(version, "version") }));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -43,11 +43,11 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module) {
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "slowVersionDetection")) {
|
||||
ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true");
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true");
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,30 @@ void ffDestroyDEOptions(FFDEOptions* options) {
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffDEModuleInfo = {
|
||||
.name = FF_DE_MODULE_NAME,
|
||||
.name = "DE",
|
||||
.description = "Print desktop environment name",
|
||||
.displayName = {
|
||||
.en = "Desktop Environment",
|
||||
.ar = "بيئة سطح المكتب",
|
||||
.cs = "Pracovní prostředí",
|
||||
.de = "Desktop-Umgebung",
|
||||
.es = "Entorno de escritorio",
|
||||
.fr = "Environnement de Bureau",
|
||||
.gl = "Contorno do Escritorio",
|
||||
.he = "סביבת שולחן עבודה",
|
||||
.id = "Lingkungan Desktop",
|
||||
.it = "Ambiente Desktop",
|
||||
.ja = "デスクトップ環境",
|
||||
.ko = "데스크탑 환경",
|
||||
.pl = "Środowisko graficzne",
|
||||
.pt = "Ambiente de desktop",
|
||||
.ru = "Рабочее окружение",
|
||||
.tr = "Masaüstü Ortamı",
|
||||
.uk = "Стільниче середовище",
|
||||
.vi = "Môi trường desktop",
|
||||
.zh_CN = "桌面环境",
|
||||
.zh_TW = "桌面環境",
|
||||
},
|
||||
.initOptions = (void*) ffInitDEOptions,
|
||||
.destroyOptions = (void*) ffDestroyDEOptions,
|
||||
.parseJsonObject = (void*) ffParseDEJsonObject,
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "option.h"
|
||||
|
||||
#define FF_DE_MODULE_NAME "DE"
|
||||
|
||||
bool ffPrintDE(FFDEOptions* options);
|
||||
void ffInitDEOptions(FFDEOptions* options);
|
||||
void ffDestroyDEOptions(FFDEOptions* options);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user