mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 02aafbd7f4 | |||
| 72da8150bd | |||
| aca2b5336d | |||
| c79b67efc1 | |||
| 30af91ce8e | |||
| 6c56348e54 | |||
| 531b25dc2f | |||
| 8c6dc34654 | |||
| cf2034b93e | |||
| f7db03b8c4 | |||
| 8647e366f9 | |||
| 1bf41d68f9 | |||
| 1ac1f1f889 | |||
| 14f1278485 | |||
| c2c6856159 | |||
| c89f3d2896 | |||
| 8e773470df | |||
| ea4fc7bdda | |||
| 468d1e0903 | |||
| 6851e7b082 | |||
| a734f18fd5 | |||
| 30b1e29785 | |||
| dde0c22195 | |||
| 1311a809db | |||
| 60a54f4880 | |||
| b4e65e7e48 | |||
| 6f3ed4a7b4 | |||
| cc8f8ff0f7 | |||
| 8a00f2d901 | |||
| c5c0e543e4 | |||
| 97255f37da | |||
| fb8a04f97a | |||
| c3ce5ac947 | |||
| eae69049b2 | |||
| 102e8fcc72 | |||
| 8372708f98 | |||
| 5011edc9d9 | |||
| 94a5228ffc | |||
| 382c0cd7c3 | |||
| ab496b23b7 | |||
| 939f428da7 | |||
| 2d496c91e1 | |||
| 442d58b646 | |||
| 4d377b94b7 | |||
| 7248868e33 | |||
| 2eda6464ad | |||
| 2622fc12a6 | |||
| b178e43428 | |||
| d00fca26c5 | |||
| 23e4d1c4aa | |||
| 6871c8bb73 | |||
| 61adc7cf64 | |||
| 9ba30adcba | |||
| 010b2c6262 | |||
| c65fb1a868 | |||
| 2029679ea5 | |||
| 817f70c2cd | |||
| 3a1f0485f4 | |||
| 64910d0781 | |||
| 821462e152 | |||
| b015fd579c | |||
| 8b40a81e22 | |||
| 8be64714ba | |||
| fe5d739cba | |||
| dba0672a11 | |||
| 3ed6acf3ca | |||
| 8c74c54bb0 | |||
| 818473102c | |||
| f1cc4a7805 | |||
| c574af97a4 | |||
| 74ae84e719 | |||
| 98738b6920 | |||
| 2e5769def2 | |||
| 18a6929662 | |||
| 0e61d1134d | |||
| 4abb183735 | |||
| d5b56be4ff | |||
| 1854953d8c | |||
| 2406015c81 | |||
| ec7f14ab96 | |||
| d94cdf4424 | |||
| 40e57b7698 | |||
| 974c658fff | |||
| ad0ddfd7f1 | |||
| 1da8367f55 | |||
| bdbc885811 | |||
| 86e5a5997b | |||
| 9832a0e45b | |||
| addf674621 | |||
| 863c5583ef | |||
| 45cbc6de83 | |||
| e68f766b4d | |||
| 29d7a1acac | |||
| 8d59d14b80 | |||
| ed1883909a | |||
| 049701a8a9 | |||
| 13b7bc89eb | |||
| 92fe44183d | |||
| 8ebc980c17 | |||
| dbeb338bda | |||
| 65ff11a8d0 | |||
| 7a73211484 | |||
| ca049997b1 | |||
| a9f021ccb9 | |||
| 55249c2294 | |||
| c13da56959 | |||
| 665c7cd5d3 |
@@ -552,7 +552,7 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '14.2'
|
||||
version: '14.3'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
@@ -683,7 +683,6 @@ jobs:
|
||||
haiku-amd64:
|
||||
name: Haiku-amd64
|
||||
runs-on: ubuntu-latest
|
||||
if: false
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -691,17 +690,45 @@ jobs:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Fixup VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
sync_files: false
|
||||
shutdown_vm: false
|
||||
run: |
|
||||
mv '/home/runner/work' '/boot/home/work'
|
||||
ln -sf '/boot/home/work' '/home/runner/work'
|
||||
|
||||
- name: Sync files to VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
sync_files: runner-to-vm
|
||||
shutdown_vm: false
|
||||
run: |
|
||||
chown -R $(id -u):$(id -g) $(pwd)
|
||||
ls -l
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: 'r1beta5'
|
||||
sync_files: vm-to-runner
|
||||
run: |
|
||||
uname -a
|
||||
ls -l
|
||||
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
@@ -709,7 +736,6 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -861,6 +887,7 @@ jobs:
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- sunos-amd64
|
||||
- haiku-amd64
|
||||
- windows-amd64
|
||||
- windows-aarch64
|
||||
permissions:
|
||||
|
||||
+88
-1
@@ -1,3 +1,90 @@
|
||||
# 2.48.1
|
||||
|
||||
Features:
|
||||
* Add support for detecting Openbox WM version (WM, Linux)
|
||||
* Improve reliability of child process spawning on Windows (Windows)
|
||||
* Add a new option `--packages-combined`, which combines related package managers into single counts (#1851, Packages)
|
||||
* For example: if you have both `flatpak-system` and `flatpak-user` packages installed, they will be combined into a single `flatpak` count with `--packages-combined` enabled.
|
||||
* Add `modules[n].condition` to conditionally enable modules on different platforms
|
||||
* Useful when sharing configuration files across platforms
|
||||
* For example:
|
||||
```jsonc
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "This string will be printed on Intel macOS only",
|
||||
"condition": {
|
||||
"system": "macOS", // Can be an array, optional
|
||||
"arch": "x86_64" // Can be an array, optional too
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Revert the change of `posix_spawn` in v2.48.0 for Android and OpenBSD (Android / OpenBSD)
|
||||
* Fix completion for Android 7 (Required by Termux)
|
||||
|
||||
# 2.48.0
|
||||
|
||||
Features:
|
||||
* Add support for detecting Fedora variants (#1830, OS, Linux)
|
||||
* Currently supported variants: CoreOS, Kinoite, Sericea, Silverblue
|
||||
* Optimize GPU detection on Windows when `--gpu-driver-specific` is not used (GPU, Windows)
|
||||
* Improve accuracy of GPU type detection. Previously it was guessed based on the dedicated vmem size, which causes issues on newer AMD integrated GPUs such as 9000 HX and AI 9 HX series. Supported on Windows 8.1 or later.
|
||||
* Add support for generic frequency detection of GPU 3D engine on Windows 11 22H2 or later.
|
||||
* Improve performance. GPU temperature detection is significantly improved when `--gpu-driver-specific` is not used.
|
||||
* Improve performance and security when spawning child processes by replacing `fork-exec` with `posix_spawn` (*nix)
|
||||
* Improve accuracy of sound device detection on macOS (Sound, macOS)
|
||||
* Trim leading and trailing whitespaces in disk serial numbers (PhysicalDisk)
|
||||
* Add `/etc/profiles/per-user` detection for Nix user packages (#1782, Packages, Linux)
|
||||
* Introduce `years` (whole years as integer), `days-of-year` (days since the last anniversary) and `years-fraction` (years as fraction, e.g. 1.5 means 1 year and 6 months) formatting placeholder to `Disk` (since disk creation), `Users` (since user login) and `Uptime` (since system boot) modules
|
||||
* For example: `fastfetch -s disk --disk-key 'OS Installation' --disk-format '{years} years {days-of-year} days'`
|
||||
* Add `--fraction-ndigits` option to specify the number of digits after the decimal point when displaying ordinary fractional values
|
||||
* Typically used with `{years-fraction}` above
|
||||
* This option does not affect percentage values, sizes, etc, which are controlled by individual options.
|
||||
|
||||
Bugfixes:
|
||||
* Fix compilation issues when not using `-DBINARY_LINK_TYPE=dlopen`
|
||||
* Regression from v2.47.0
|
||||
* Note: this option was added for debugging purposes only and is not recommended for production use
|
||||
* Replace `MTLDevice::hasUnifiedMemory` with `MTLDevice::location` for GPU type Detection (GPU, macOS)
|
||||
* This should resolve the issue where discrete GPUs were detected as integrated GPUs on Intel MacBooks with multi-GPU configurations.
|
||||
* Prevent text files from being loaded as image files (#1843, Logo)
|
||||
|
||||
Logos:
|
||||
* Add Minimal System
|
||||
* Add AxOS
|
||||
* Rename Ada to Xray OS
|
||||
|
||||
# 2.47.0
|
||||
|
||||
Features:
|
||||
* Various improvements for Solaris / OpenIndiana support
|
||||
* Support BIOS (UEFI or legacy) type detection (BIOS)
|
||||
* Support physical disk detection (PhysicalDisk)
|
||||
* Remove leading `-` from login shells (Shell)
|
||||
* Improve GPU detection performance (GPU)
|
||||
* Drop `libpciaccess` dependency
|
||||
* Use native API to detect sound devices (Sound)
|
||||
* Drop `PulseAudio` dependency
|
||||
* Improve DietPi OS and Raspberry Pi OS detection (#1816, OS, Linux)
|
||||
* Force reporting version 26 on macOS Tahoe (OS, macOS)
|
||||
* Append version string to Ubuntu variants (OS, Linux)
|
||||
* Improve performance of media detection for macOS 15.4+ (Media, macOS)
|
||||
* Increase `PROC_FILE_BUFFSIZ` to avoid possible short reads (Linux)
|
||||
* Fix potential bugs in `DiskIO`, `NetIO` and `CPUUsage` modules
|
||||
* Improve accuracy of CPU usage calculations by including interrupt and softirq times (CPUUsage, Linux / *BSD)
|
||||
* Ignore `init` and `systemd` processes when detecting terminals (Terminal, Linux)
|
||||
* Improve accuracy of CPU usage detection on Windows 10+ with perflib, which matches values reported by Task Manager (CPUUsage, Windows)
|
||||
|
||||
Bugfixes:
|
||||
* Fix `pci.ids` file location (#1819, GPU, OpenBSD)
|
||||
* Fix compiling on FreeBSD when `libdrm` support is disabled (#1820, GPU, FreeBSD)
|
||||
|
||||
Logos:
|
||||
* Improve visibility on white-background terminals for some logos by replacing white with the default foreground color
|
||||
* According to Wikipedia, the default foreground color is implementation-defined. It's usually black for white themes and white for dark themes. However, some terminals, notably Konsole with the default theme, use a different color, which may cause issues with some logos.
|
||||
* Add Xubuntu
|
||||
|
||||
# 2.46.0
|
||||
|
||||
Features:
|
||||
@@ -12,7 +99,7 @@ Features:
|
||||
* Use `board-id` as board name if available (Board, macOS)
|
||||
* Intel only
|
||||
* Support shared VRAM usage detection for AMD GPUs (GPU, Linux)
|
||||
* Use `perflib.h` instead of `pdh.h` for CPU temperature querying to get rid of pdh.dll (#1787, CPU, Windows)
|
||||
* Use `perflib.h` instead of `pdh.h` for CPU temperature querying to get rid of `pdh.dll` dependency (#1787, CPU, Windows)
|
||||
* Support GPU info detection for old ATI radeon driver (#1810, GPU, Linux)
|
||||
* Add macOS 26 Tahoe support (macOS)
|
||||
* Report macOS 26 code name (OS)
|
||||
|
||||
+7
-12
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.46.0
|
||||
VERSION 2.48.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -76,13 +76,13 @@ cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD O
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD" OFF)
|
||||
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
@@ -326,11 +326,6 @@ endif()
|
||||
fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)
|
||||
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
|
||||
|
||||
if(APPLE)
|
||||
# See src/detection/media/media_apple.m
|
||||
fastfetch_load_text(src/data/nowPlaying.scptd DATATEXT_NOWPLAYING)
|
||||
endif()
|
||||
|
||||
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
|
||||
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
|
||||
if(APPLE)
|
||||
@@ -341,7 +336,7 @@ endif()
|
||||
# Ascii image data #
|
||||
####################
|
||||
|
||||
file(GLOB LOGO_FILES "src/logo/ascii/*.txt")
|
||||
file(GLOB LOGO_FILES CONFIGURE_DEPENDS "src/logo/ascii/*.txt")
|
||||
set(LOGO_BUILTIN_H "#pragma once\n#pragma GCC diagnostic ignored \"-Wtrigraphs\"\n\n")
|
||||
foreach(file ${LOGO_FILES})
|
||||
fastfetch_load_text("${file}" content)
|
||||
@@ -1062,7 +1057,7 @@ elseif(SunOS)
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/disk/disk_sunos.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nosupport.c
|
||||
src/detection/physicaldisk/physicaldisk_sunos.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_sunos.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
@@ -1102,7 +1097,7 @@ elseif(SunOS)
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_sunos.c
|
||||
src/detection/swap/swap_sunos.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
@@ -1587,7 +1582,6 @@ elseif(WIN32)
|
||||
PRIVATE "ws2_32"
|
||||
PRIVATE "ntdll"
|
||||
PRIVATE "version"
|
||||
PRIVATE "setupapi"
|
||||
PRIVATE "hid"
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "imagehlp"
|
||||
@@ -1637,6 +1631,7 @@ elseif(SunOS)
|
||||
PRIVATE "proc"
|
||||
PRIVATE "zfs"
|
||||
PRIVATE "nvpair"
|
||||
PRIVATE "devinfo"
|
||||
)
|
||||
elseif(ANDROID)
|
||||
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[](https://github.com/fastfetch-cli/fastfetch/releases)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://deepwiki.com/fastfetch-cli/fastfetch)
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS.
|
||||
|
||||
@@ -69,13 +70,12 @@ If fastfetch is not packaged for your distribution or an outdated version is pac
|
||||
|
||||
You may also download the program directly from [the GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) in the form of an archive file.
|
||||
|
||||
### FreeBSD
|
||||
### BSD systems
|
||||
|
||||
* `pkg install fastfetch`
|
||||
|
||||
### NetBSD
|
||||
|
||||
* `pkgin in fastfetch`
|
||||
* FreeBSD: `pkg install fastfetch`
|
||||
* NetBSD: `pkgin in fastfetch`
|
||||
* OpenBSD: `pkg_add fastfetch` (Snapshots only)
|
||||
* DragonFly BSD: `pkg install fastfetch` (Snapshots only)
|
||||
|
||||
### Android (Termux)
|
||||
|
||||
@@ -93,7 +93,7 @@ See the Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
|
||||
* Run with default configuration: `fastfetch`
|
||||
* Run with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) to find what interests you: `fastfetch -c all.jsonc`
|
||||
* View all data that fastfetch detects: `fastfetch -s <module> --format json`
|
||||
* View all data that fastfetch detects: `fastfetch -s <module1>[:<module2>][:<module3>] --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate a config file based on command line arguments: `fastfetch --arg1 --arg2 --gen-config`
|
||||
|
||||
|
||||
Vendored
+18
@@ -1,3 +1,21 @@
|
||||
fastfetch (2.48.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.48.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 17 Jul 2025 16:16:52 +0800
|
||||
|
||||
fastfetch (2.47.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.47.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 03 Jul 2025 14:51:45 +0800
|
||||
|
||||
fastfetch (2.46.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.46.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 20 Jun 2025 15:01:21 +0800
|
||||
|
||||
fastfetch (2.45.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.45.0
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.45.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.48.0_source.buildinfo universe/utils optional
|
||||
|
||||
+426
-8
@@ -108,6 +108,128 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"systems": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Android",
|
||||
"Linux",
|
||||
"DragonFly",
|
||||
"MidnightBSD",
|
||||
"FreeBSD",
|
||||
"macOS",
|
||||
"Windows",
|
||||
"SunOS",
|
||||
"OpenBSD",
|
||||
"NetBSD",
|
||||
"Haiku"
|
||||
]
|
||||
},
|
||||
"architectures": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"x86_64",
|
||||
"i386",
|
||||
"ia64",
|
||||
"aarch64",
|
||||
"arm",
|
||||
"mips",
|
||||
"powerpc",
|
||||
"riscv",
|
||||
"s390x",
|
||||
"loongarch",
|
||||
"sparc",
|
||||
"alpha",
|
||||
"hppa",
|
||||
"m68k"
|
||||
]
|
||||
},
|
||||
"conditions": {
|
||||
"description": "Only show the module if conditions are met",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"system": {
|
||||
"description": "System name to match",
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/systems"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/systems"
|
||||
},
|
||||
"description": "Array of system names to match"
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Null to disable this condition"
|
||||
}
|
||||
]
|
||||
},
|
||||
"!system": {
|
||||
"description": "System name to not match",
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/systems"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/systems"
|
||||
},
|
||||
"description": "Array of system names to not match"
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Null to disable this condition"
|
||||
}
|
||||
]
|
||||
},
|
||||
"arch": {
|
||||
"description": "Architecture to match",
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/architectures"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/architectures"
|
||||
},
|
||||
"description": "Array of architectures to match"
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Null to disable this condition"
|
||||
}
|
||||
]
|
||||
},
|
||||
"!arch": {
|
||||
"description": "Architecture to not match",
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/architectures"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/architectures"
|
||||
},
|
||||
"description": "Array of architectures to not match"
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Null to disable this condition"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
"batteryFormat": {
|
||||
@@ -183,7 +305,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"diskFormat": {
|
||||
"description": "Output format of the module `Disk`. See Wiki for formatting syntax\n 1. {size-used}: Size used\n 2. {size-total}: Size total\n 3. {size-percentage}: Size percentage num\n 4. {files-used}: Files used\n 5. {files-total}: Files total\n 6. {files-percentage}: Files percentage num\n 7. {is-external}: True if external volume\n 8. {is-hidden}: True if hidden volume\n 9. {filesystem}: Filesystem\n 10. {name}: Label / name\n 11. {is-readonly}: True if read-only\n 12. {create-time}: Create time in local timezone\n 13. {size-percentage-bar}: Size percentage bar\n 14. {files-percentage-bar}: Files percentage bar\n 15. {days}: Days after creation\n 16. {hours}: Hours after creation\n 17. {minutes}: Minutes after creation\n 18. {seconds}: Seconds after creation\n 19. {milliseconds}: Milliseconds after creation\n 20. {mountpoint}: Mount point / drive letter\n 21. {mount-from}: Mount from (device path)",
|
||||
"description": "Output format of the module `Disk`. See Wiki for formatting syntax\n 1. {size-used}: Size used\n 2. {size-total}: Size total\n 3. {size-percentage}: Size percentage num\n 4. {files-used}: Files used\n 5. {files-total}: Files total\n 6. {files-percentage}: Files percentage num\n 7. {is-external}: True if external volume\n 8. {is-hidden}: True if hidden volume\n 9. {filesystem}: Filesystem\n 10. {name}: Label / name\n 11. {is-readonly}: True if read-only\n 12. {create-time}: Create time in local timezone\n 13. {size-percentage-bar}: Size percentage bar\n 14. {files-percentage-bar}: Files percentage bar\n 15. {days}: Days after creation\n 16. {hours}: Hours after creation\n 17. {minutes}: Minutes after creation\n 18. {seconds}: Seconds after creation\n 19. {milliseconds}: Milliseconds after creation\n 20. {mountpoint}: Mount point / drive letter\n 21. {mount-from}: Mount from (device path)\n 22. {years}: Years integer after creation\n 23. {days-of-year}: Days of year after creation\n 24. {years-fraction}: Years fraction after creation",
|
||||
"type": "string"
|
||||
},
|
||||
"diskioFormat": {
|
||||
@@ -306,10 +428,6 @@
|
||||
"description": "Output format of the module `PublicIp`. See Wiki for formatting syntax\n 1. {ip}: Public IP address\n 2. {location}: Location",
|
||||
"type": "string"
|
||||
},
|
||||
"separatorFormat": {
|
||||
"description": "Output format of the module `Separator`. See Wiki for formatting syntax\n 1. {string}: Separator string\n 2. {outputColor}: Output color\n 3. {length}: Length",
|
||||
"type": "string"
|
||||
},
|
||||
"shellFormat": {
|
||||
"description": "Output format of the module `Shell`. See Wiki for formatting syntax\n 1. {process-name}: Shell process name\n 2. {exe}: The first argument of the command line when running the shell\n 3. {exe-name}: Shell base name of arg0\n 4. {version}: Shell version\n 5. {pid}: Shell pid\n 6. {pretty-name}: Shell pretty name\n 7. {exe-path}: Shell full exe path\n 8. {tty}: Shell tty used",
|
||||
"type": "string"
|
||||
@@ -319,7 +437,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"swapFormat": {
|
||||
"description": "Output format of the module `Swap`. See Wiki for formatting syntax\n 1. {used}: Used size\n 2. {total}: Total size\n 3. {percentage}: Percentage used (num)\n 4. {percentage-bar}: Percentage used (bar)",
|
||||
"description": "Output format of the module `Swap`. See Wiki for formatting syntax\n 1. {used}: Used size\n 2. {total}: Total size\n 3. {percentage}: Percentage used (num)\n 4. {percentage-bar}: Percentage used (bar)\n 5. {name}: Name",
|
||||
"type": "string"
|
||||
},
|
||||
"terminalFormat": {
|
||||
@@ -351,11 +469,11 @@
|
||||
"type": "string"
|
||||
},
|
||||
"uptimeFormat": {
|
||||
"description": "Output format of the module `Uptime`. See Wiki for formatting syntax\n 1. {days}: Days\n 2. {hours}: Hours\n 3. {minutes}: Minutes\n 4. {seconds}: Seconds\n 5. {milliseconds}: Milliseconds\n 6. {boot-time}: Boot time in local timezone",
|
||||
"description": "Output format of the module `Uptime`. See Wiki for formatting syntax\n 1. {days}: Days after boot\n 2. {hours}: Hours after boot\n 3. {minutes}: Minutes after boot\n 4. {seconds}: Seconds after boot\n 5. {milliseconds}: Milliseconds after boot\n 6. {boot-time}: Boot time in local timezone\n 7. {years}: Years integer after boot\n 8. {days-of-year}: Days of year after boot\n 9. {years-fraction}: Years fraction after boot",
|
||||
"type": "string"
|
||||
},
|
||||
"usersFormat": {
|
||||
"description": "Output format of the module `Users`. See Wiki for formatting syntax\n 1. {name}: User name\n 2. {host-name}: Host name\n 3. {session}: Session name\n 4. {client-ip}: Client IP\n 5. {login-time}: Login Time in local timezone\n 6. {days}: Days after login\n 7. {hours}: Hours after login\n 8. {minutes}: Minutes after login\n 9. {seconds}: Seconds after login\n 10. {milliseconds}: Milliseconds after login",
|
||||
"description": "Output format of the module `Users`. See Wiki for formatting syntax\n 1. {name}: User name\n 2. {host-name}: Host name\n 3. {session}: Session name\n 4. {client-ip}: Client IP\n 5. {login-time}: Login Time in local timezone\n 6. {days}: Days after login\n 7. {hours}: Hours after login\n 8. {minutes}: Minutes after login\n 9. {seconds}: Seconds after login\n 10. {milliseconds}: Milliseconds after login\n 11. {years}: Years integer after login\n 12. {days-of-year}: Days of year after login\n 13. {years-fraction}: Years fraction after login",
|
||||
"type": "string"
|
||||
},
|
||||
"versionFormat": {
|
||||
@@ -934,6 +1052,28 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fraction": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set how ordinary fraction numbers should be displayed",
|
||||
"properties": {
|
||||
"ndigits": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"description": "Set the number of digits to keep after the decimal point when formatting ordinary fraction numbers",
|
||||
"minimum": 0,
|
||||
"maximum": 9
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
"description": "The number of digits will be automatically determined based on the value"
|
||||
}
|
||||
],
|
||||
"default": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"noBuffer": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to disable the stdout application buffer",
|
||||
@@ -987,6 +1127,7 @@
|
||||
"host",
|
||||
"icons",
|
||||
"initsystem",
|
||||
"keyboard",
|
||||
"kernel",
|
||||
"lm",
|
||||
"loadavg",
|
||||
@@ -995,6 +1136,7 @@
|
||||
"media",
|
||||
"memory",
|
||||
"monitor",
|
||||
"mouse",
|
||||
"netio",
|
||||
"opencl",
|
||||
"opengl",
|
||||
@@ -1049,6 +1191,9 @@
|
||||
"type": {
|
||||
"const": "break",
|
||||
"description": "Print a empty line"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1089,6 +1234,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/batteryFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1118,6 +1266,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/biosFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1155,6 +1306,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/bluetoothFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1184,6 +1338,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/bluetoothradioFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1213,6 +1370,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/boardFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1242,6 +1402,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/bootmgrFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1286,6 +1449,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/brightnessFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1318,6 +1484,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/btrfsFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1347,6 +1516,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/cameraFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1376,6 +1548,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/chassisFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1413,6 +1588,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/cpuFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1445,6 +1623,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/cpucacheFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1488,6 +1669,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/cpuusageFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1549,6 +1733,9 @@
|
||||
},
|
||||
"keyIcon": {
|
||||
"$ref": "#/$defs/keyIcon"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1590,6 +1777,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/commandFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1622,6 +1812,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/cursorFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1653,6 +1846,9 @@
|
||||
"format": {
|
||||
"description": "Text to print",
|
||||
"type": "string"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1685,6 +1881,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/datetimeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1739,6 +1938,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/displayFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1813,6 +2015,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/diskFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1857,6 +2062,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/diskioFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1891,6 +2099,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/deFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1929,6 +2140,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/dnsFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1961,6 +2175,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/editorFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1993,6 +2210,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/fontFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2025,6 +2245,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/gamepadFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2084,6 +2307,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/gpuFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2113,6 +2339,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/hostFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2142,6 +2371,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/iconsFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2171,6 +2403,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/initsystemFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2200,6 +2435,38 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/kernelFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Keyboard",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "keyboard",
|
||||
"description": "List (connected) keyboards"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyIcon": {
|
||||
"$ref": "#/$defs/keyIcon"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2229,6 +2496,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/lmFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2317,6 +2587,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/localipFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2361,6 +2634,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/loadavgFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2390,6 +2666,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/localeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2419,6 +2698,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/mediaFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2451,6 +2733,38 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Mouse",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "mouse",
|
||||
"description": "List connected mouses"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyIcon": {
|
||||
"$ref": "#/$defs/keyIcon"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2480,6 +2794,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/monitorFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2529,6 +2846,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/netioFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2558,6 +2878,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/openclFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2596,6 +2919,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/openglFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2625,6 +2951,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/osFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2678,6 +3007,11 @@
|
||||
},
|
||||
"default": ["winget"]
|
||||
},
|
||||
"combined": {
|
||||
"description": "Whether to combine related package managers into single counts (e.g., nix-system + nix-user = nix)",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -2695,6 +3029,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/packagesFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2731,6 +3068,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/physicaldiskFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2760,6 +3100,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/physicalmemoryFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2789,6 +3132,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/playerFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2818,6 +3164,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/poweradapterFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2847,6 +3196,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/processesFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2893,6 +3245,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/publicipFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2919,6 +3274,9 @@
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2948,6 +3306,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/shellFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2990,6 +3351,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/soundFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3027,6 +3391,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/swapFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3056,6 +3423,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/terminalFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3085,6 +3455,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/terminalfontFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3114,6 +3487,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/terminalsizeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3143,6 +3519,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/terminalthemeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3172,6 +3551,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/themeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3225,6 +3607,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/titleFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3254,6 +3639,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/tpmFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3293,6 +3681,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/usersFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3322,6 +3713,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/uptimeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3351,6 +3745,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/versionFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3380,6 +3777,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/vulkanFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3409,6 +3809,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/wallpaperFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3453,6 +3856,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/weatherFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3482,6 +3888,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/wifiFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3516,6 +3925,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/wmFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3545,6 +3957,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/wmthemeFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3577,6 +3992,9 @@
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/zpoolFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,10 +217,23 @@
|
||||
"key": "│{#magenta}│ {icon} Login │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"condition": {
|
||||
"!system": "macOS"
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"folders": "/", // On macOS, "/System/Volumes/VM" works for me
|
||||
"folders": "/",
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
"condition": {
|
||||
"system": "macOS"
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"folders": "/System/Volumes/VM",
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small",
|
||||
"padding": {
|
||||
"top": 1
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"separator": " "
|
||||
},
|
||||
"modules": [
|
||||
"break",
|
||||
"title",
|
||||
{
|
||||
"type": "os",
|
||||
"key": "os ",
|
||||
"keyColor": "red"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "kernel",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"format": "{vendor} {family}",
|
||||
"key": "host ",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "pkgs ",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"format": "{?days}{days}d {?}{hours}h {minutes}m",
|
||||
"key": "uptime",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "memory",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
"break"
|
||||
]
|
||||
}
|
||||
@@ -16,7 +16,10 @@
|
||||
"format": "{release}"
|
||||
},
|
||||
"uptime",
|
||||
"packages",
|
||||
{
|
||||
"type": "packages",
|
||||
"combined": true
|
||||
},
|
||||
"shell",
|
||||
{
|
||||
"type": "display",
|
||||
|
||||
+9
-2
@@ -32,10 +32,16 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_FLOAT:
|
||||
ffStrbufAppendF(buffer, "%f", *(float*)formatarg->value);
|
||||
if (instance.config.display.fractionNdigits >= 0)
|
||||
ffStrbufAppendF(buffer, "%.*f", instance.config.display.fractionNdigits, *(float*)formatarg->value);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "%g", *(float*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_DOUBLE:
|
||||
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||
if (instance.config.display.fractionNdigits >= 0)
|
||||
ffStrbufAppendF(buffer, "%.*f", instance.config.display.fractionNdigits, *(double*)formatarg->value);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_BOOL:
|
||||
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
|
||||
@@ -108,6 +114,7 @@ static inline bool formatArgSet(const FFformatarg* arg)
|
||||
{
|
||||
return arg->value != NULL && (
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_FLOAT && *(float*)arg->value > 0.0) || //Also is false for NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet((char*)arg->value)) ||
|
||||
|
||||
+3
-2
@@ -19,8 +19,7 @@
|
||||
#define FF_INVALID_FD (-1)
|
||||
// procfs's file can be changed between read calls such as /proc/meminfo and /proc/uptime.
|
||||
// one safe way to read correct data is reading the whole file in a single read syscall
|
||||
// 8192 comes from procps-ng: https://gitlab.com/procps-ng/procps/-/blob/master/library/meminfo.c?ref_type=heads#L39
|
||||
#define PROC_FILE_BUFFSIZ 8192
|
||||
#define PROC_FILE_BUFFSIZ (32 * 1024)
|
||||
#endif
|
||||
|
||||
static inline FFNativeFD FFUnixFD2NativeFD(int unixfd)
|
||||
@@ -223,6 +222,8 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char*
|
||||
return false;
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Only O_RDONLY is supported
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory);
|
||||
|
||||
@@ -358,3 +358,12 @@ void ffListFilesRecursively(const char* path, bool pretty)
|
||||
ffStrbufEnsureEndsWithC(&folder, '/');
|
||||
listFilesRecursively(folder.length, &folder, 0, NULL, pretty);
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void)
|
||||
{
|
||||
static FFNativeFD hNullFile = -1;
|
||||
if (hNullFile != -1)
|
||||
return hNullFile;
|
||||
hNullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ bool ffSuppressIO(bool suppress)
|
||||
static bool init = false;
|
||||
static HANDLE hOrigOut = INVALID_HANDLE_VALUE;
|
||||
static HANDLE hOrigErr = INVALID_HANDLE_VALUE;
|
||||
static HANDLE hNullFile = INVALID_HANDLE_VALUE;
|
||||
HANDLE hNullFile = ffGetNullFD();
|
||||
static int fOrigOut = -1;
|
||||
static int fOrigErr = -1;
|
||||
static int fNullFile = -1;
|
||||
@@ -187,7 +187,6 @@ bool ffSuppressIO(bool suppress)
|
||||
|
||||
hOrigOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
hOrigErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
hNullFile = CreateFileW(L"NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL);
|
||||
fOrigOut = _dup(STDOUT_FILENO);
|
||||
fOrigErr = _dup(STDERR_FILENO);
|
||||
fNullFile = _open_osfhandle((intptr_t) hNullFile, 0);
|
||||
@@ -352,3 +351,23 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void)
|
||||
{
|
||||
static FFNativeFD hNullFile = INVALID_HANDLE_VALUE;
|
||||
if (hNullFile != INVALID_HANDLE_VALUE)
|
||||
return hNullFile;
|
||||
hNullFile = CreateFileW(
|
||||
L"NUL",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
&(SECURITY_ATTRIBUTES){
|
||||
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
||||
.lpSecurityDescriptor = NULL,
|
||||
.bInheritHandle = TRUE,
|
||||
});
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/time.h"
|
||||
#include "detection/version/version.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
@@ -170,6 +171,25 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchesJsonArray(const char* str, yyjson_val* val)
|
||||
{
|
||||
assert(val);
|
||||
|
||||
if (unsafe_yyjson_is_str(val))
|
||||
return ffStrEqualsIgnCase(str, unsafe_yyjson_get_str(val));
|
||||
|
||||
if (!unsafe_yyjson_is_arr(val)) return false;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_val* item;
|
||||
yyjson_arr_foreach(val, idx, max, item)
|
||||
{
|
||||
if (yyjson_is_str(item) && ffStrEqualsIgnCase(str, unsafe_yyjson_get_str(item)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
@@ -197,6 +217,29 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
module = NULL;
|
||||
else if (yyjson_is_obj(module))
|
||||
{
|
||||
yyjson_val* conditions = yyjson_obj_get(module, "condition");
|
||||
if (conditions)
|
||||
{
|
||||
if (!yyjson_is_obj(conditions))
|
||||
return "Property 'conditions' must be an object";
|
||||
|
||||
yyjson_val* system = yyjson_obj_get(conditions, "system");
|
||||
if (system && !matchesJsonArray(ffVersionResult.sysName, system))
|
||||
continue;
|
||||
|
||||
system = yyjson_obj_get(conditions, "!system");
|
||||
if (system && matchesJsonArray(ffVersionResult.sysName, system))
|
||||
continue;
|
||||
|
||||
yyjson_val* arch = yyjson_obj_get(conditions, "arch");
|
||||
if (arch && !matchesJsonArray(ffVersionResult.architecture, arch))
|
||||
continue;
|
||||
|
||||
arch = yyjson_obj_get(conditions, "!arch");
|
||||
if (arch && matchesJsonArray(ffVersionResult.architecture, arch))
|
||||
continue;
|
||||
}
|
||||
|
||||
type = yyjson_get_str(yyjson_obj_get(module, "type"));
|
||||
if (!type) return "module object must contain a \"type\" key ( case sensitive )";
|
||||
if (yyjson_obj_size(module) == 1) // contains only Property type
|
||||
|
||||
@@ -74,7 +74,7 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...);
|
||||
FF_MAYBE_UNUSED void* libraryObjectName = NULL; // Placeholder
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
|
||||
symbolMapping = (__typeof__(&symbolName)) &symbolName
|
||||
symbolMapping = (__typeof__(&symbolName)) &symbolName;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
|
||||
FF_MAYBE_UNUSED __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "util/debug.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/poll.h>
|
||||
#include <poll.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
+106
-14
@@ -12,6 +12,10 @@
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if !(__ANDROID__ || __OpenBSD__)
|
||||
#include <spawn.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
@@ -33,6 +37,10 @@
|
||||
#include <image.h>
|
||||
#endif
|
||||
|
||||
#ifndef environ
|
||||
extern char** environ;
|
||||
#endif
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
|
||||
static inline int ffPipe2(int* fds, int flags)
|
||||
@@ -48,6 +56,8 @@ static inline int ffPipe2(int* fds, int flags)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Not thread-safe
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
{
|
||||
int pipes[2];
|
||||
@@ -56,7 +66,77 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if(ffPipe2(pipes, O_CLOEXEC) == -1)
|
||||
return "pipe() failed";
|
||||
|
||||
pid_t childPid = fork();
|
||||
pid_t childPid = -1;
|
||||
int nullFile = ffGetNullFD();
|
||||
|
||||
#if !(__ANDROID__ || __OpenBSD__)
|
||||
|
||||
// NetBSD / Darwin: native syscall
|
||||
// Linux (glibc): clone3-execve
|
||||
// FreeBSD: vfork-execve
|
||||
// illumos: vforkx-execve
|
||||
// OpenBSD / Android (bionic): fork-execve
|
||||
|
||||
posix_spawn_file_actions_t file_actions;
|
||||
posix_spawn_file_actions_init(&file_actions);
|
||||
posix_spawn_file_actions_adddup2(&file_actions, pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
posix_spawn_file_actions_adddup2(&file_actions, nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
|
||||
static char* oldLang = NULL;
|
||||
static int langIndex = -1;
|
||||
|
||||
if (langIndex >= 0)
|
||||
{
|
||||
// Found before
|
||||
if (oldLang) // oldLang was set only if it needed to be changed
|
||||
{
|
||||
if (environ[langIndex] != oldLang)
|
||||
{
|
||||
// environ is changed outside of this function
|
||||
langIndex = -1;
|
||||
}
|
||||
else
|
||||
environ[langIndex] = (char*) "LANG=C.UTF-8";
|
||||
}
|
||||
}
|
||||
if (langIndex < 0)
|
||||
{
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
{
|
||||
if (ffStrStartsWith(environ[i], "LANG="))
|
||||
{
|
||||
langIndex = i;
|
||||
const char* langValue = environ[i] + 5; // Skip "LANG="
|
||||
if (ffStrEqualsIgnCase(langValue, "C") ||
|
||||
ffStrStartsWithIgnCase(environ[i], "C.") ||
|
||||
ffStrEqualsIgnCase(langValue, "en_US") ||
|
||||
ffStrStartsWithIgnCase(langValue, "en_US."))
|
||||
break; // No need to change LANG
|
||||
oldLang = environ[i];
|
||||
environ[i] = (char*) "LANG=C.UTF-8"; // Set LANG to C.UTF-8 for consistent output
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = posix_spawnp(&childPid, argv[0], &file_actions, NULL, argv, environ);
|
||||
|
||||
if (oldLang)
|
||||
environ[langIndex] = oldLang;
|
||||
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
return "posix_spawnp() failed";
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// https://github.com/termux/termux-packages/issues/25369
|
||||
childPid = fork();
|
||||
if(childPid == -1)
|
||||
{
|
||||
close(pipes[0]);
|
||||
@@ -64,18 +144,18 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
return "fork() failed";
|
||||
}
|
||||
|
||||
//Child
|
||||
if(childPid == 0)
|
||||
{
|
||||
int nullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
//Child
|
||||
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
setenv("LANG", "C", 1);
|
||||
putenv("LANG=C.UTF-8");
|
||||
execvp(argv[0], argv);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
//Parent
|
||||
#endif
|
||||
|
||||
close(pipes[1]);
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
@@ -86,20 +166,30 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (timeout >= 0)
|
||||
{
|
||||
struct pollfd pollfd = { childPipeFd, POLLIN, 0 };
|
||||
if (poll(&pollfd, 1, timeout) == 0)
|
||||
int pollret = poll(&pollfd, 1, timeout);
|
||||
if (pollret == 0)
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
else if (pollret < 0)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
if (errno == EINTR)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
@@ -279,8 +369,10 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
psinfo_t proc;
|
||||
if (ffReadFileData(filePath, sizeof(proc), &proc) == sizeof(proc))
|
||||
{
|
||||
ffStrbufSetS(exe, proc.pr_psargs);
|
||||
ffStrbufSubstrBeforeFirstC(exe, ' ');
|
||||
const char* args = proc.pr_psargs;
|
||||
if (args[0] == '-') ++args;
|
||||
const char* end = strchr(args, ' ');
|
||||
ffStrbufSetNS(exe, end ? (uint32_t) (end - args) : (uint32_t) strlen(args), args);
|
||||
}
|
||||
|
||||
if (exePath)
|
||||
|
||||
@@ -81,7 +81,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (hChildPipeWrite == INVALID_HANDLE_VALUE)
|
||||
return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
|
||||
|
||||
PROCESS_INFORMATION piProcInfo = {0};
|
||||
PROCESS_INFORMATION piProcInfo = {};
|
||||
|
||||
BOOL success;
|
||||
|
||||
@@ -91,9 +91,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
if (useStdErr)
|
||||
{
|
||||
siStartInfo.hStdOutput = ffGetNullFD();
|
||||
siStartInfo.hStdError = hChildPipeWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
siStartInfo.hStdError = ffGetNullFD();
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
|
||||
@@ -97,3 +97,47 @@ static inline const char* ffTimeToTimeStr(uint64_t msec)
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
typedef struct FFTimeGetAgeResult
|
||||
{
|
||||
uint32_t years;
|
||||
uint32_t daysOfYear;
|
||||
double yearsFraction;
|
||||
} FFTimeGetAgeResult;
|
||||
|
||||
static inline FFTimeGetAgeResult ffTimeGetAge(uint64_t birthMs, uint64_t nowMs)
|
||||
{
|
||||
FFTimeGetAgeResult result = {};
|
||||
if (__builtin_expect(birthMs == 0 || nowMs < birthMs, 0))
|
||||
return result;
|
||||
|
||||
time_t birth_s = (time_t) (birthMs / 1000);
|
||||
struct tm birth_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&birth_tm, &birth_s);
|
||||
#else
|
||||
localtime_r(&birth_s, &birth_tm);
|
||||
#endif
|
||||
|
||||
time_t now_s = (time_t) (nowMs / 1000);
|
||||
struct tm now_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&now_tm, &now_s);
|
||||
#else
|
||||
localtime_r(&now_s, &now_tm);
|
||||
#endif
|
||||
|
||||
result.years = (uint32_t) (now_tm.tm_year - birth_tm.tm_year);
|
||||
if (now_tm.tm_yday < birth_tm.tm_yday)
|
||||
result.years--;
|
||||
|
||||
birth_tm.tm_year += (int) result.years;
|
||||
birth_s = mktime(&birth_tm);
|
||||
uint32_t diff_s = (uint32_t) (now_s - birth_s);
|
||||
result.daysOfYear = diff_s / (24 * 60 * 60);
|
||||
|
||||
birth_tm.tm_year += 1;
|
||||
result.yearsFraction = (double) diff_s / (double) (mktime(&birth_tm) - birth_s) + result.years;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -719,6 +719,15 @@
|
||||
"default": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "fraction-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when printing ordinary fraction numbers",
|
||||
"remark": "If negative, the number of digits will be automatically determined based on the value",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": -1
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temp-unit",
|
||||
"desc": "Set the temperature unit",
|
||||
@@ -981,6 +990,16 @@
|
||||
"default": "winget"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "packages-combined",
|
||||
"desc": "Whether to combine related package managers into single counts",
|
||||
"remark": "e.g., nix-system + nix-user = nix",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "display-compact-type",
|
||||
"desc": "Specify whether all displays should be printed in one line",
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
use scripting additions
|
||||
use framework "/System/Library/PrivateFrameworks/MediaRemote.framework"
|
||||
|
||||
set MRNowPlayingRequest to current application's NSClassFromString("MRNowPlayingRequest")
|
||||
|
||||
if MRNowPlayingRequest's localNowPlayingItem() is missing value then
|
||||
return
|
||||
end if
|
||||
|
||||
if MRNowPlayingRequest's localIsPlaying() then
|
||||
set status to "Playing"
|
||||
else
|
||||
set status to "Paused"
|
||||
end if
|
||||
|
||||
set infoDict to MRNowPlayingRequest's localNowPlayingItem()'s nowPlayingInfo()
|
||||
set bundleObj to MRNowPlayingRequest's localNowPlayingPlayerPath()'s client()
|
||||
|
||||
return status & "
|
||||
" & (infoDict's valueForKey:"kMRMediaRemoteNowPlayingInfoTitle" as text) & "
|
||||
" & (infoDict's valueForKey:"kMRMediaRemoteNowPlayingInfoArtist" as text) & "
|
||||
" & (infoDict's valueForKey:"kMRMediaRemoteNowPlayingInfoAlbum" as text) & "
|
||||
" & (bundleObj's bundleIdentifier() as text) & "
|
||||
" & (bundleObj's displayName() as text)
|
||||
@@ -8,40 +8,31 @@
|
||||
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <batclass.h>
|
||||
#include <devguid.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <winternl.h>
|
||||
|
||||
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
if(*hdev)
|
||||
SetupDiDestroyDeviceInfoList(*hdev);
|
||||
}
|
||||
//https://learn.microsoft.com/en-us/windows-hardware/drivers/install/using-device-interfaces
|
||||
ULONG cchDeviceInterfaces = 0;
|
||||
CONFIGRET cr = CM_Get_Device_Interface_List_SizeW(&cchDeviceInterfaces, (LPGUID)&GUID_DEVCLASS_BATTERY, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
return "CM_Get_Device_Interface_List_SizeW() failed";
|
||||
|
||||
static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(hdev == INVALID_HANDLE_VALUE)
|
||||
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
|
||||
if (cchDeviceInterfaces <= 1)
|
||||
return NULL; // Not found
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
|
||||
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
|
||||
wchar_t* FF_AUTO_FREE mszDeviceInterfaces = (wchar_t*)malloc(cchDeviceInterfaces * sizeof(wchar_t));
|
||||
cr = CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVCLASS_BATTERY, NULL, mszDeviceInterfaces, cchDeviceInterfaces, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
return "CM_Get_Device_Interface_ListW() failed";
|
||||
|
||||
for (const wchar_t* pDeviceInterface = mszDeviceInterfaces; *pDeviceInterface; pDeviceInterface += wcslen(pDeviceInterface) + 1)
|
||||
{
|
||||
DWORD cbRequired = 0;
|
||||
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
|
||||
if(!pdidd)
|
||||
break; //Out of memory
|
||||
|
||||
pdidd->cbSize = sizeof(*pdidd);
|
||||
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||
continue;
|
||||
|
||||
HANDLE FF_AUTO_CLOSE_FD hBattery =
|
||||
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
CreateFileW(pDeviceInterface, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(hBattery == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
@@ -99,7 +90,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
bqi.InformationLevel = BatteryManufactureDate;
|
||||
BATTERY_MANUFACTURE_DATE date;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year + 1900, date.Month, date.Day);
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year < 1000 ? date.Year + 1900 : date.Year, date.Month, date.Day);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -131,7 +122,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
{
|
||||
BATTERY_STATUS bs;
|
||||
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY && bi.FullChargedCapacity != 0)
|
||||
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
|
||||
else
|
||||
battery->capacity = 0;
|
||||
@@ -271,6 +262,6 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
return options->useSetupApi
|
||||
? detectWithSetupApi(options, results)
|
||||
? detectWithCmApi(options, results)
|
||||
: detectWithNtApi(options, results);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#elif __sun
|
||||
#include <libdevinfo.h>
|
||||
#include <sys/sunddi.h>
|
||||
#endif
|
||||
|
||||
typedef struct FFSmbiosBios
|
||||
@@ -59,6 +63,7 @@ typedef struct FFSmbiosBios
|
||||
static_assert(offsetof(FFSmbiosBios, ExtendedBiosRomSize) == 0x18,
|
||||
"FFSmbiosBios: Wrong struct alignment");
|
||||
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
|
||||
@@ -94,6 +99,17 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#elif __sun
|
||||
di_node_t rootNode = di_init("/", DINFOPROP);
|
||||
if (rootNode != DI_NODE_NIL)
|
||||
{
|
||||
char* efiVersion = NULL;
|
||||
if (di_prop_lookup_strings(DDI_DEV_T_ANY, rootNode, "efi-version", &efiVersion) > 0)
|
||||
ffStrbufSetStatic(&bios->type, "UEFI");
|
||||
else
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
}
|
||||
di_fini(rootNode);
|
||||
#elif __HAIKU__ || __OpenBSD__
|
||||
// Currently SMBIOS detection is supported in legancy BIOS only
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "perflib_.h"
|
||||
#include "util/windows/perflib_.h"
|
||||
#include <wchar.h>
|
||||
|
||||
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
#include <stdint.h>
|
||||
|
||||
static FFlist cpuTimes1;
|
||||
static uint64_t startTime;
|
||||
|
||||
void ffPrepareCPUUsage(void)
|
||||
{
|
||||
assert(cpuTimes1.elementSize == 0);
|
||||
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
|
||||
ffGetCpuUsageInfo(&cpuTimes1);
|
||||
startTime = ffTimeGetNow();
|
||||
}
|
||||
|
||||
const char* ffGetCpuUsageResult(FFCPUUsageOptions* options, FFlist* result)
|
||||
@@ -23,6 +25,12 @@ const char* ffGetCpuUsageResult(FFCPUUsageOptions* options, FFlist* result)
|
||||
if(error) return error;
|
||||
ffTimeSleep(options->waitTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t elapsedTime = ffTimeGetNow() - startTime;
|
||||
if (elapsedTime < options->waitTime)
|
||||
ffTimeSleep(options->waitTime - (uint32_t)elapsedTime);
|
||||
}
|
||||
|
||||
if(cpuTimes1.length == 0) return "No CPU cores found";
|
||||
|
||||
@@ -57,5 +65,6 @@ retry:
|
||||
cpuTime1->inUseAll = cpuTime2->inUseAll;
|
||||
cpuTime1->totalAll = cpuTime2->totalAll;
|
||||
}
|
||||
startTime = ffTimeGetNow();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
for (uint32_t i = 0; i < coreCount; ++i)
|
||||
{
|
||||
uint64_t* cpTime = cpTimes[i];
|
||||
uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS];
|
||||
uint64_t total = inUse + cpTime[CP_INTR] + cpTime[CP_IDLE];
|
||||
uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS] + cpTime[CP_INTR];
|
||||
uint64_t total = inUse + cpTime[CP_IDLE];
|
||||
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
|
||||
@@ -31,8 +31,8 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
if(sscanf(start, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7)
|
||||
{
|
||||
uint64_t inUse = user + nice + system;
|
||||
uint64_t total = inUse + idle + iowait + irq + softirq;
|
||||
uint64_t inUse = user + nice + system + irq + softirq;
|
||||
uint64_t total = inUse + idle + iowait;
|
||||
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
#include <windows.h>
|
||||
#include <wchar.h>
|
||||
#include "util/windows/perflib_.h"
|
||||
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
static const char* getInfoByNqsi(FFlist* cpuTimes)
|
||||
{
|
||||
ULONG size = 0;
|
||||
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
|
||||
@@ -20,11 +23,8 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i;
|
||||
|
||||
// KernelTime includes idle time.
|
||||
LONGLONG dpcTime = coreInfo->Reserved1[0].QuadPart;
|
||||
LONGLONG interruptTime = coreInfo->Reserved1[1].QuadPart;
|
||||
// KernelTime includes IdleTime and DpcTime.
|
||||
coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart;
|
||||
coreInfo->KernelTime.QuadPart += dpcTime + interruptTime;
|
||||
|
||||
uint64_t inUse = (uint64_t) (coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart);
|
||||
uint64_t total = inUse + (uint64_t)coreInfo->IdleTime.QuadPart;
|
||||
@@ -38,3 +38,137 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* getInfoByPerflib(FFlist* cpuTimes)
|
||||
{
|
||||
static HANDLE hQuery = NULL;
|
||||
|
||||
if (hQuery == NULL)
|
||||
{
|
||||
struct FFPerfQuerySpec
|
||||
{
|
||||
PERF_COUNTER_IDENTIFIER Identifier;
|
||||
WCHAR Name[16];
|
||||
} querySpec = {
|
||||
.Identifier = {
|
||||
// Processor Information GUID
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{b4fc721a-0378-476f-89ba-a5a79f810b36}
|
||||
.CounterSetGuid = { 0xb4fc721a, 0x0378, 0x476f, {0x89, 0xba, 0xa5, 0xa7, 0x9f, 0x81, 0x0b, 0x36} },
|
||||
.Size = sizeof(querySpec),
|
||||
.CounterId = PERF_WILDCARD_COUNTER, // https://learn.microsoft.com/en-us/windows/win32/perfctrs/using-the-perflib-functions-to-consume-counter-data
|
||||
.InstanceId = PERF_WILDCARD_COUNTER,
|
||||
},
|
||||
.Name = PERF_WILDCARD_INSTANCE,
|
||||
};
|
||||
|
||||
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
|
||||
{
|
||||
PerfCloseQueryHandle(hQuery);
|
||||
hQuery = INVALID_HANDLE_VALUE;
|
||||
return "PerfOpenQueryHandle() failed";
|
||||
}
|
||||
|
||||
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
|
||||
{
|
||||
PerfCloseQueryHandle(hQuery);
|
||||
hQuery = INVALID_HANDLE_VALUE;
|
||||
return "PerfAddCounters() failed";
|
||||
}
|
||||
|
||||
if (querySpec.Identifier.Status != ERROR_SUCCESS)
|
||||
{
|
||||
PerfCloseQueryHandle(hQuery);
|
||||
hQuery = INVALID_HANDLE_VALUE;
|
||||
return "PerfAddCounters() reports invalid identifier";
|
||||
}
|
||||
}
|
||||
|
||||
if (hQuery == INVALID_HANDLE_VALUE)
|
||||
return "Init hQuery failed";
|
||||
|
||||
DWORD dataSize = 0;
|
||||
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
return "PerfQueryCounterData(NULL) failed";
|
||||
|
||||
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER))
|
||||
return "instance doesn't exist";
|
||||
|
||||
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = (PERF_DATA_HEADER*)malloc(dataSize);
|
||||
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS)
|
||||
return "PerfQueryCounterData(pDataHeader) failed";
|
||||
|
||||
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*)(pDataHeader + 1);
|
||||
if (pCounterHeader->dwType != PERF_COUNTERSET)
|
||||
return "Invalid counter type";
|
||||
|
||||
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*)(pCounterHeader + 1);
|
||||
if (pMultiCounters->dwCounters == 0)
|
||||
return "No CPU counters found";
|
||||
|
||||
PERF_MULTI_INSTANCES* pMultiInstances = (PERF_MULTI_INSTANCES*)((BYTE*)pMultiCounters + pMultiCounters->dwSize);
|
||||
if (pMultiInstances->dwInstances == 0)
|
||||
return "No CPU instances found";
|
||||
|
||||
PERF_INSTANCE_HEADER* pInstanceHeader = (PERF_INSTANCE_HEADER*)(pMultiInstances + 1);
|
||||
for (DWORD iInstance = 0; iInstance < pMultiInstances->dwInstances; ++iInstance)
|
||||
{
|
||||
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pInstanceHeader + sizeof(*pInstanceHeader));
|
||||
|
||||
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pInstanceHeader + pInstanceHeader->Size);
|
||||
|
||||
uint64_t processorUtility = UINT64_MAX, utilityBase = UINT64_MAX;
|
||||
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++)
|
||||
{
|
||||
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
|
||||
// https://learn.microsoft.com/en-us/windows/win32/perfctrs/using-the-perflib-functions-to-consume-counter-data
|
||||
switch (pCounterIds[iCounter]) {
|
||||
case 26: // % Processor Utility (#26, Type=PERF_AVERAGE_BULK)
|
||||
assert(pCounterData->dwDataSize == sizeof(uint64_t));
|
||||
processorUtility = *(uint64_t*)(pCounterData + 1);
|
||||
break;
|
||||
case 27: // % Utility Base (#27, Type=PERF_AVERAGE_BASE)
|
||||
assert(pCounterData->dwDataSize == sizeof(uint32_t));
|
||||
utilityBase = *(uint32_t*)(pCounterData + 1) * 100LLU;
|
||||
break;
|
||||
}
|
||||
|
||||
pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pCounterData + pCounterData->dwSize);
|
||||
}
|
||||
|
||||
if (wcschr(instanceName, L'_') == NULL /* ignore `_Total` */)
|
||||
{
|
||||
if (processorUtility == UINT64_MAX)
|
||||
return "Counter \"% Processor Utility\" are not supported";
|
||||
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
.inUseAll = processorUtility,
|
||||
.totalAll = utilityBase,
|
||||
};
|
||||
}
|
||||
|
||||
pInstanceHeader = (PERF_INSTANCE_HEADER*)pCounterData;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
#if __aarch64__
|
||||
static uint8_t winver = 10; // Assume Windows 10 or later for WoA
|
||||
#else
|
||||
static uint8_t winver = 0;
|
||||
if (winver == 0)
|
||||
winver = (uint8_t) ffStrbufToUInt(&instance.state.platform.sysinfo.release, 1);
|
||||
#endif
|
||||
|
||||
if (winver >= 10)
|
||||
{
|
||||
if (getInfoByPerflib(cpuTimes) == NULL) return NULL;
|
||||
ffListClear(cpuTimes);
|
||||
winver = 1; // Fall back to NQSI
|
||||
}
|
||||
|
||||
return getInfoByNqsi(cpuTimes);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
while((device = getmntent(mountsFile)))
|
||||
{
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
if (__builtin_expect(options->folders.length > 0, false))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, device->mnt_dir))
|
||||
continue;
|
||||
|
||||
@@ -440,7 +440,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffdsConnectDrm(FFDisplayServerResult* result)
|
||||
const char* ffdsConnectDrm(FF_MAYBE_UNUSED FFDisplayServerResult* result)
|
||||
{
|
||||
#ifdef FF_HAVE_DRM
|
||||
if (instance.config.general.dsForceDrm != FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY)
|
||||
|
||||
@@ -71,7 +71,7 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
|
||||
|
||||
gpu->type = device.location == MTLDeviceLocationBuiltIn ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->index = (uint32_t) device.locationNumber;
|
||||
|
||||
if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0)
|
||||
|
||||
@@ -212,11 +212,13 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
#if FF_HAVE_DRM
|
||||
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
|
||||
{
|
||||
detectByDrm(options, gpus);
|
||||
if (gpus->length > 0) return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return detectByPci(options, gpus);
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
|
||||
struct drm_asahi_params_global paramsGlobal = {};
|
||||
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
|
||||
.param_group = DRM_ASAHI_GET_PARAMS,
|
||||
.pointer = (uint64_t) ¶msGlobal,
|
||||
.pointer = (uintptr_t) ¶msGlobal,
|
||||
.size = sizeof(paramsGlobal),
|
||||
}) >= 0)
|
||||
{
|
||||
|
||||
@@ -89,19 +89,19 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
|
||||
if (properties.device_type != CTL_DEVICE_TYPE_GRAPHICS)
|
||||
continue;
|
||||
|
||||
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_LUID)
|
||||
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
|
||||
{
|
||||
if (cond->luid == deviceId)
|
||||
if (cond->pciBusId.bus == properties.adapter_bdf.bus &&
|
||||
cond->pciBusId.device == properties.adapter_bdf.device &&
|
||||
cond->pciBusId.func == properties.adapter_bdf.function)
|
||||
{
|
||||
device = devices[iDev];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
|
||||
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_LUID)
|
||||
{
|
||||
if (cond->pciBusId.bus == properties.adapter_bdf.bus &&
|
||||
cond->pciBusId.device == properties.adapter_bdf.device &&
|
||||
cond->pciBusId.func == properties.adapter_bdf.function)
|
||||
if (cond->luid == deviceId)
|
||||
{
|
||||
device = devices[iDev];
|
||||
break;
|
||||
|
||||
@@ -29,11 +29,12 @@ struct FFNvapiData {
|
||||
FF_LIBRARY_SYMBOL(nvapi_Unload)
|
||||
FF_LIBRARY_SYMBOL(nvapi_EnumPhysicalGPUs)
|
||||
FF_LIBRARY_SYMBOL(nvapi_GPU_GetRamType)
|
||||
FF_LIBRARY_SYMBOL(nvapi_GPU_GetGPUType)
|
||||
|
||||
bool inited;
|
||||
} nvapiData;
|
||||
|
||||
static const char* detectMemTypeByNvapi(FFGpuDriverResult* result)
|
||||
static const char* detectMoreByNvapi(FFGpuDriverResult* result)
|
||||
{
|
||||
if (!nvapiData.inited)
|
||||
{
|
||||
@@ -55,6 +56,7 @@ static const char* detectMemTypeByNvapi(FFGpuDriverResult* result)
|
||||
FF_NVAPI_INTERFACE(nvapi_Unload, NVAPI_INTERFACE_OFFSET_UNLOAD)
|
||||
FF_NVAPI_INTERFACE(nvapi_EnumPhysicalGPUs, NVAPI_INTERFACE_OFFSET_ENUM_PHYSICAL_GPUS)
|
||||
FF_NVAPI_INTERFACE(nvapi_GPU_GetRamType, NVAPI_INTERFACE_OFFSET_GPU_GET_RAM_TYPE)
|
||||
FF_NVAPI_INTERFACE(nvapi_GPU_GetGPUType, NVAPI_INTERFACE_OFFSET_GPU_GET_GPU_TYPE)
|
||||
#undef FF_NVAPI_INTERFACE
|
||||
|
||||
if (ffnvapi_Initialize() < 0)
|
||||
@@ -62,6 +64,7 @@ static const char* detectMemTypeByNvapi(FFGpuDriverResult* result)
|
||||
|
||||
nvapiData.ffnvapi_EnumPhysicalGPUs = ffnvapi_EnumPhysicalGPUs;
|
||||
nvapiData.ffnvapi_GPU_GetRamType = ffnvapi_GPU_GetRamType;
|
||||
nvapiData.ffnvapi_GPU_GetGPUType = ffnvapi_GPU_GetGPUType;
|
||||
nvapiData.ffnvapi_Unload = ffnvapi_Unload;
|
||||
|
||||
atexit((void*) ffnvapi_Unload);
|
||||
@@ -86,36 +89,53 @@ static const char* detectMemTypeByNvapi(FFGpuDriverResult* result)
|
||||
NvPhysicalGpuHandle gpuHandle = handles[gpuIndex];
|
||||
|
||||
NvApiGPUMemoryType memType;
|
||||
if (nvapiData.ffnvapi_GPU_GetRamType(gpuHandle, &memType) < 0)
|
||||
return "NvAPI_GPU_GetRamType() failed";
|
||||
|
||||
switch (memType)
|
||||
if (result->memoryType && nvapiData.ffnvapi_GPU_GetRamType(gpuHandle, &memType) == 0)
|
||||
{
|
||||
#define FF_NVAPI_MEMORY_TYPE(type) \
|
||||
case NVAPI_GPU_MEMORY_TYPE_##type: \
|
||||
ffStrbufSetStatic(result->memoryType, #type); \
|
||||
switch (memType)
|
||||
{
|
||||
#define FF_NVAPI_MEMORY_TYPE(type) \
|
||||
case NVAPI_GPU_MEMORY_TYPE_##type: \
|
||||
ffStrbufSetStatic(result->memoryType, #type); \
|
||||
break;
|
||||
FF_NVAPI_MEMORY_TYPE(UNKNOWN)
|
||||
FF_NVAPI_MEMORY_TYPE(SDRAM)
|
||||
FF_NVAPI_MEMORY_TYPE(DDR1)
|
||||
FF_NVAPI_MEMORY_TYPE(DDR2)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR2)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR3)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR4)
|
||||
FF_NVAPI_MEMORY_TYPE(DDR3)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR5)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR2)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR5X)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR3)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR4)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR5)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR6)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR6X)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR7)
|
||||
#undef FF_NVAPI_MEMORY_TYPE
|
||||
default:
|
||||
ffStrbufSetF(result->memoryType, "Unknown (%d)", memType);
|
||||
break;
|
||||
FF_NVAPI_MEMORY_TYPE(UNKNOWN)
|
||||
FF_NVAPI_MEMORY_TYPE(SDRAM)
|
||||
FF_NVAPI_MEMORY_TYPE(DDR1)
|
||||
FF_NVAPI_MEMORY_TYPE(DDR2)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR2)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR3)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR4)
|
||||
FF_NVAPI_MEMORY_TYPE(DDR3)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR5)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR2)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR5X)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR3)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR4)
|
||||
FF_NVAPI_MEMORY_TYPE(LPDDR5)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR6)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR6X)
|
||||
FF_NVAPI_MEMORY_TYPE(GDDR7)
|
||||
#undef FF_NVAPI_MEMORY_TYPE
|
||||
default:
|
||||
ffStrbufSetF(result->memoryType, "Unknown (%d)", memType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NvApiGPUType gpuType;
|
||||
if (result->type && nvapiData.ffnvapi_GPU_GetGPUType(gpuHandle, &gpuType) == 0)
|
||||
{
|
||||
switch (gpuType)
|
||||
{
|
||||
case NV_SYSTEM_TYPE_IGPU:
|
||||
*result->type = FF_GPU_TYPE_INTEGRATED;
|
||||
break;
|
||||
case NV_SYSTEM_TYPE_DGPU:
|
||||
*result->type = FF_GPU_TYPE_DISCRETE;
|
||||
break;
|
||||
default:
|
||||
*result->type = FF_GPU_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -222,13 +242,13 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
{
|
||||
*result.index = value;
|
||||
#ifdef _WIN32
|
||||
// Don't bother loading nvapi for GPU type detection only
|
||||
if (result.memoryType)
|
||||
detectMemTypeByNvapi(&result);
|
||||
detectMoreByNvapi(&result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (result.temp)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
@@ -45,8 +45,10 @@ static const FFstrbuf* loadPciIds()
|
||||
if (pciids.length == 0)
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids);
|
||||
}
|
||||
#elif __FreeBSD__ || __OpenBSD__ || __NetBSD__
|
||||
#elif __FreeBSD__ || __NetBSD__
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids);
|
||||
#elif __OpenBSD__
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/hwdata/pci.ids", &pciids);
|
||||
#elif __sun
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
|
||||
#elif __HAIKU__
|
||||
|
||||
@@ -1,83 +1,57 @@
|
||||
#include "gpu.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
#include <libdevinfo.h>
|
||||
|
||||
static int walkDevTree(di_node_t node, FF_MAYBE_UNUSED di_minor_t minor, FFlist* gpus)
|
||||
{
|
||||
// SunOS requires root permission to query PCI device list, except `/usr/bin/scanpci`
|
||||
// Same behavior can be observed with `cp $(which scanpci) /tmp/ && /tmp/scanpci`
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) {
|
||||
"/usr/bin/scanpci",
|
||||
"-v",
|
||||
NULL,
|
||||
});
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!ffStrbufStartsWithS(&buffer, "\npci "))
|
||||
return "Invalid scanpci result";
|
||||
|
||||
// pci bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e
|
||||
// Device unknown
|
||||
// CardVendor 0x0000 card 0x0000 (Card unknown)
|
||||
// STATUS 0x0010 COMMAND 0x0007
|
||||
// CLASS 0x03 0x02 0x00 REVISION 0x00
|
||||
// BIST 0x00 HEADER 0x00 LATENCY 0x00 CACHE 0x00
|
||||
// MAX_LAT 0x00 MIN_GNT 0x00 INT_PIN 0x00 INT_LINE 0x00
|
||||
|
||||
for (
|
||||
const char* pclass = strstr(buffer.chars, "\n CLASS 0x03 ");
|
||||
pclass;
|
||||
pclass = strstr(pclass, "\n CLASS 0x03 ")
|
||||
)
|
||||
int* vendorId;
|
||||
int* deviceId;
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "vendor-id", &vendorId) > 0
|
||||
&& di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-id", &deviceId) > 0)
|
||||
{
|
||||
// find the start of device entry
|
||||
const char* pstart = memrchr(buffer.chars, '\n', (size_t) (pclass - buffer.chars));
|
||||
if (pstart == NULL)
|
||||
return "PCI info not found, invalid scanpci result";
|
||||
while (pstart[1] != 'p')
|
||||
{
|
||||
pstart = memrchr(buffer.chars, '\n', (size_t) (pstart - buffer.chars - 1));
|
||||
if (pstart == NULL)
|
||||
return "PCI info not found, invalid scanpci result";
|
||||
}
|
||||
++pstart;
|
||||
|
||||
uint32_t vendorId, deviceId;
|
||||
if (sscanf(pstart, "pci %*[^:]: vendor %x device %x",
|
||||
&vendorId, &deviceId) != 2)
|
||||
return "PCI info not found, invalid scanpci result";
|
||||
|
||||
pclass += strlen("\n CLASS 0x03 ");
|
||||
uint32_t subclass = (uint32_t) strtoul(pclass, NULL, 16);
|
||||
pclass += strlen("0x02 0x00 REVISION ");
|
||||
uint32_t revision = (uint32_t) strtoul(pclass, NULL, 16);
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
ffStrbufInitS(&gpu->vendor, ffGPUGetVendorString((uint16_t) *vendorId));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitStatic(&gpu->platformApi, "/usr/bin/scanpci");
|
||||
ffStrbufInitS(&gpu->driver, di_driver_name(node));
|
||||
ffStrbufInitStatic(&gpu->platformApi, "libdevinfo");
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = 0;
|
||||
gpu->deviceId = strtoul(di_bus_addr(node), NULL, 16);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffGPUQueryAmdGpuName((uint16_t) deviceId, (uint8_t) revision, gpu);
|
||||
{
|
||||
int* revId;
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "revision-id", &revId) > 0)
|
||||
ffGPUQueryAmdGpuName((uint16_t) *deviceId, (uint8_t) *revId, gpu);
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
ffGPUFillVendorAndName((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
uint8_t subclass = 0; // assume VGA
|
||||
int* classCode;
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "class-code", &classCode) > 0)
|
||||
subclass = (uint8_t) (*classCode & 0xFFFF);
|
||||
ffGPUFillVendorAndName(subclass, (uint16_t) *vendorId, (uint16_t) *deviceId, gpu);
|
||||
}
|
||||
}
|
||||
|
||||
return DI_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
di_node_t rootNode = di_init("/", DINFOCPYALL);
|
||||
if (rootNode == DI_NODE_NIL)
|
||||
return "di_init() failed";
|
||||
di_walk_minor(rootNode, DDI_NT_DISPLAY, DI_WALK_CLDFIRST, gpus, (void*) walkDevTree);
|
||||
di_fini(rootNode);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+193
-84
@@ -1,18 +1,15 @@
|
||||
#include "gpu.h"
|
||||
#include "common/library.h"
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#define INITGUID
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <devguid.h>
|
||||
|
||||
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
{
|
||||
if(*hdev)
|
||||
SetupDiDestroyDeviceInfoList(*hdev);
|
||||
}
|
||||
#include <cfgmgr32.h>
|
||||
#include <ntddvdeo.h>
|
||||
#include <devpkey.h>
|
||||
#include "util/windows/nt.h"
|
||||
|
||||
#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}"
|
||||
enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 };
|
||||
@@ -24,21 +21,38 @@ const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\C
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
|
||||
ULONG devInfListSize = 0;
|
||||
if (CM_Get_Device_Interface_List_SizeW(&devInfListSize, (LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || devInfListSize <= 1)
|
||||
return "No display devices found";
|
||||
|
||||
if(hdev == INVALID_HANDLE_VALUE)
|
||||
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed";
|
||||
FF_AUTO_FREE DEVINSTID_W devInfList = malloc(devInfListSize * sizeof(*devInfList));
|
||||
|
||||
SP_DEVINFO_DATA did = { .cbSize = sizeof(did) };
|
||||
for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev)
|
||||
if (CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, devInfList, devInfListSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
|
||||
return "CM_Get_Device_Interface_ListW failed";
|
||||
|
||||
for (wchar_t* devInf = devInfList; *devInf; devInf += wcslen(devInf) + 1)
|
||||
{
|
||||
if (wcsncmp(devInf, L"\\\\?\\ROOT#BasicDisplay#", 22) == 0)
|
||||
continue; // Skip Microsoft Basic Display Adapter
|
||||
|
||||
DEVINST devInst = 0;
|
||||
wchar_t buffer[256];
|
||||
ULONG bufferLen = 0;
|
||||
|
||||
{
|
||||
DEVPROPTYPE propertyType;
|
||||
bufferLen = sizeof(buffer);
|
||||
if (CM_Get_Device_Interface_PropertyW(devInf, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &bufferLen, 0) != CR_SUCCESS ||
|
||||
CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS)
|
||||
continue;
|
||||
}
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
ffStrbufInitStatic(&gpu->platformApi, "SetupAPI");
|
||||
ffStrbufInitStatic(&gpu->platformApi, "CM API");
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
@@ -48,86 +62,91 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
gpu->deviceId = 0;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0;
|
||||
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) &&
|
||||
SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL))
|
||||
{
|
||||
pciDev = (pciAddr >> 16) & 0xFFFF;
|
||||
pciFunc = pciAddr & 0xFFFF;
|
||||
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
|
||||
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
|
||||
}
|
||||
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
|
||||
if (swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4)
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
|
||||
wchar_t buffer[256];
|
||||
uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0;
|
||||
|
||||
ULONG pciBufLen = sizeof(pciBus);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_BUSNUMBER, NULL, &pciBus, &pciBufLen, 0) == CR_SUCCESS)
|
||||
{
|
||||
pciBufLen = sizeof(pciAddr);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_ADDRESS, NULL, &pciAddr, &pciBufLen, 0) == CR_SUCCESS)
|
||||
{
|
||||
pciDev = (pciAddr >> 16) & 0xFFFF;
|
||||
pciFunc = pciAddr & 0xFFFF;
|
||||
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
|
||||
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t adapterLuid = 0;
|
||||
|
||||
FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
|
||||
if (!hVideoIdKey) continue;
|
||||
DWORD bufferLen = sizeof(buffer);
|
||||
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
|
||||
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
|
||||
FF_HKEY_AUTO_DESTROY hVideoIdKey = NULL;
|
||||
if (CM_Open_DevNode_Key(devInst, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hVideoIdKey, CM_REGISTRY_HARDWARE) == CR_SUCCESS)
|
||||
{
|
||||
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
|
||||
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
|
||||
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
|
||||
bufferLen = sizeof(buffer);
|
||||
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
|
||||
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
|
||||
{
|
||||
uint32_t vendorId = 0;
|
||||
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
|
||||
uint64_t dedicatedVideoMemory = 0;
|
||||
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
|
||||
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
|
||||
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
|
||||
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
if (gpu->vendor.length == 0)
|
||||
{
|
||||
uint32_t vendorId = 0;
|
||||
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
}
|
||||
|
||||
uint64_t dedicatedSystemMemory, sharedSystemMemory;
|
||||
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
|
||||
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
|
||||
{
|
||||
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
|
||||
gpu->shared.total = sharedSystemMemory;
|
||||
}
|
||||
ffRegReadStrbuf(hDirectxKey, L"Description", &gpu->name, NULL);
|
||||
|
||||
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL))
|
||||
{
|
||||
if (!gpu->deviceId) gpu->deviceId = adapterLuid;
|
||||
}
|
||||
ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &gpu->dedicated.total, NULL);
|
||||
if (ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &gpu->shared.total, NULL))
|
||||
{
|
||||
uint64_t sharedSystemMemory = 0;
|
||||
if (ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
|
||||
gpu->shared.total += sharedSystemMemory;
|
||||
}
|
||||
|
||||
uint32_t featureLevel = 0;
|
||||
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
|
||||
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
|
||||
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
|
||||
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
|
||||
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL))
|
||||
{
|
||||
if (!gpu->deviceId) gpu->deviceId = adapterLuid;
|
||||
}
|
||||
|
||||
uint64_t driverVersion = 0;
|
||||
if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion)
|
||||
{
|
||||
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u",
|
||||
(unsigned) (driverVersion >> 48) & 0xFFFF,
|
||||
(unsigned) (driverVersion >> 32) & 0xFFFF,
|
||||
(unsigned) (driverVersion >> 16) & 0xFFFF,
|
||||
(unsigned) (driverVersion >> 0) & 0xFFFF
|
||||
);
|
||||
uint32_t featureLevel = 0;
|
||||
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
|
||||
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
|
||||
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
|
||||
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
|
||||
|
||||
uint64_t driverVersion = 0;
|
||||
if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion)
|
||||
{
|
||||
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u",
|
||||
(unsigned) (driverVersion >> 48) & 0xFFFF,
|
||||
(unsigned) (driverVersion >> 32) & 0xFFFF,
|
||||
(unsigned) (driverVersion >> 16) & 0xFFFF,
|
||||
(unsigned) (driverVersion >> 0) & 0xFFFF
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu->vendor.length == 0)
|
||||
if (gpu->vendor.length == 0 || gpu->name.length == 0)
|
||||
{
|
||||
bufferLen = sizeof(buffer);
|
||||
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DRIVER, NULL, (PBYTE) buffer, sizeof(buffer), &bufferLen) && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2)
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DRIVER, NULL, buffer, &bufferLen, 0) == CR_SUCCESS &&
|
||||
bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2)
|
||||
{
|
||||
wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000"));
|
||||
FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL;
|
||||
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDriverKey, &hRegDriverKey, NULL))
|
||||
{
|
||||
if (ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL))
|
||||
if (gpu->vendor.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL))
|
||||
{
|
||||
if (ffStrbufContainS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
@@ -136,6 +155,19 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
}
|
||||
if (gpu->name.length == 0)
|
||||
ffRegReadStrbuf(hRegDriverKey, L"DriverDesc", &gpu->name, NULL);
|
||||
if (gpu->driver.length == 0)
|
||||
ffRegReadStrbuf(hRegDriverKey, L"DriverVersion", &gpu->driver, NULL);
|
||||
if (gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
if (!ffRegReadUint64(hRegDriverKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
|
||||
{
|
||||
uint32_t memorySize = 0;
|
||||
if (ffRegReadUint(hRegDriverKey, L"HardwareInformation.MemorySize", &memorySize, NULL))
|
||||
gpu->dedicated.total = memorySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,18 +175,11 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
||||
const char* dllName;
|
||||
|
||||
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific))
|
||||
if (options->driverSpecific && getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName))
|
||||
{
|
||||
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
|
||||
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
|
||||
{
|
||||
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
|
||||
}
|
||||
|
||||
detectFn(
|
||||
&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID
|
||||
.type = (deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID : 0)
|
||||
| (adapterLuid > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0)
|
||||
| (pciAddr > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0),
|
||||
.pciDeviceId = {
|
||||
@@ -189,9 +214,93 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
|
||||
if (!gpu->name.length)
|
||||
{
|
||||
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
|
||||
bufferLen = sizeof(buffer);
|
||||
if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DEVICEDESC, NULL, buffer, &bufferLen, 0) == CR_SUCCESS)
|
||||
ffStrbufSetWS(&gpu->name, buffer);
|
||||
}
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN && adapterLuid > 0)
|
||||
{
|
||||
HMODULE hgdi32 = GetModuleHandleW(L"gdi32.dll");
|
||||
if (hgdi32)
|
||||
{
|
||||
FF_LIBRARY_LOAD_SYMBOL_LAZY(hgdi32, D3DKMTOpenAdapterFromLuid);
|
||||
if (ffD3DKMTOpenAdapterFromLuid) // Windows 8 and later
|
||||
{
|
||||
D3DKMT_OPENADAPTERFROMLUID openAdapterFromLuid = { .AdapterLuid = *(LUID*)&adapterLuid };
|
||||
if (NT_SUCCESS(ffD3DKMTOpenAdapterFromLuid(&openAdapterFromLuid)))
|
||||
{
|
||||
D3DKMT_ADAPTERTYPE adapterType = {};
|
||||
D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {
|
||||
.hAdapter = openAdapterFromLuid.hAdapter,
|
||||
.Type = KMTQAITYPE_ADAPTERTYPE,
|
||||
.pPrivateDriverData = &adapterType,
|
||||
.PrivateDriverDataSize = sizeof(adapterType),
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) // Vista and later
|
||||
{
|
||||
if (adapterType.HybridDiscrete)
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
else if (adapterType.HybridIntegrated)
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
|
||||
if (gpu->frequency == FF_GPU_FREQUENCY_UNSET)
|
||||
{
|
||||
for (ULONG nodeIdx = 0; ; nodeIdx++)
|
||||
{
|
||||
D3DKMT_NODEMETADATA nodeMetadata = {
|
||||
.NodeOrdinalAndAdapterIndex = (0 << 16) | nodeIdx,
|
||||
};
|
||||
queryAdapterInfo = (D3DKMT_QUERYADAPTERINFO) {
|
||||
.hAdapter = openAdapterFromLuid.hAdapter,
|
||||
.Type = KMTQAITYPE_NODEMETADATA,
|
||||
.pPrivateDriverData = &nodeMetadata,
|
||||
.PrivateDriverDataSize = sizeof(nodeMetadata),
|
||||
};
|
||||
if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) break; // Windows 10 and later
|
||||
if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) continue;
|
||||
|
||||
D3DKMT_QUERYSTATISTICS queryStatistics = {
|
||||
.Type = D3DKMT_QUERYSTATISTICS_NODE2,
|
||||
.AdapterLuid = *(LUID*)&adapterLuid,
|
||||
.QueryNode2 = { .PhysicalAdapterIndex = 0, .NodeOrdinal = (UINT16) nodeIdx },
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) // Windows 11 (22H2) and later
|
||||
{
|
||||
gpu->frequency = (uint32_t) (queryStatistics.QueryResult.NodeInformation.NodePerfData.MaxFrequency / 1000 / 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter };
|
||||
(void) D3DKMTCloseAdapter(&closeAdapter);
|
||||
openAdapterFromLuid.hAdapter = 0;
|
||||
}
|
||||
|
||||
if (options->temp && gpu->temperature != gpu->temperature)
|
||||
{
|
||||
D3DKMT_QUERYSTATISTICS queryStatistics = {
|
||||
.Type = D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER,
|
||||
.AdapterLuid = *(LUID*)&adapterLuid,
|
||||
.QueryPhysAdapter = { .PhysicalAdapterIndex = 0 },
|
||||
};
|
||||
if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)) &&
|
||||
queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0)
|
||||
gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
else if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
gpu->type = gpu->dedicated.total >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -23,6 +23,13 @@ typedef enum NvApiGPUMemoryType
|
||||
NVAPI_GPU_MEMORY_TYPE_GDDR7,
|
||||
} NvApiGPUMemoryType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NV_SYSTEM_TYPE_GPU_UNKNOWN = 0,
|
||||
NV_SYSTEM_TYPE_IGPU = 1, // Integrated
|
||||
NV_SYSTEM_TYPE_DGPU = 2, // Discrete
|
||||
} NvApiGPUType;
|
||||
|
||||
typedef int NvAPI_Status; // 0 = success; < 0 = error
|
||||
typedef struct NvPhysicalGpuHandle* NvPhysicalGpuHandle;
|
||||
|
||||
@@ -32,6 +39,7 @@ typedef enum
|
||||
NVAPI_INTERFACE_OFFSET_UNLOAD = 0xD22BDD7E,
|
||||
NVAPI_INTERFACE_OFFSET_ENUM_PHYSICAL_GPUS = 0xE5AC921F,
|
||||
NVAPI_INTERFACE_OFFSET_GPU_GET_RAM_TYPE = 0x57F7CAAC,
|
||||
NVAPI_INTERFACE_OFFSET_GPU_GET_GPU_TYPE = 0xC33BAEB1,
|
||||
|
||||
NVAPI_INTERFACE_OFFSET_FORCE_UINT32 = 0xFFFFFFFF
|
||||
} NvApiInterfaceOffsets;
|
||||
@@ -42,3 +50,4 @@ extern NvAPI_Status nvapi_Initialize(void);
|
||||
extern NvAPI_Status nvapi_Unload(void);
|
||||
extern NvAPI_Status nvapi_EnumPhysicalGPUs(NvPhysicalGpuHandle* handles, int* count);
|
||||
extern NvAPI_Status nvapi_GPU_GetRamType(NvPhysicalGpuHandle handle, NvApiGPUMemoryType* memtype);
|
||||
extern NvAPI_Status nvapi_GPU_GetGPUType(NvPhysicalGpuHandle handle, NvApiGPUType* gpuType);
|
||||
|
||||
@@ -1,50 +1,35 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/media/media.h"
|
||||
#include "common/library.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/apple/osascript.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
// https://github.com/andrewwiik/iOS-Blocks/blob/master/Widgets/Music/MediaRemote.h
|
||||
extern void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t dispatcher, void(^callback)(_Nullable CFDictionaryRef info)) __attribute__((weak_import));
|
||||
extern void MRMediaRemoteGetNowPlayingClient(dispatch_queue_t dispatcher, void (^callback)(_Nullable id clientObj)) __attribute__((weak_import));
|
||||
extern CFStringRef MRNowPlayingClientGetBundleIdentifier(id clientObj) __attribute__((weak_import));
|
||||
extern CFStringRef MRNowPlayingClientGetParentAppBundleIdentifier(id clientObj) __attribute__((weak_import));
|
||||
void MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_queue_t queue, void (^callback)(BOOL playing)) __attribute__((weak_import));
|
||||
extern void MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_queue_t queue, void (^callback)(BOOL playing)) __attribute__((weak_import));
|
||||
extern void MRMediaRemoteGetNowPlayingApplicationDisplayID(dispatch_queue_t queue, void (^callback)(_Nullable CFStringRef displayID)) __attribute__((weak_import));
|
||||
extern void MRMediaRemoteGetNowPlayingApplicationDisplayName(int unknown, dispatch_queue_t queue, void (^callback)(_Nullable CFStringRef name)) __attribute__((weak_import));
|
||||
|
||||
static const char* getMediaByMediaRemote(FFMediaResult* result)
|
||||
{
|
||||
#define FF_TEST_FN_EXISTANCE(fn) if (!fn) return "MediaRemote function " #fn " is not available"
|
||||
FF_TEST_FN_EXISTANCE(MRMediaRemoteGetNowPlayingInfo);
|
||||
FF_TEST_FN_EXISTANCE(MRMediaRemoteGetNowPlayingClient);
|
||||
FF_TEST_FN_EXISTANCE(MRNowPlayingClientGetBundleIdentifier);
|
||||
FF_TEST_FN_EXISTANCE(MRNowPlayingClientGetParentAppBundleIdentifier);
|
||||
FF_TEST_FN_EXISTANCE(MRMediaRemoteGetNowPlayingApplicationIsPlaying);
|
||||
#undef FF_TEST_FN_EXISTANCE
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
|
||||
|
||||
dispatch_group_enter(group);
|
||||
MRMediaRemoteGetNowPlayingApplicationIsPlaying(queue, ^(BOOL playing) {
|
||||
ffStrbufSetStatic(&result->status, playing ? "Playing" : "Paused");
|
||||
dispatch_group_leave(group);
|
||||
});
|
||||
|
||||
dispatch_group_enter(group);
|
||||
__block const char* error = NULL;
|
||||
MRMediaRemoteGetNowPlayingInfo(queue, ^(_Nullable CFDictionaryRef info) {
|
||||
if(info != nil)
|
||||
{
|
||||
error = ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song);
|
||||
if(!error)
|
||||
{
|
||||
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist);
|
||||
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album);
|
||||
}
|
||||
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song);
|
||||
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist);
|
||||
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album);
|
||||
}
|
||||
else
|
||||
error = "MRMediaRemoteGetNowPlayingInfo() failed";
|
||||
@@ -53,42 +38,76 @@ static const char* getMediaByMediaRemote(FFMediaResult* result)
|
||||
});
|
||||
|
||||
dispatch_group_enter(group);
|
||||
MRMediaRemoteGetNowPlayingClient(queue, ^(_Nullable id clientObj) {
|
||||
if (clientObj != nil)
|
||||
{
|
||||
CFStringRef identifier = MRNowPlayingClientGetBundleIdentifier(clientObj);
|
||||
if (identifier == nil)
|
||||
identifier = MRNowPlayingClientGetParentAppBundleIdentifier(clientObj);
|
||||
if (identifier != nil)
|
||||
ffCfStrGetString(identifier, &result->playerId);
|
||||
}
|
||||
MRMediaRemoteGetNowPlayingApplicationIsPlaying(queue, ^(BOOL playing) {
|
||||
ffStrbufSetStatic(&result->status, playing ? "Playing" : "Paused");
|
||||
dispatch_group_leave(group);
|
||||
});
|
||||
|
||||
if (MRMediaRemoteGetNowPlayingApplicationDisplayID)
|
||||
{
|
||||
dispatch_group_enter(group);
|
||||
MRMediaRemoteGetNowPlayingApplicationDisplayID(queue, ^(_Nullable CFStringRef displayID) {
|
||||
ffCfStrGetString(displayID, &result->playerId);
|
||||
dispatch_group_leave(group);
|
||||
});
|
||||
}
|
||||
|
||||
if (MRMediaRemoteGetNowPlayingApplicationDisplayName)
|
||||
{
|
||||
dispatch_group_enter(group);
|
||||
MRMediaRemoteGetNowPlayingApplicationDisplayName(0, queue, ^(_Nullable CFStringRef name) {
|
||||
ffCfStrGetString(name, &result->player);
|
||||
dispatch_group_leave(group);
|
||||
});
|
||||
}
|
||||
|
||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
||||
// Don't dispatch_release because we are using ARC
|
||||
|
||||
if(result->playerId.length > 0)
|
||||
{
|
||||
char buf[128];
|
||||
snprintf(buf, ARRAY_SIZE(buf), "name of app id \"%s\"", result->playerId.chars);
|
||||
ffOsascript(buf, &result->player);
|
||||
}
|
||||
|
||||
if(result->song.length > 0)
|
||||
return NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* getMediaByOsascript(FFMediaResult* result)
|
||||
__attribute__((visibility("default"), used))
|
||||
int ffPrintMediaByMediaRemote(void)
|
||||
{
|
||||
FFMediaResult media = {
|
||||
.status = ffStrbufCreate(),
|
||||
.song = ffStrbufCreate(),
|
||||
.artist = ffStrbufCreate(),
|
||||
.album = ffStrbufCreate(),
|
||||
.playerId = ffStrbufCreate(),
|
||||
.player = ffStrbufCreate(),
|
||||
};
|
||||
if (getMediaByMediaRemote(&media) != NULL)
|
||||
return 1;
|
||||
ffStrbufPutTo(&media.status, stdout);
|
||||
ffStrbufPutTo(&media.song, stdout);
|
||||
ffStrbufPutTo(&media.artist, stdout);
|
||||
ffStrbufPutTo(&media.album, stdout);
|
||||
ffStrbufPutTo(&media.playerId, stdout);
|
||||
ffStrbufPutTo(&media.player, stdout);
|
||||
ffStrbufDestroy(&media.status);
|
||||
ffStrbufDestroy(&media.song);
|
||||
ffStrbufDestroy(&media.artist);
|
||||
ffStrbufDestroy(&media.album);
|
||||
ffStrbufDestroy(&media.playerId);
|
||||
ffStrbufDestroy(&media.player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* getMediaByAuthorizedProcess(FFMediaResult* result)
|
||||
{
|
||||
// #1737
|
||||
FF_STRBUF_AUTO_DESTROY script = ffStrbufCreateF("import ctypes;ctypes.CDLL('%s').ffPrintMediaByMediaRemote()", instance.state.platform.exePath.chars);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
// The script must be executed by `/usr/bin/osascript`. `ffOsascript` doesn't work here
|
||||
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) {
|
||||
"/usr/bin/osascript",
|
||||
"-e",
|
||||
FASTFETCH_DATATEXT_NOWPLAYING,
|
||||
"/usr/bin/python3", // Must be signed by Apple. Homebrew python doesn't work
|
||||
"-c",
|
||||
script.chars,
|
||||
nil
|
||||
});
|
||||
if (error) return error;
|
||||
@@ -107,8 +126,16 @@ void ffDetectMediaImpl(FFMediaResult* media)
|
||||
{
|
||||
const char* error;
|
||||
if (@available(macOS 15.4, *))
|
||||
error = getMediaByOsascript(media);
|
||||
error = getMediaByAuthorizedProcess(media);
|
||||
else
|
||||
error = getMediaByMediaRemote(media);
|
||||
if (error) ffStrbufAppendS(&media->error, error);
|
||||
if (error)
|
||||
ffStrbufAppendS(&media->error, error);
|
||||
else if (media->player.length == 0 && media->playerId.length > 0)
|
||||
{
|
||||
ffStrbufSet(&media->player, &media->playerId);
|
||||
if (ffStrbufStartsWithIgnCaseS(&media->player, "com."))
|
||||
ffStrbufSubstrAfter(&media->player, strlen("com.") - 1);
|
||||
ffStrbufReplaceAllC(&media->player, '.', ' ');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ static void parseSystemVersion(FFOSResult* os)
|
||||
ffStrbufInitS(&os->version, value.UTF8String);
|
||||
if((value = dict[@"ProductBuildVersion"]))
|
||||
ffStrbufInitS(&os->buildID, value.UTF8String);
|
||||
if (ffStrbufStartsWithS(&os->version, "16."))
|
||||
{
|
||||
// macOS 26 Tahoe. #1809
|
||||
os->version.chars[0] = '2';
|
||||
}
|
||||
}
|
||||
|
||||
static bool detectOSCodeName(FFOSResult* os)
|
||||
@@ -64,7 +69,7 @@ static bool detectOSCodeName(FFOSResult* os)
|
||||
case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); return true;
|
||||
case 5: ffStrbufSetStatic(&os->codename, "Leopard"); return true;
|
||||
case 4: ffStrbufSetStatic(&os->codename, "Tiger"); return true;
|
||||
case 3: ffStrbufSetStatic(&os->codename, "Panther"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true;
|
||||
case 3: ffStrbufSetStatic(&os->codename, "Panther"); return true;
|
||||
case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); return true;
|
||||
case 1: ffStrbufSetStatic(&os->codename, "Puma"); return true;
|
||||
case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); return true;
|
||||
|
||||
+104
-70
@@ -47,7 +47,7 @@ FF_MAYBE_UNUSED static bool detectArmbianVersion(FFOSResult* result)
|
||||
// - `Armbian_Security` for images with kali repo added
|
||||
// - `Armbian-unofficial` for an unofficial image built from source, e.g. during development and testing
|
||||
if (ffStrbufStartsWithS(&result->prettyName, "Armbian"))
|
||||
ffStrbufSetS(&result->name, "Armbian");
|
||||
ffStrbufSetStatic(&result->name, "Armbian");
|
||||
else
|
||||
return false;
|
||||
ffStrbufSet(&result->idLike, &result->id);
|
||||
@@ -69,113 +69,113 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
|
||||
return;
|
||||
else if(ffStrbufStartsWithS(&result->prettyName, "Linux Lite "))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Linux Lite");
|
||||
ffStrbufSetS(&result->id, "linuxlite");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Linux Lite");
|
||||
ffStrbufSetStatic(&result->id, "linuxlite");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Linux Lite "));
|
||||
return;
|
||||
}
|
||||
else if(ffStrbufStartsWithS(&result->prettyName, "Rhino Linux "))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Rhino Linux");
|
||||
ffStrbufSetS(&result->id, "rhinolinux");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Rhino Linux");
|
||||
ffStrbufSetStatic(&result->id, "rhinolinux");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Rhino Linux "));
|
||||
return;
|
||||
}
|
||||
else if(ffStrbufStartsWithS(&result->prettyName, "VanillaOS "))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "vanilla");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->id, "vanilla");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Kubuntu");
|
||||
ffStrbufSetS(&result->prettyName, "Kubuntu");
|
||||
ffStrbufSetS(&result->id, "kubuntu");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Kubuntu");
|
||||
ffStrbufSetF(&result->prettyName, "Kubuntu %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "kubuntu");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "xfce") || ffStrContains(xdgConfigDirs, "xubuntu"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Xubuntu");
|
||||
ffStrbufSetS(&result->prettyName, "Xubuntu");
|
||||
ffStrbufSetS(&result->id, "xubuntu");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Xubuntu");
|
||||
ffStrbufSetF(&result->prettyName, "Xubuntu %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "xubuntu");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "lxqt") || ffStrContains(xdgConfigDirs, "lubuntu"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Lubuntu");
|
||||
ffStrbufSetS(&result->prettyName, "Lubuntu");
|
||||
ffStrbufSetS(&result->id, "lubuntu");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Lubuntu");
|
||||
ffStrbufSetF(&result->prettyName, "Lubuntu %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "lubuntu");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "budgie"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Budgie");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Budgie");
|
||||
ffStrbufSetS(&result->id, "ubuntu-budgie");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Ubuntu Budgie");
|
||||
ffStrbufSetF(&result->prettyName, "Ubuntu Budgie %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "ubuntu-budgie");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "cinnamon"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Cinnamon");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Cinnamon");
|
||||
ffStrbufSetS(&result->id, "ubuntu-cinnamon");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Ubuntu Cinnamon");
|
||||
ffStrbufSetF(&result->prettyName, "Ubuntu Cinnamon %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "ubuntu-cinnamon");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "mate"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu MATE");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu MATE");
|
||||
ffStrbufSetS(&result->id, "ubuntu-mate");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Ubuntu MATE");
|
||||
ffStrbufSetF(&result->prettyName, "Ubuntu MATE %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "ubuntu-mate");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "studio"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Studio");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Studio");
|
||||
ffStrbufSetS(&result->id, "ubuntu-studio");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Ubuntu Studio");
|
||||
ffStrbufSetF(&result->prettyName, "Ubuntu Studio %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "ubuntu-studio");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "sway"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Sway");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Sway");
|
||||
ffStrbufSetS(&result->id, "ubuntu-sway");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Ubuntu Sway");
|
||||
ffStrbufSetF(&result->prettyName, "Ubuntu Sway %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "ubuntu-sway");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "touch"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Ubuntu Touch");
|
||||
ffStrbufSetS(&result->prettyName, "Ubuntu Touch");
|
||||
ffStrbufSetS(&result->id, "ubuntu-touch");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "Ubuntu Touch");
|
||||
ffStrbufSetF(&result->prettyName, "Ubuntu Touch %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "ubuntu-touch");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "lliurex"))
|
||||
{
|
||||
ffStrbufSetS(&result->name, "LliureX");
|
||||
ffStrbufSetS(&result->prettyName, "LliureX");
|
||||
ffStrbufSetS(&result->id, "lliurex");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
ffStrbufSetStatic(&result->name, "LliureX");
|
||||
ffStrbufSetF(&result->prettyName, "LliureX %s", result->version.chars);
|
||||
ffStrbufSetStatic(&result->id, "lliurex");
|
||||
ffStrbufSetStatic(&result->idLike, "ubuntu");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -196,8 +196,8 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
|
||||
return true;
|
||||
else if (ffStrbufStartsWithS(&result->name, "Loc-OS"))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "locos");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetStatic(&result->id, "locos");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
return true;
|
||||
}
|
||||
else if (ffStrbufEqualS(&result->name, "Parrot Security"))
|
||||
@@ -210,15 +210,15 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
|
||||
else if (ffStrbufStartsWithS(&result->name, "Lilidog GNU/Linux"))
|
||||
{
|
||||
// https://github.com/fastfetch-cli/fastfetch/issues/1373
|
||||
ffStrbufSetS(&result->id, "lilidog");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetStatic(&result->id, "lilidog");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
return true;
|
||||
}
|
||||
else if (access("/usr/bin/pveversion", X_OK) == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->id, "pve");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "Proxmox VE");
|
||||
ffStrbufSetStatic(&result->id, "pve");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
ffStrbufSetStatic(&result->name, "Proxmox VE");
|
||||
ffStrbufClear(&result->versionID);
|
||||
if (ffProcessAppendStdOut(&result->versionID, (char* const[]) {
|
||||
"/usr/bin/dpkg-query",
|
||||
@@ -231,22 +231,39 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
|
||||
ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars);
|
||||
return true;
|
||||
}
|
||||
else if (ffStrbufContainS(&instance.state.platform.sysinfo.release, "+rpt-rpi-"))
|
||||
else if (ffPathExists("/etc/rpi-issue", FF_PATHTYPE_FILE))
|
||||
{
|
||||
// Raspberry Pi OS
|
||||
ffStrbufSetS(&result->id, "raspbian");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "Raspberry Pi OS");
|
||||
ffStrbufSetS(&result->prettyName, "Raspberry Pi OS");
|
||||
ffStrbufSetStatic(&result->id, "raspbian");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
ffStrbufSetStatic(&result->name, "Raspberry Pi OS");
|
||||
ffStrbufSetStatic(&result->prettyName, "Raspberry Pi OS");
|
||||
return true;
|
||||
}
|
||||
else if (ffPathExists("/boot/dietpi/.version", FF_PATHTYPE_FILE))
|
||||
{
|
||||
// DietPi
|
||||
ffStrbufSetStatic(&result->id, "dietpi");
|
||||
ffStrbufSetStatic(&result->name, "DietPi");
|
||||
ffStrbufSetStatic(&result->prettyName, "DietPi");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
FF_STRBUF_AUTO_DESTROY core = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY sub = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY rc = ffStrbufCreate();
|
||||
if (ffParsePropFileValues("/boot/dietpi/.version", 3, (FFpropquery[]) {
|
||||
{"G_DIETPI_VERSION_CORE=", &core},
|
||||
{"G_DIETPI_VERSION_SUB=", &sub},
|
||||
{"G_DIETPI_VERSION_RC=", &rc},
|
||||
})) ffStrbufAppendF(&result->prettyName, " %s.%s.%s", core.chars, sub.chars, rc.chars);
|
||||
return true;
|
||||
}
|
||||
else if (ffStrbufEndsWithS(&instance.state.platform.sysinfo.release, "+truenas"))
|
||||
{
|
||||
// TrueNAS Scale
|
||||
ffStrbufSetS(&result->id, "truenas-scale");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "TrueNAS Scale");
|
||||
ffStrbufSetS(&result->prettyName, "TrueNAS Scale");
|
||||
ffStrbufSetStatic(&result->id, "truenas-scale");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
ffStrbufSetStatic(&result->name, "TrueNAS Scale");
|
||||
ffStrbufSetStatic(&result->prettyName, "TrueNAS Scale");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -255,9 +272,9 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
|
||||
FF_STRBUF_AUTO_DESTROY lsbRelease = ffStrbufCreate();
|
||||
if (ffAppendFileBuffer("/etc/lsb-release", &lsbRelease) && ffStrbufContainS(&lsbRelease, "DISTRIB_ID=MX"))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "mx");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "MX");
|
||||
ffStrbufSetStatic(&result->id, "mx");
|
||||
ffStrbufSetStatic(&result->idLike, "debian");
|
||||
ffStrbufSetStatic(&result->name, "MX");
|
||||
|
||||
ffStrbufClear(&result->version);
|
||||
ffParsePropLines(lsbRelease.chars, "DISTRIB_RELEASE=", &result->version);
|
||||
@@ -274,6 +291,21 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
|
||||
return false;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool detectFedoraVariant(FFOSResult* result)
|
||||
{
|
||||
if (ffStrbufEqualS(&result->variantID, "coreos")
|
||||
|| ffStrbufEqualS(&result->variantID, "kinoite")
|
||||
|| ffStrbufEqualS(&result->variantID, "sericea")
|
||||
|| ffStrbufEqualS(&result->variantID, "silverblue"))
|
||||
{
|
||||
ffStrbufAppendC(&result->id, '-');
|
||||
ffStrbufAppend(&result->id, &result->variantID);
|
||||
ffStrbufSetStatic(&result->idLike, "fedora");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectOS(FFOSResult* os)
|
||||
{
|
||||
#ifdef FF_CUSTOM_OS_RELEASE_PATH
|
||||
@@ -324,13 +356,15 @@ void ffDetectOSImpl(FFOSResult* os)
|
||||
detectOS(os);
|
||||
|
||||
#ifdef __linux__
|
||||
if(ffStrbufIgnCaseEqualS(&os->id, "ubuntu"))
|
||||
if(ffStrbufEqualS(&os->id, "ubuntu"))
|
||||
getUbuntuFlavour(os);
|
||||
else if(ffStrbufIgnCaseEqualS(&os->id, "debian"))
|
||||
else if(ffStrbufEqualS(&os->id, "debian"))
|
||||
{
|
||||
if (!detectDebianDerived(os))
|
||||
getDebianVersion(os);
|
||||
}
|
||||
else if(ffStrbufEqualS(&os->id, "fedora"))
|
||||
detectFedoraVariant(os);
|
||||
else if(ffStrbufEqualS(&os->id, "linuxmint"))
|
||||
{
|
||||
if (ffStrbufEqualS(&os->name, "LMDE"))
|
||||
|
||||
@@ -646,33 +646,30 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
#endif
|
||||
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
{
|
||||
// check if ~/.nix-profile exists
|
||||
FF_STRBUF_AUTO_DESTROY profilePath = ffStrbufCreateCopy(&baseDir);
|
||||
ffStrbufAppendS(&profilePath, ".nix-profile");
|
||||
if (ffPathExists(profilePath.chars, FF_PATHTYPE_DIRECTORY))
|
||||
{
|
||||
result->nixUser += getNixPackages(&baseDir, ".nix-profile");
|
||||
}
|
||||
// Count packages from $HOME/.nix-profile
|
||||
result->nixUser += getNixPackages(&baseDir, ".nix-profile");
|
||||
|
||||
// check if $XDG_STATE_HOME/nix/profile exists
|
||||
FF_STRBUF_AUTO_DESTROY stateDir = ffStrbufCreate();
|
||||
const char* stateHome = getenv("XDG_STATE_HOME");
|
||||
if(ffStrSet(stateHome))
|
||||
// Check in $XDG_STATE_HOME/nix/profile
|
||||
FF_STRBUF_AUTO_DESTROY stateHome = ffStrbufCreate();
|
||||
const char* stateHomeEnv = getenv("XDG_STATE_HOME");
|
||||
if (ffStrSet(stateHomeEnv))
|
||||
{
|
||||
ffStrbufSetS(&stateDir, stateHome);
|
||||
ffStrbufEnsureEndsWithC(&stateDir, '/');
|
||||
ffStrbufSetS(&stateHome, stateHomeEnv);
|
||||
ffStrbufEnsureEndsWithC(&stateHome, '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSet(&stateDir, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&stateDir, ".local/state/");
|
||||
ffStrbufSet(&stateHome, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&stateHome, ".local/state/");
|
||||
}
|
||||
result->nixUser += getNixPackages(&stateHome, "nix/profile");
|
||||
|
||||
ffStrbufSet(&profilePath, &stateDir);
|
||||
ffStrbufAppendS(&profilePath, "nix/profile");
|
||||
result->nixUser += getNixPackages(&stateDir, "nix/profile");
|
||||
// Check in /etc/profiles/per-user/$USER
|
||||
FF_STRBUF_AUTO_DESTROY userPkgsDir = ffStrbufCreateStatic("/etc/profiles/per-user/");
|
||||
result->nixUser += getNixPackages(&userPkgsDir, instance.state.platform.userName.chars);
|
||||
}
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_GUIX_BIT))
|
||||
|
||||
@@ -113,9 +113,9 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
if (deviceCharacteristics)
|
||||
{
|
||||
ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductSerialNumberKey), &device->serial);
|
||||
ffStrbufTrim(&device->serial, ' ');
|
||||
ffStrbufTrimSpace(&device->serial);
|
||||
ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductRevisionLevelKey), &device->revision);
|
||||
ffStrbufTrim(&device->revision, ' ');
|
||||
ffStrbufTrimRightSpace(&device->revision);
|
||||
|
||||
CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey));
|
||||
if (mediumType)
|
||||
|
||||
@@ -65,7 +65,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
|
||||
ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name);
|
||||
ffStrbufInitMove(&device->serial, &identifier);
|
||||
ffStrbufTrim(&device->serial, ' ');
|
||||
ffStrbufTrimSpace(&device->serial);
|
||||
ffStrbufInit(&device->revision);
|
||||
ffStrbufInit(&device->interconnect);
|
||||
switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK)
|
||||
|
||||
@@ -153,7 +153,7 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
|
||||
{
|
||||
ffStrbufInit(&device->serial);
|
||||
if (ffReadFileBufferRelative(devfd, "serial", &device->serial))
|
||||
ffStrbufTrim(&device->serial, ' ');
|
||||
ffStrbufTrimSpace(&device->serial);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "physicaldisk.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "sys/scsi/generic/inquiry.h"
|
||||
|
||||
#include <libdevinfo.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
struct FFWalkTreeBundle
|
||||
{
|
||||
FFPhysicalDiskOptions* options;
|
||||
FFlist* disks;
|
||||
};
|
||||
|
||||
static int walkDevTree(di_node_t node, di_minor_t minor, struct FFWalkTreeBundle* bundle)
|
||||
{
|
||||
if (di_minor_spectype(minor) != S_IFCHR || !ffStrEquals(di_minor_name(minor), "a,raw")) return DI_WALK_CONTINUE;
|
||||
|
||||
char* productId;
|
||||
char* vendorId;
|
||||
if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "inquiry-product-id", &productId) > 0
|
||||
&& di_prop_lookup_strings(DDI_DEV_T_ANY, node, "inquiry-vendor-id", &vendorId) > 0)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateF("%s %s", vendorId, productId);
|
||||
if (bundle->options->namePrefix.length && !ffStrbufStartsWithIgnCase(&name, &bundle->options->namePrefix))
|
||||
return DI_WALK_CONTINUE;
|
||||
|
||||
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(bundle->disks);
|
||||
ffStrbufInitMove(&device->name, &name);
|
||||
ffStrbufInitF(&device->devPath, "/devices%s", di_devfs_path(node));
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInit(&device->revision);
|
||||
ffStrbufInit(&device->interconnect);
|
||||
device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
|
||||
device->type = FF_PHYSICALDISK_TYPE_NONE;
|
||||
device->size = 0;
|
||||
|
||||
char* buf;
|
||||
if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "inquiry-serial-no", &buf) > 0)
|
||||
{
|
||||
ffStrbufSetS(&device->serial, buf);
|
||||
ffStrbufTrimSpace(&device->serial);
|
||||
}
|
||||
if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "inquiry-revision-id", &buf) > 0)
|
||||
{
|
||||
ffStrbufSetS(&device->revision, buf);
|
||||
ffStrbufTrimRightSpace(&device->revision);
|
||||
}
|
||||
if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "class", &buf) > 0)
|
||||
ffStrbufSetS(&device->interconnect, buf);
|
||||
|
||||
device->type |= di_prop_find(DDI_DEV_T_ANY, node, "removable-media") ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED;
|
||||
|
||||
int* value;
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-solid-state", &value) > 0)
|
||||
device->type |= *value ? FF_PHYSICALDISK_TYPE_SSD : FF_PHYSICALDISK_TYPE_HDD;
|
||||
if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type", &value) > 0)
|
||||
device->type |= *value == DTYPE_DIRECT ? FF_PHYSICALDISK_TYPE_READWRITE : *value == DTYPE_RODIRECT ? FF_PHYSICALDISK_TYPE_READONLY : 0;
|
||||
|
||||
int64_t* nblocks;
|
||||
if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "device-nblocks", &nblocks) > 0
|
||||
&& di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-blksize", &value) > 0)
|
||||
device->size = (uint64_t) ((uint64_t) *nblocks * (uint64_t) *value);
|
||||
}
|
||||
|
||||
return DI_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
{
|
||||
di_node_t rootNode = di_init("/", DINFOCPYALL);
|
||||
if (rootNode == DI_NODE_NIL)
|
||||
return "di_init() failed";
|
||||
di_walk_minor(rootNode, DDI_NT_BLOCK, DI_WALK_CLDFIRST, &(struct FFWalkTreeBundle) { options, result }, (void*) walkDevTree);
|
||||
di_fini(rootNode);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -62,14 +62,14 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic
|
||||
if (sdd->SerialNumberOffset != 0)
|
||||
{
|
||||
ffStrbufSetS(&device->serial, (const char*) sddBuffer + sdd->SerialNumberOffset);
|
||||
ffStrbufTrim(&device->serial, ' ');
|
||||
ffStrbufTrimSpace(&device->serial);
|
||||
}
|
||||
|
||||
ffStrbufInit(&device->revision);
|
||||
if (sdd->ProductRevisionOffset != 0)
|
||||
{
|
||||
ffStrbufSetS(&device->revision, (const char*) sddBuffer + sdd->ProductRevisionOffset);
|
||||
ffStrbufTrim(&device->revision, ' ');
|
||||
ffStrbufTrimRightSpace(&device->revision);
|
||||
}
|
||||
|
||||
device->type |= sdd->RemovableMedia ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED;
|
||||
|
||||
@@ -0,0 +1,909 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 4Front Technologies 1996-2008.
|
||||
*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SYS_AUDIO_OSS_H
|
||||
#define _SYS_AUDIO_OSS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/*
|
||||
* These are the ioctl calls for all Solaris /dev/dsp and /dev/mixer audio
|
||||
* devices.
|
||||
*
|
||||
* Note that the contents of this file include definitions which exist
|
||||
* primarily for compatibility. Many of the defines here are not
|
||||
* actually implemented, but exist solely to facilitate compilation of
|
||||
* programs from other operating systems. Other definitions here may
|
||||
* not be fully supported or may otherwise be obsolete. There are many
|
||||
* things in this file which should not be used on SunOS.
|
||||
*
|
||||
* Please read the documentation to determine which portions of the
|
||||
* API are fully supported and recommended for use in new
|
||||
* applications.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Buffer status queries.
|
||||
* SNDCTL_DSP_GETOSPACE and SNDCTL_DSP_GETISPACE
|
||||
*/
|
||||
typedef struct audio_buf_info {
|
||||
int fragments; /* # of available fragments */
|
||||
int fragstotal; /* Total # of fragments allocated */
|
||||
int fragsize; /* Size of a fragment in bytes */
|
||||
int bytes; /* Available space in bytes */
|
||||
/* Note! 'bytes' could be more than fragments*fragsize */
|
||||
} audio_buf_info;
|
||||
|
||||
/*
|
||||
* Sync groups for audio devices.
|
||||
* SNDCTL_DSP_SYNCGROUP and SNDCTL_DSP_SYNCSTART
|
||||
*/
|
||||
typedef struct oss_syncgroup {
|
||||
int id;
|
||||
int mode;
|
||||
int filler[16];
|
||||
} oss_syncgroup;
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_GETERROR
|
||||
*/
|
||||
typedef struct audio_errinfo {
|
||||
int play_underruns;
|
||||
int rec_overruns;
|
||||
unsigned int play_ptradjust;
|
||||
unsigned int rec_ptradjust;
|
||||
int play_errorcount;
|
||||
int rec_errorcount;
|
||||
int play_lasterror;
|
||||
int rec_lasterror;
|
||||
int play_errorparm;
|
||||
int rec_errorparm;
|
||||
int filler[16];
|
||||
} audio_errinfo;
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_GETIPTR and SNDCTL_DSP_GETOPTR
|
||||
*/
|
||||
typedef struct count_info {
|
||||
unsigned int bytes; /* Total # of bytes processed */
|
||||
int blocks; /* # of fragment transitions since last time */
|
||||
int ptr; /* Current DMA pointer value */
|
||||
} count_info;
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_CURENT_IPTR and SNDCTL_DSP_CURRENT_OPTR
|
||||
*/
|
||||
typedef struct {
|
||||
long long samples; /* Total # of samples */
|
||||
int fifo_samples; /* Samples in device FIFO */
|
||||
int filler[32]; /* For future use */
|
||||
} oss_count_t;
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_GET_RECSRC_NAMES and SNDCTL_DSP_GET_PLAYTGT_NAMES
|
||||
*/
|
||||
#define OSS_ENUM_MAXVALUE 255
|
||||
typedef struct oss_mixer_enuminfo {
|
||||
int dev;
|
||||
int ctrl;
|
||||
int nvalues;
|
||||
int version;
|
||||
short strindex[OSS_ENUM_MAXVALUE];
|
||||
char strings[3000];
|
||||
} oss_mixer_enuminfo;
|
||||
|
||||
/*
|
||||
* Digital interface (S/PDIF) control interface
|
||||
* SNDCTL_DSP_READCTL and SNDCTL_DSP_WRITECTL
|
||||
*/
|
||||
typedef struct oss_digital_control {
|
||||
unsigned int caps;
|
||||
#define DIG_CBITIN_NONE 0x00000000
|
||||
#define DIG_CBITIN_LIMITED 0x00000001
|
||||
#define DIG_CBITIN_DATA 0x00000002
|
||||
#define DIG_CBITIN_BYTE0 0x00000004
|
||||
#define DIG_CBITIN_FULL 0x00000008
|
||||
#define DIG_CBITIN_MASK 0x0000000f
|
||||
#define DIG_CBITOUT_NONE 0x00000000
|
||||
#define DIG_CBITOUT_LIMITED 0x00000010
|
||||
#define DIG_CBITOUT_BYTE0 0x00000020
|
||||
#define DIG_CBITOUT_FULL 0x00000040
|
||||
#define DIG_CBITOUT_DATA 0x00000080
|
||||
#define DIG_CBITOUT_MASK 0x000000f0
|
||||
#define DIG_UBITIN 0x00000100
|
||||
#define DIG_UBITOUT 0x00000200
|
||||
#define DIG_VBITOUT 0x00000400
|
||||
#define DIG_OUTRATE 0x00000800
|
||||
#define DIG_INRATE 0x00001000
|
||||
#define DIG_INBITS 0x00002000
|
||||
#define DIG_OUTBITS 0x00004000
|
||||
#define DIG_EXACT 0x00010000
|
||||
#define DIG_PRO 0x00020000
|
||||
#define DIG_CONSUMER 0x00040000
|
||||
#define DIG_PASSTHROUGH 0x00080000
|
||||
#define DIG_OUTSEL 0x00100000
|
||||
|
||||
unsigned int valid;
|
||||
#define VAL_CBITIN 0x00000001
|
||||
#define VAL_UBITIN 0x00000002
|
||||
#define VAL_CBITOUT 0x00000004
|
||||
#define VAL_UBITOUT 0x00000008
|
||||
#define VAL_ISTATUS 0x00000010
|
||||
#define VAL_IRATE 0x00000020
|
||||
#define VAL_ORATE 0x00000040
|
||||
#define VAL_INBITS 0x00000080
|
||||
#define VAL_OUTBITS 0x00000100
|
||||
#define VAL_REQUEST 0x00000200
|
||||
#define VAL_OUTSEL 0x00000400
|
||||
|
||||
#define VAL_OUTMASK (VAL_CBITOUT|VAL_UBITOUT|VAL_ORATE|VAL_OUTBITS|VAL_OUTSEL)
|
||||
|
||||
unsigned int request;
|
||||
unsigned int param;
|
||||
#define SPD_RQ_PASSTHROUGH 1
|
||||
|
||||
unsigned char cbitin[24];
|
||||
unsigned char ubitin[24];
|
||||
unsigned char cbitout[24];
|
||||
unsigned char ubitout[24];
|
||||
|
||||
unsigned int outsel;
|
||||
#define OUTSEL_DIGITAL 1
|
||||
#define OUTSEL_ANALOG 2
|
||||
#define OUTSEL_BOTH (OUTSEL_DIGITAL|OUTSEL_ANALOG)
|
||||
|
||||
int in_data; /* Audio/data if autodetectable by receiver */
|
||||
#define IND_UNKNOWN 0
|
||||
#define IND_AUDIO 1
|
||||
#define IND_DATA 2
|
||||
|
||||
int in_locked; /* Receiver locked */
|
||||
#define LOCK_NOT_INDICATED 0
|
||||
#define LOCK_UNLOCKED 1
|
||||
#define LOCK_LOCKED 2
|
||||
|
||||
int in_quality; /* Input signal quality */
|
||||
#define IN_QUAL_NOT_INDICATED 0
|
||||
#define IN_QUAL_POOR 1
|
||||
#define IN_QUAL_GOOD 2
|
||||
|
||||
int in_vbit;
|
||||
int out_vbit; /* V bits */
|
||||
#define VBIT_NOT_INDICATED 0
|
||||
#define VBIT_OFF 1
|
||||
#define VBIT_ON 2
|
||||
|
||||
unsigned int in_errors; /* Various input error conditions */
|
||||
#define INERR_CRC 0x0001
|
||||
#define INERR_QCODE_CRC 0x0002
|
||||
#define INERR_PARITY 0x0004
|
||||
#define INERR_BIPHASE 0x0008
|
||||
|
||||
int srate_in;
|
||||
int srate_out;
|
||||
int bits_in;
|
||||
int bits_out;
|
||||
|
||||
int filler[32];
|
||||
} oss_digital_control;
|
||||
|
||||
/*
|
||||
* The "new" mixer API.
|
||||
*
|
||||
* This improved mixer API makes it possible to access every possible feature
|
||||
* of every possible device. However you should read the mixer programming
|
||||
* section of the OSS API Developer's Manual. There is no chance that you
|
||||
* could use this interface correctly just by examining this header.
|
||||
*/
|
||||
#define OSS_VERSION 0x040003
|
||||
#define SOUND_VERSION OSS_VERSION
|
||||
|
||||
typedef struct oss_sysinfo {
|
||||
char product[32]; /* E.g. SunOS Audio */
|
||||
char version[32]; /* E.g. 4.0a */
|
||||
int versionnum; /* See OSS_GETVERSION */
|
||||
char options[128]; /* NOT SUPPORTED */
|
||||
|
||||
int numaudios; /* # of audio/dsp devices */
|
||||
int openedaudio[8]; /* Mask of audio devices are busy */
|
||||
|
||||
int numsynths; /* NOT SUPPORTED, always 0 */
|
||||
int nummidis; /* NOT SUPPORTED, always 0 */
|
||||
int numtimers; /* NOT SUPPORTED, always 0 */
|
||||
int nummixers; /* # of mixer devices */
|
||||
|
||||
int openedmidi[8]; /* Mask of midi devices are busy */
|
||||
int numcards; /* Number of sound cards in the system */
|
||||
int numaudioengines; /* Number of audio engines in the system */
|
||||
char license[16]; /* E.g. "GPL" or "CDDL" */
|
||||
char revision_info[256]; /* For internal use */
|
||||
int filler[172]; /* For future expansion */
|
||||
} oss_sysinfo;
|
||||
|
||||
typedef struct oss_mixext {
|
||||
int dev; /* Mixer device number */
|
||||
int ctrl; /* Extension number */
|
||||
int type; /* Entry type */
|
||||
#define MIXT_DEVROOT 0 /* Device root entry */
|
||||
#define MIXT_GROUP 1 /* Controller group */
|
||||
#define MIXT_ONOFF 2 /* OFF (0) or ON (1) */
|
||||
#define MIXT_ENUM 3 /* Enumerated (0 to maxvalue) */
|
||||
#define MIXT_MONOSLIDER 4 /* Mono slider (0 to 255) */
|
||||
#define MIXT_STEREOSLIDER 5 /* Stereo slider (dual 0 to 255) */
|
||||
#define MIXT_MESSAGE 6 /* (Readable) textual message */
|
||||
#define MIXT_MONOVU 7 /* VU meter value (mono) */
|
||||
#define MIXT_STEREOVU 8 /* VU meter value (stereo) */
|
||||
#define MIXT_MONOPEAK 9 /* VU meter peak value (mono) */
|
||||
#define MIXT_STEREOPEAK 10 /* VU meter peak value (stereo) */
|
||||
#define MIXT_RADIOGROUP 11 /* Radio button group */
|
||||
#define MIXT_MARKER 12 /* Separator between entries */
|
||||
#define MIXT_VALUE 13 /* Decimal value entry */
|
||||
#define MIXT_HEXVALUE 14 /* Hexadecimal value entry */
|
||||
#define MIXT_MONODB 15 /* OBSOLETE */
|
||||
#define MIXT_STEREODB 16 /* OBSOLETE */
|
||||
#define MIXT_SLIDER 17 /* Slider (mono, 31 bit int range) */
|
||||
#define MIXT_3D 18
|
||||
#define MIXT_MONOSLIDER16 19 /* Mono slider (0-32767) */
|
||||
#define MIXT_STEREOSLIDER16 20 /* Stereo slider (dual 0-32767) */
|
||||
#define MIXT_MUTE 21 /* Mute=1, unmute=0 */
|
||||
|
||||
/* Possible value range (minvalue to maxvalue) */
|
||||
/* Note that maxvalue may also be smaller than minvalue */
|
||||
int maxvalue;
|
||||
int minvalue;
|
||||
|
||||
int flags;
|
||||
#define MIXF_READABLE 0x00000001 /* Has readable value */
|
||||
#define MIXF_WRITEABLE 0x00000002 /* Has writeable value */
|
||||
#define MIXF_POLL 0x00000004 /* May change itself */
|
||||
#define MIXF_HZ 0x00000008 /* Hertz scale */
|
||||
#define MIXF_STRING 0x00000010 /* Use dynamic extensions for value */
|
||||
#define MIXF_DYNAMIC 0x00000010 /* Supports dynamic extensions */
|
||||
#define MIXF_OKFAIL 0x00000020 /* Interpret value as 1=OK, 0=FAIL */
|
||||
#define MIXF_FLAT 0x00000040 /* NOT SUPPORTED */
|
||||
#define MIXF_LEGACY 0x00000080 /* NOT SUPPORTED */
|
||||
#define MIXF_CENTIBEL 0x00000100 /* Centibel (0.1 dB) step size */
|
||||
#define MIXF_DECIBEL 0x00000200 /* Step size of 1 dB */
|
||||
#define MIXF_MAINVOL 0x00000400 /* Main volume control */
|
||||
#define MIXF_PCMVOL 0x00000800 /* PCM output volume control */
|
||||
#define MIXF_RECVOL 0x00001000 /* PCM recording volume control */
|
||||
#define MIXF_MONVOL 0x00002000 /* Input->output monitor volume */
|
||||
#define MIXF_WIDE 0x00004000 /* NOT SUPPORTED */
|
||||
#define MIXF_DESCR 0x00008000 /* NOT SUPPORTED */
|
||||
#define MIXF_DISABLE 0x00010000 /* Control has been disabled */
|
||||
|
||||
char id[16]; /* Mnemonic ID (internal use) */
|
||||
int parent; /* Entry# of parent (-1 if root) */
|
||||
|
||||
int dummy; /* NOT SUPPORTED */
|
||||
|
||||
int timestamp;
|
||||
|
||||
char data[64]; /* Misc data (entry type dependent) */
|
||||
unsigned char enum_present[32]; /* Mask of allowed enum values */
|
||||
int control_no; /* NOT SUPPORTED, always -1 */
|
||||
|
||||
unsigned int desc; /* Scope flags, etc */
|
||||
#define MIXEXT_SCOPE_MASK 0x0000003f
|
||||
#define MIXEXT_SCOPE_OTHER 0x00000000
|
||||
#define MIXEXT_SCOPE_INPUT 0x00000001
|
||||
#define MIXEXT_SCOPE_OUTPUT 0x00000002
|
||||
#define MIXEXT_SCOPE_MONITOR 0x00000003
|
||||
#define MIXEXT_SCOPE_RECSWITCH 0x00000004
|
||||
|
||||
char extname[32];
|
||||
int update_counter;
|
||||
#ifdef _KERNEL
|
||||
int filler[6];
|
||||
int enumbit;
|
||||
#else
|
||||
int filler[7];
|
||||
#endif
|
||||
} oss_mixext;
|
||||
|
||||
typedef struct oss_mixext_root {
|
||||
char id[16];
|
||||
char name[48];
|
||||
} oss_mixext_root;
|
||||
|
||||
typedef struct oss_mixer_value {
|
||||
int dev;
|
||||
int ctrl;
|
||||
int value;
|
||||
int flags; /* Reserved for future use. Initialize to 0 */
|
||||
int timestamp; /* Must be set to oss_mixext.timestamp */
|
||||
int filler[8]; /* Reserved for future use. Initialize to 0 */
|
||||
} oss_mixer_value;
|
||||
|
||||
#define OSS_LONGNAME_SIZE 64
|
||||
#define OSS_LABEL_SIZE 16
|
||||
#define OSS_DEVNODE_SIZE 32
|
||||
typedef char oss_longname_t[OSS_LONGNAME_SIZE];
|
||||
typedef char oss_label_t[OSS_LABEL_SIZE];
|
||||
typedef char oss_devnode_t[OSS_DEVNODE_SIZE];
|
||||
|
||||
|
||||
typedef struct oss_audioinfo {
|
||||
int dev; /* Audio device number */
|
||||
char name[64];
|
||||
int busy; /* 0, OPEN_READ, OPEN_WRITE, OPEN_READWRITE */
|
||||
int pid; /* Process ID, not used in SunOS */
|
||||
int caps; /* PCM_CAP_INPUT, PCM_CAP_OUTPUT */
|
||||
int iformats; /* Supported input formats */
|
||||
int oformats; /* Supported output formats */
|
||||
int magic; /* Internal use only */
|
||||
char cmd[64]; /* Command using the device (if known) */
|
||||
int card_number;
|
||||
int port_number;
|
||||
int mixer_dev;
|
||||
int legacy_device; /* Obsolete field. Replaced by devnode */
|
||||
int enabled; /* 1=enabled, 0=device not ready */
|
||||
int flags; /* internal use only - no practical meaning */
|
||||
int min_rate; /* Minimum sample rate */
|
||||
int max_rate; /* Maximum sample rate */
|
||||
int min_channels; /* Minimum number of channels */
|
||||
int max_channels; /* Maximum number of channels */
|
||||
int binding; /* DSP_BIND_FRONT, etc. 0 means undefined */
|
||||
int rate_source;
|
||||
char handle[32];
|
||||
#define OSS_MAX_SAMPLE_RATES 20 /* Cannot be changed */
|
||||
unsigned int nrates; /* Array of supported sample rates */
|
||||
unsigned int rates[OSS_MAX_SAMPLE_RATES];
|
||||
oss_longname_t song_name; /* Song name (if given) */
|
||||
oss_label_t label; /* Device label (if given) */
|
||||
int latency; /* In usecs, -1=unknown */
|
||||
oss_devnode_t devnode; /* Device special file name (absolute path) */
|
||||
int next_play_engine;
|
||||
int next_rec_engine;
|
||||
int filler[184];
|
||||
} oss_audioinfo;
|
||||
|
||||
typedef struct oss_mixerinfo {
|
||||
int dev;
|
||||
char id[16];
|
||||
char name[32];
|
||||
int modify_counter;
|
||||
int card_number;
|
||||
int port_number;
|
||||
char handle[32];
|
||||
int magic; /* Reserved */
|
||||
int enabled; /* Reserved */
|
||||
int caps;
|
||||
#define MIXER_CAP_VIRTUAL 0x00000001
|
||||
#define MIXER_CAP_LAYOUT_B 0x00000002 /* For internal use only */
|
||||
#define MIXER_CAP_NARROW 0x00000004 /* Conserve horiz space */
|
||||
int flags; /* Reserved */
|
||||
int nrext;
|
||||
/*
|
||||
* The priority field can be used to select the default
|
||||
* (motherboard) mixer device. The mixer with the highest
|
||||
* priority is the most preferred one. -2 or less means that
|
||||
* this device cannot be used as the default mixer.
|
||||
*/
|
||||
int priority;
|
||||
oss_devnode_t devnode; /* Device special file name (absolute path) */
|
||||
int legacy_device;
|
||||
int filler[245]; /* Reserved */
|
||||
} oss_mixerinfo;
|
||||
|
||||
typedef struct oss_card_info {
|
||||
int card;
|
||||
char shortname[16];
|
||||
char longname[128];
|
||||
int flags;
|
||||
char hw_info[400];
|
||||
int intr_count;
|
||||
int ack_count;
|
||||
int filler[154];
|
||||
} oss_card_info;
|
||||
|
||||
typedef struct mixer_info { /* OBSOLETE */
|
||||
char id[16];
|
||||
char name[32];
|
||||
int modify_counter;
|
||||
int card_number;
|
||||
int port_number;
|
||||
char handle[32];
|
||||
} mixer_info;
|
||||
|
||||
#define MAX_PEAK_CHANNELS 128
|
||||
typedef unsigned short oss_peaks_t[MAX_PEAK_CHANNELS];
|
||||
|
||||
/* For use with SNDCTL_DSP_GET_CHNORDER */
|
||||
#define CHID_UNDEF 0
|
||||
#define CHID_L 1
|
||||
#define CHID_R 2
|
||||
#define CHID_C 3
|
||||
#define CHID_LFE 4
|
||||
#define CHID_LS 5
|
||||
#define CHID_RS 6
|
||||
#define CHID_LR 7
|
||||
#define CHID_RR 8
|
||||
#define CHNORDER_UNDEF 0x0000000000000000ULL
|
||||
#define CHNORDER_NORMAL 0x0000000087654321ULL
|
||||
|
||||
|
||||
#define OSSIOCPARM_MASK 0x1fff /* parameters must be < 8192 bytes */
|
||||
#define OSSIOC_VOID 0x00000000 /* no parameters */
|
||||
#define OSSIOC_OUT 0x20000000 /* copy out parameters */
|
||||
#define OSSIOC_IN 0x40000000 /* copy in parameters */
|
||||
#define OSSIOC_INOUT (OSSIOC_IN|OSSIOC_OUT)
|
||||
#define OSSIOC_SZ(t) ((sizeof (t) & OSSIOCPARM_MASK) << 16)
|
||||
#define OSSIOC_GETSZ(x) (((x) >> 16) & OSSIOCPARM_MASK)
|
||||
|
||||
#define __OSSIO(x, y) ((int)(OSSIOC_VOID|(x<<8)|y))
|
||||
#define __OSSIOR(x, y, t) ((int)(OSSIOC_OUT|OSSIOC_SZ(t)|(x<<8)|y))
|
||||
#define __OSSIOW(x, y, t) ((int)(OSSIOC_IN|OSSIOC_SZ(t)|(x<<8)|y))
|
||||
#define __OSSIOWR(x, y, t) ((int)(OSSIOC_INOUT|OSSIOC_SZ(t)|(x<<8)|y))
|
||||
|
||||
#define SNDCTL_SYSINFO __OSSIOR('X', 1, oss_sysinfo)
|
||||
#define OSS_SYSINFO SNDCTL_SYSINFO /* Old name */
|
||||
|
||||
#define SNDCTL_MIX_NRMIX __OSSIOR('X', 2, int)
|
||||
#define SNDCTL_MIX_NREXT __OSSIOWR('X', 3, int)
|
||||
#define SNDCTL_MIX_EXTINFO __OSSIOWR('X', 4, oss_mixext)
|
||||
#define SNDCTL_MIX_READ __OSSIOWR('X', 5, oss_mixer_value)
|
||||
#define SNDCTL_MIX_WRITE __OSSIOWR('X', 6, oss_mixer_value)
|
||||
|
||||
#define SNDCTL_AUDIOINFO __OSSIOWR('X', 7, oss_audioinfo)
|
||||
#define SNDCTL_MIX_ENUMINFO __OSSIOWR('X', 8, oss_mixer_enuminfo)
|
||||
#define SNDCTL_MIDIINFO __OSSIO('X', 9)
|
||||
#define SNDCTL_MIXERINFO __OSSIOWR('X', 10, oss_mixerinfo)
|
||||
#define SNDCTL_CARDINFO __OSSIOWR('X', 11, oss_card_info)
|
||||
#define SNDCTL_ENGINEINFO __OSSIOWR('X', 12, oss_audioinfo)
|
||||
#define SNDCTL_AUDIOINFO_EX __OSSIOWR('X', 13, oss_audioinfo)
|
||||
#define SNDCTL_MIX_DESCRIPTION __OSSIOWR('X', 14, oss_mixer_enuminfo)
|
||||
|
||||
/* ioctl codes 'X', 200-255 are reserved for internal use */
|
||||
|
||||
/*
|
||||
* Few more "globally" available ioctl calls.
|
||||
*/
|
||||
#define SNDCTL_SETSONG __OSSIOW('Y', 2, oss_longname_t)
|
||||
#define SNDCTL_GETSONG __OSSIOR('Y', 2, oss_longname_t)
|
||||
#define SNDCTL_SETNAME __OSSIOW('Y', 3, oss_longname_t)
|
||||
#define SNDCTL_SETLABEL __OSSIOW('Y', 4, oss_label_t)
|
||||
#define SNDCTL_GETLABEL __OSSIOR('Y', 4, oss_label_t)
|
||||
|
||||
/*
|
||||
* IOCTL commands for /dev/dsp
|
||||
*/
|
||||
#define SNDCTL_DSP_HALT __OSSIO('P', 0)
|
||||
#define SNDCTL_DSP_RESET SNDCTL_DSP_HALT /* Old name */
|
||||
#define SNDCTL_DSP_SYNC __OSSIO('P', 1)
|
||||
#define SNDCTL_DSP_SPEED __OSSIOWR('P', 2, int)
|
||||
|
||||
#define SNDCTL_DSP_STEREO __OSSIOWR('P', 3, int) /* OBSOLETE */
|
||||
|
||||
#define SNDCTL_DSP_GETBLKSIZE __OSSIOWR('P', 4, int)
|
||||
#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT
|
||||
#define SNDCTL_DSP_CHANNELS __OSSIOWR('P', 6, int)
|
||||
#define SNDCTL_DSP_POST __OSSIO('P', 8)
|
||||
#define SNDCTL_DSP_SUBDIVIDE __OSSIOWR('P', 9, int)
|
||||
#define SNDCTL_DSP_SETFRAGMENT __OSSIOWR('P', 10, int)
|
||||
|
||||
#define SNDCTL_DSP_GETFMTS __OSSIOR('P', 11, int) /* Returns a mask */
|
||||
#define SNDCTL_DSP_SETFMT __OSSIOWR('P', 5, int) /* Selects ONE fmt */
|
||||
|
||||
#define SNDCTL_DSP_GETOSPACE __OSSIOR('P', 12, audio_buf_info)
|
||||
#define SNDCTL_DSP_GETISPACE __OSSIOR('P', 13, audio_buf_info)
|
||||
#define SNDCTL_DSP_NONBLOCK __OSSIO('P', 14) /* Obsolete */
|
||||
#define SNDCTL_DSP_GETCAPS __OSSIOR('P', 15, int)
|
||||
|
||||
#define SNDCTL_DSP_GETTRIGGER __OSSIOR('P', 16, int)
|
||||
#define SNDCTL_DSP_SETTRIGGER __OSSIOW('P', 16, int)
|
||||
|
||||
#define SNDCTL_DSP_GETIPTR __OSSIOR('P', 17, count_info)
|
||||
#define SNDCTL_DSP_GETOPTR __OSSIOR('P', 18, count_info)
|
||||
|
||||
#define SNDCTL_DSP_SETSYNCRO __OSSIO('P', 21)
|
||||
#define SNDCTL_DSP_SETDUPLEX __OSSIO('P', 22)
|
||||
|
||||
#define SNDCTL_DSP_PROFILE __OSSIOW('P', 23, int) /* OBSOLETE */
|
||||
#define APF_NORMAL 0 /* Normal applications */
|
||||
#define APF_NETWORK 1 /* Underruns caused by "external" delay */
|
||||
#define APF_CPUINTENS 2 /* Underruns caused by "overheating" the CPU */
|
||||
|
||||
|
||||
#define SNDCTL_DSP_GETODELAY __OSSIOR('P', 23, int)
|
||||
|
||||
#define SNDCTL_DSP_GETPLAYVOL __OSSIOR('P', 24, int)
|
||||
#define SNDCTL_DSP_SETPLAYVOL __OSSIOWR('P', 24, int)
|
||||
#define SNDCTL_DSP_GETERROR __OSSIOR('P', 25, audio_errinfo)
|
||||
|
||||
#define SNDCTL_DSP_READCTL __OSSIOWR('P', 26, oss_digital_control)
|
||||
#define SNDCTL_DSP_WRITECTL __OSSIOWR('P', 27, oss_digital_control)
|
||||
|
||||
#define SNDCTL_DSP_SYNCGROUP __OSSIOWR('P', 28, oss_syncgroup)
|
||||
#define SNDCTL_DSP_SYNCSTART __OSSIOW('P', 29, int)
|
||||
|
||||
#define SNDCTL_DSP_COOKEDMODE __OSSIOW('P', 30, int)
|
||||
|
||||
#define SNDCTL_DSP_SILENCE __OSSIO('P', 31)
|
||||
#define SNDCTL_DSP_SKIP __OSSIO('P', 32)
|
||||
|
||||
#define SNDCTL_DSP_HALT_INPUT __OSSIO('P', 33)
|
||||
#define SNDCTL_DSP_RESET_INPUT SNDCTL_DSP_HALT_INPUT /* Old name */
|
||||
#define SNDCTL_DSP_HALT_OUTPUT __OSSIO('P', 34)
|
||||
#define SNDCTL_DSP_RESET_OUTPUT SNDCTL_DSP_HALT_OUTPUT /* Old name */
|
||||
|
||||
#define SNDCTL_DSP_LOW_WATER __OSSIOW('P', 34, int)
|
||||
|
||||
#define SNDCTL_DSP_CURRENT_IPTR __OSSIOR('P', 35, oss_count_t)
|
||||
#define SNDCTL_DSP_CURRENT_OPTR __OSSIOR('P', 36, oss_count_t)
|
||||
|
||||
#define SNDCTL_DSP_GET_RECSRC_NAMES __OSSIOR('P', 37, oss_mixer_enuminfo)
|
||||
#define SNDCTL_DSP_GET_RECSRC __OSSIOR('P', 38, int)
|
||||
#define SNDCTL_DSP_SET_RECSRC __OSSIOWR('P', 38, int)
|
||||
|
||||
#define SNDCTL_DSP_GET_PLAYTGT_NAMES __OSSIOR('P', 39, oss_mixer_enuminfo)
|
||||
#define SNDCTL_DSP_GET_PLAYTGT __OSSIOR('P', 40, int)
|
||||
#define SNDCTL_DSP_SET_PLAYTGT __OSSIOWR('P', 40, int)
|
||||
#define SNDCTL_DSP_GETRECVOL __OSSIOR('P', 41, int)
|
||||
#define SNDCTL_DSP_SETRECVOL __OSSIOWR('P', 41, int)
|
||||
|
||||
#define SNDCTL_DSP_GET_CHNORDER __OSSIOR('P', 42, unsigned long long)
|
||||
#define SNDCTL_DSP_SET_CHNORDER __OSSIOWR('P', 42, unsigned long long)
|
||||
|
||||
#define SNDCTL_DSP_GETIPEAKS __OSSIOR('P', 43, oss_peaks_t)
|
||||
#define SNDCTL_DSP_GETOPEAKS __OSSIOR('P', 44, oss_peaks_t)
|
||||
|
||||
#define SNDCTL_DSP_POLICY __OSSIOW('P', 45, int) /* See the manual */
|
||||
|
||||
#define SNDCTL_DSP_GETCHANNELMASK __OSSIOWR('P', 64, int)
|
||||
#define SNDCTL_DSP_BIND_CHANNEL __OSSIOWR('P', 65, int)
|
||||
|
||||
/*
|
||||
* These definitions are here for the benefit of compiling application
|
||||
* code. Most of these are NOT implemented in the Solaris code,
|
||||
* however. This is the older 3.x OSS API, and only the master input and
|
||||
* output levels are actually supported.
|
||||
*/
|
||||
#define SOUND_MIXER_NRDEVICES 28
|
||||
#define SOUND_MIXER_VOLUME 0
|
||||
#define SOUND_MIXER_BASS 1
|
||||
#define SOUND_MIXER_TREBLE 2
|
||||
#define SOUND_MIXER_SYNTH 3
|
||||
#define SOUND_MIXER_PCM 4
|
||||
#define SOUND_MIXER_SPEAKER 5
|
||||
#define SOUND_MIXER_LINE 6
|
||||
#define SOUND_MIXER_MIC 7
|
||||
#define SOUND_MIXER_CD 8
|
||||
#define SOUND_MIXER_IMIX 9 /* Recording monitor */
|
||||
#define SOUND_MIXER_ALTPCM 10
|
||||
#define SOUND_MIXER_RECLEV 11 /* Recording level */
|
||||
#define SOUND_MIXER_IGAIN 12 /* Input gain */
|
||||
#define SOUND_MIXER_OGAIN 13 /* Output gain */
|
||||
#define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */
|
||||
#define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */
|
||||
#define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */
|
||||
#define SOUND_MIXER_DIGITAL1 17 /* Digital I/O 1 */
|
||||
#define SOUND_MIXER_DIGITAL2 18 /* Digital I/O 2 */
|
||||
#define SOUND_MIXER_DIGITAL3 19 /* Digital I/O 3 */
|
||||
#define SOUND_MIXER_PHONE 20 /* Phone */
|
||||
#define SOUND_MIXER_MONO 21 /* Mono Output */
|
||||
#define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */
|
||||
#define SOUND_MIXER_RADIO 23 /* Radio in */
|
||||
#define SOUND_MIXER_DEPTH 24 /* Surround depth */
|
||||
#define SOUND_MIXER_REARVOL 25 /* Rear/Surround speaker vol */
|
||||
#define SOUND_MIXER_CENTERVOL 26 /* Center/LFE speaker vol */
|
||||
#define SOUND_MIXER_SIDEVOL 27 /* Side-Surround (8speaker) vol */
|
||||
#define SOUND_MIXER_SURRVOL SOUND_MIXER_SIDEVOL
|
||||
#define SOUND_ONOFF_MIN 28
|
||||
#define SOUND_ONOFF_MAX 30
|
||||
#define SOUND_MIXER_NONE 31
|
||||
|
||||
#define SOUND_MIXER_RECSRC 0xff /* Recording sources */
|
||||
#define SOUND_MIXER_DEVMASK 0xfe /* Supported devices */
|
||||
#define SOUND_MIXER_RECMASK 0xfd /* Recording sources */
|
||||
#define SOUND_MIXER_CAPS 0xfc /* Mixer capabilities (do not use) */
|
||||
#define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */
|
||||
#define SOUND_MIXER_OUTSRC 0xfa
|
||||
#define SOUND_MIXER_OUTMASK 0xf9
|
||||
|
||||
#define SOUND_MIXER_ENHANCE SOUND_MIXER_NONE
|
||||
#define SOUND_MIXER_MUTE SOUND_MIXER_NONE
|
||||
#define SOUND_MIXER_LOUD SOUND_MIXER_NONE
|
||||
|
||||
#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME)
|
||||
#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS)
|
||||
#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE)
|
||||
#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH)
|
||||
#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM)
|
||||
#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER)
|
||||
#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE)
|
||||
#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC)
|
||||
#define SOUND_MASK_CD (1 << SOUND_MIXER_CD)
|
||||
#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX)
|
||||
#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM)
|
||||
#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV)
|
||||
#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN)
|
||||
#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN)
|
||||
#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1)
|
||||
#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2)
|
||||
#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3)
|
||||
#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1)
|
||||
#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2)
|
||||
#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3)
|
||||
#define SOUND_MASK_MONO (1 << SOUND_MIXER_MONO)
|
||||
#define SOUND_MASK_PHONE (1 << SOUND_MIXER_PHONE)
|
||||
#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO)
|
||||
#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO)
|
||||
#define SOUND_MASK_DEPTH (1 << SOUND_MIXER_DEPTH)
|
||||
#define SOUND_MASK_REARVOL (1 << SOUND_MIXER_REARVOL)
|
||||
#define SOUND_MASK_CENTERVOL (1 << SOUND_MIXER_CENTERVOL)
|
||||
#define SOUND_MASK_SIDEVOL (1 << SOUND_MIXER_SIDEVOL)
|
||||
#define SOUND_MASK_SURRVOL SOUND_MASK_SIDEVOL
|
||||
#define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE)
|
||||
#define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE)
|
||||
#define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD)
|
||||
|
||||
/*
|
||||
* Again, DO NOT USE the following two macros. They are here for SOURCE
|
||||
* COMPATIBILITY ONLY.
|
||||
*/
|
||||
#define SOUND_DEVICE_LABELS { \
|
||||
"Vol ", "Bass ", "Treble", "Synth", "Pcm ", "Speaker ", "Line ", \
|
||||
"Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \
|
||||
"Aux1", "Aux2", "Aux3", "Digital1", "Digital2", "Digital3", \
|
||||
"Phone", "Mono", "Video", "Radio", "Depth", \
|
||||
"Rear", "Center", "Side" }
|
||||
|
||||
#define SOUND_DEVICE_NAMES { \
|
||||
"vol", "bass", "treble", "synth", "pcm", "speaker", "line", \
|
||||
"mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \
|
||||
"aux1", "aux2", "aux3", "dig1", "dig2", "dig3", \
|
||||
"phone", "mono", "video", "radio", "depth", \
|
||||
"rear", "center", "side" }
|
||||
|
||||
#define MIXER_READ(dev) __OSSIOR('M', dev, int)
|
||||
#define MIXER_WRITE(dev) __OSSIOWR('M', dev, int)
|
||||
#define SOUND_MIXER_INFO __OSSIOR('M', 101, mixer_info)
|
||||
#define OSS_GETVERSION __OSSIOR('M', 118, int)
|
||||
|
||||
/*
|
||||
* These macros are useful for some applications. They are implemented
|
||||
* as soft values for the application, and do not affect real hardware.
|
||||
*/
|
||||
#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME)
|
||||
#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN)
|
||||
#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM)
|
||||
#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN)
|
||||
#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV)
|
||||
#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC)
|
||||
#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK)
|
||||
#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK)
|
||||
#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS)
|
||||
#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS)
|
||||
#define SOUND_MIXER_READ_RECGAIN __OSSIOR('M', 119, int)
|
||||
#define SOUND_MIXER_READ_MONGAIN __OSSIOR('M', 120, int)
|
||||
|
||||
#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME)
|
||||
#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN)
|
||||
#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM)
|
||||
#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN)
|
||||
#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV)
|
||||
#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC)
|
||||
#define SOUND_MIXER_WRITE_RECGAIN __OSSIOWR('M', 119, int)
|
||||
#define SOUND_MIXER_WRITE_MONGAIN __OSSIOWR('M', 120, int)
|
||||
|
||||
/*
|
||||
* These macros are here for source compatibility. They intentionally don't
|
||||
* map to any real hardware. NOT SUPPORTED!
|
||||
*/
|
||||
#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS)
|
||||
#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE)
|
||||
#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH)
|
||||
#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER)
|
||||
#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE)
|
||||
#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC)
|
||||
#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD)
|
||||
#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX)
|
||||
#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM)
|
||||
#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1)
|
||||
#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2)
|
||||
#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3)
|
||||
|
||||
#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS)
|
||||
#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE)
|
||||
#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH)
|
||||
#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER)
|
||||
#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE)
|
||||
#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC)
|
||||
#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD)
|
||||
#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX)
|
||||
#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM)
|
||||
#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1)
|
||||
#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2)
|
||||
#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3)
|
||||
|
||||
/*
|
||||
* Audio encoding types (Note! U8=8 and S16_LE=16 for compatibility)
|
||||
*/
|
||||
#define AFMT_QUERY 0x00000000 /* Return current fmt */
|
||||
#define AFMT_MU_LAW 0x00000001
|
||||
#define AFMT_A_LAW 0x00000002
|
||||
#define AFMT_IMA_ADPCM 0x00000004
|
||||
#define AFMT_U8 0x00000008
|
||||
#define AFMT_S16_LE 0x00000010
|
||||
#define AFMT_S16_BE 0x00000020
|
||||
#define AFMT_S8 0x00000040
|
||||
#define AFMT_U16_LE 0x00000080
|
||||
#define AFMT_U16_BE 0x00000100
|
||||
#define AFMT_MPEG 0x00000200 /* NOT SUPPORTED: MPEG (2) audio */
|
||||
#define AFMT_AC3 0x00000400 /* NOT SUPPORTED: AC3 compressed */
|
||||
#define AFMT_VORBIS 0x00000800 /* NOT SUPPORTED: Ogg Vorbis */
|
||||
#define AFMT_S32_LE 0x00001000
|
||||
#define AFMT_S32_BE 0x00002000
|
||||
#define AFMT_FLOAT 0x00004000 /* NOT SUPPORTED: IEEE double float */
|
||||
#define AFMT_S24_LE 0x00008000 /* LSB aligned in 32 bit word */
|
||||
#define AFMT_S24_BE 0x00010000 /* LSB aligned in 32 bit word */
|
||||
#define AFMT_SPDIF_RAW 0x00020000 /* NOT SUPPORTED: Raw S/PDIF frames */
|
||||
#define AFMT_S24_PACKED 0x00040000 /* 24 bit packed little endian */
|
||||
/*
|
||||
* Some big endian/little endian handling macros (native endian and
|
||||
* opposite endian formats).
|
||||
*/
|
||||
#if defined(_BIG_ENDIAN)
|
||||
#define AFMT_S16_NE AFMT_S16_BE
|
||||
#define AFMT_U16_NE AFMT_U16_BE
|
||||
#define AFMT_S32_NE AFMT_S32_BE
|
||||
#define AFMT_S24_NE AFMT_S24_BE
|
||||
#define AFMT_S16_OE AFMT_S16_LE
|
||||
#define AFMT_S32_OE AFMT_S32_LE
|
||||
#define AFMT_S24_OE AFMT_S24_LE
|
||||
#else
|
||||
#define AFMT_S16_NE AFMT_S16_LE
|
||||
#define AFMT_U16_NE AFMT_U16_LE
|
||||
#define AFMT_S32_NE AFMT_S32_LE
|
||||
#define AFMT_S24_NE AFMT_S24_LE
|
||||
#define AFMT_S16_OE AFMT_S16_BE
|
||||
#define AFMT_S32_OE AFMT_S32_BE
|
||||
#define AFMT_S24_OE AFMT_S24_BE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_GETCAPS bits
|
||||
*/
|
||||
#define PCM_CAP_REVISION 0x000000ff /* Revision level (0 to 255) */
|
||||
#define PCM_CAP_DUPLEX 0x00000100 /* Full duplex rec/play */
|
||||
#define PCM_CAP_REALTIME 0x00000200 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_BATCH 0x00000400 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_COPROC 0x00000800 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */
|
||||
#define PCM_CAP_MMAP 0x00002000 /* Supports mmap() */
|
||||
#define PCM_CAP_MULTI 0x00004000 /* Supports multiple open */
|
||||
#define PCM_CAP_BIND 0x00008000 /* Supports channel binding */
|
||||
#define PCM_CAP_INPUT 0x00010000 /* Supports recording */
|
||||
#define PCM_CAP_OUTPUT 0x00020000 /* Supports playback */
|
||||
#define PCM_CAP_VIRTUAL 0x00040000 /* Virtual device */
|
||||
#define PCM_CAP_ANALOGOUT 0x00100000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_ANALOGIN 0x00200000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_DIGITALOUT 0x00400000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_DIGITALIN 0x00800000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_ADMASK 0x00f00000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_SHADOW 0x01000000 /* "Shadow" device */
|
||||
#define PCM_CAP_CH_MASK 0x06000000 /* See DSP_CH_MASK below */
|
||||
#define PCM_CAP_HIDDEN 0x08000000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_FREERATE 0x10000000
|
||||
#define PCM_CAP_MODEM 0x20000000 /* NOT SUPPORTED */
|
||||
#define PCM_CAP_DEFAULT 0x40000000 /* "Default" device */
|
||||
|
||||
/*
|
||||
* Preferred channel usage. These bits can be used to give
|
||||
* recommendations to the application. Used by few drivers. For
|
||||
* example if ((caps & DSP_CH_MASK) == DSP_CH_MONO) means that the
|
||||
* device works best in mono mode. However it doesn't necessarily mean
|
||||
* that the device cannot be used in stereo. These bits should only be
|
||||
* used by special applications such as multi track hard disk
|
||||
* recorders to find out the initial setup. However the user should be
|
||||
* able to override this selection.
|
||||
*
|
||||
* To find out which modes are actually supported the application
|
||||
* should try to select them using SNDCTL_DSP_CHANNELS.
|
||||
*/
|
||||
#define DSP_CH_MASK 0x06000000 /* Mask */
|
||||
#define DSP_CH_ANY 0x00000000 /* No preferred mode */
|
||||
#define DSP_CH_MONO 0x02000000
|
||||
#define DSP_CH_STEREO 0x04000000
|
||||
#define DSP_CH_MULTI 0x06000000 /* More than two channels */
|
||||
|
||||
|
||||
/*
|
||||
* The PCM_CAP_* capability names used to be known as DSP_CAP_*, so
|
||||
* it's necessary to define the older names too.
|
||||
*/
|
||||
#define DSP_CAP_ADMASK PCM_CAP_ADMASK
|
||||
#define DSP_CAP_ANALOGIN PCM_CAP_ANALOGIN
|
||||
#define DSP_CAP_ANALOGOUT PCM_CAP_ANALOGOUT
|
||||
#define DSP_CAP_BATCH PCM_CAP_BATCH
|
||||
#define DSP_CAP_BIND PCM_CAP_BIND
|
||||
#define DSP_CAP_COPROC PCM_CAP_COPROC
|
||||
#define DSP_CAP_DEFAULT PCM_CAP_DEFAULT
|
||||
#define DSP_CAP_DIGITALIN PCM_CAP_DIGITALIN
|
||||
#define DSP_CAP_DIGITALOUT PCM_CAP_DIGITALOUT
|
||||
#define DSP_CAP_DUPLEX PCM_CAP_DUPLEX
|
||||
#define DSP_CAP_FREERATE PCM_CAP_FREERATE
|
||||
#define DSP_CAP_HIDDEN PCM_CAP_HIDDEN
|
||||
#define DSP_CAP_INPUT PCM_CAP_INPUT
|
||||
#define DSP_CAP_MMAP PCM_CAP_MMAP
|
||||
#define DSP_CAP_MODEM PCM_CAP_MODEM
|
||||
#define DSP_CAP_MULTI PCM_CAP_MULTI
|
||||
#define DSP_CAP_OUTPUT PCM_CAP_OUTPUT
|
||||
#define DSP_CAP_REALTIME PCM_CAP_REALTIME
|
||||
#define DSP_CAP_REVISION PCM_CAP_REVISION
|
||||
#define DSP_CAP_SHADOW PCM_CAP_SHADOW
|
||||
#define DSP_CAP_TRIGGER PCM_CAP_TRIGGER
|
||||
#define DSP_CAP_VIRTUAL PCM_CAP_VIRTUAL
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_GETTRIGGER and SNDCTL_DSP_SETTRIGGER
|
||||
*/
|
||||
#define PCM_ENABLE_INPUT 0x00000001
|
||||
#define PCM_ENABLE_OUTPUT 0x00000002
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_BIND_CHANNEL
|
||||
*/
|
||||
#define DSP_BIND_QUERY 0x00000000
|
||||
#define DSP_BIND_FRONT 0x00000001
|
||||
#define DSP_BIND_SURR 0x00000002
|
||||
#define DSP_BIND_CENTER_LFE 0x00000004
|
||||
#define DSP_BIND_HANDSET 0x00000008
|
||||
#define DSP_BIND_MIC 0x00000010
|
||||
#define DSP_BIND_MODEM1 0x00000020
|
||||
#define DSP_BIND_MODEM2 0x00000040
|
||||
#define DSP_BIND_I2S 0x00000080
|
||||
#define DSP_BIND_SPDIF 0x00000100
|
||||
#define DSP_BIND_REAR 0x00000200
|
||||
|
||||
/*
|
||||
* SOUND_MIXER_READ_CAPS
|
||||
*/
|
||||
#define SOUND_CAP_EXCL_INPUT 0x00000001
|
||||
#define SOUND_CAP_NOLEGACY 0x00000004
|
||||
#define SOUND_CAP_NORECSRC 0x00000008
|
||||
|
||||
/*
|
||||
* The following ioctl is for internal use only -- it is used to
|
||||
* coordinate /dev/sndstat numbering with file names in /dev/sound.
|
||||
* Applications must not use it. (This is duplicated in sys/audioio.h
|
||||
* as well.)
|
||||
*/
|
||||
#define SNDCTL_SUN_SEND_NUMBER __OSSIOW('X', 200, int)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_AUDIO_OSS_H */
|
||||
@@ -32,15 +32,6 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
|
||||
{
|
||||
AudioDeviceID deviceId = deviceIds[index];
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef name = NULL;
|
||||
dataSize = sizeof(name);
|
||||
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
|
||||
kAudioObjectPropertyName,
|
||||
kAudioObjectPropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
}, 0, NULL, &dataSize, &name) != kAudioHardwareNoError)
|
||||
continue;
|
||||
|
||||
// Ignore input devices
|
||||
if(AudioObjectGetPropertyDataSize(deviceId, &(AudioObjectPropertyAddress){
|
||||
kAudioDevicePropertyStreams,
|
||||
@@ -71,10 +62,31 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
|
||||
device->main = deviceId == mainDeviceId;
|
||||
device->active = false;
|
||||
device->volume = FF_SOUND_VOLUME_UNKNOWN;
|
||||
ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId);
|
||||
ffStrbufInit(&device->identifier);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInitStatic(&device->platformApi, "Core Audio");
|
||||
ffCfStrGetString(name, &device->name);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef uid = NULL;
|
||||
dataSize = sizeof(uid);
|
||||
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress) {
|
||||
kAudioDevicePropertyDeviceUID,
|
||||
kAudioObjectPropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
}, 0, NULL, &dataSize, &uid) == kAudioHardwareNoError)
|
||||
ffCfStrGetString(uid, &device->identifier);
|
||||
else
|
||||
ffStrbufAppendF(&device->identifier, "ID-%u", (unsigned) deviceId);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef name = NULL;
|
||||
dataSize = sizeof(name);
|
||||
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
|
||||
kAudioObjectPropertyName,
|
||||
kAudioObjectPropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
}, 0, NULL, &dataSize, &name) == kAudioHardwareNoError)
|
||||
ffCfStrGetString(name, &device->name);
|
||||
else
|
||||
ffStrbufSet(&device->name, &device->identifier);
|
||||
|
||||
uint32_t muted;
|
||||
dataSize = sizeof(muted);
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "sound.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#if __has_include(<sys/soundcard.h>)
|
||||
#include <sys/soundcard.h>
|
||||
#else
|
||||
// Strangely, they don't provide this file on default installation
|
||||
#include "audio_oss_sunos.h"
|
||||
#endif
|
||||
|
||||
const char* ffDetectSound(FFlist* devices)
|
||||
{
|
||||
int defaultDev;
|
||||
{
|
||||
char mixerp[12];
|
||||
ssize_t plen = readlink("/dev/audio", mixerp, ARRAY_SIZE(mixerp));
|
||||
if (plen < 6)
|
||||
return "readlink(/dev/audio) failed";
|
||||
defaultDev = mixerp[plen - 1] - '0';
|
||||
if (defaultDev < 0 || defaultDev > 9)
|
||||
return "Invalid mixer device";
|
||||
}
|
||||
|
||||
char path[] = "/dev/mixer0";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY sndstat = ffStrbufCreate();
|
||||
|
||||
struct oss_sysinfo info = { .nummixers = 9 };
|
||||
|
||||
// The implementation is very different from *BSD's. They call it OSS4
|
||||
for (int idev = 0; idev < info.nummixers; ++idev)
|
||||
{
|
||||
path[strlen("/dev/mixer")] = (char) ('0' + idev);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) break;
|
||||
|
||||
if (idev == 0)
|
||||
{
|
||||
if (ioctl(fd, SNDCTL_SYSINFO, &info) != 0)
|
||||
return "ioctl(SNDCTL_SYSINFO) failed";
|
||||
if (ffAppendFDBuffer(fd, &sndstat))
|
||||
ffStrbufSubstrAfterFirstS(&sndstat, "\nMixers:");
|
||||
}
|
||||
|
||||
struct oss_mixerinfo mi = {};
|
||||
if (ioctl(fd, SNDCTL_MIXERINFO, &mi) < 0)
|
||||
continue;
|
||||
|
||||
int volume = -1;
|
||||
for (int iext = 0; iext < mi.nrext; ++iext)
|
||||
{
|
||||
struct oss_mixext me = { .dev = mi.dev, .ctrl = iext };
|
||||
if (ioctl(fd, SNDCTL_MIX_EXTINFO, &me) < 0)
|
||||
continue;
|
||||
if (me.flags & MIXF_PCMVOL)
|
||||
{
|
||||
struct oss_mixer_value mv = { .dev = mi.dev, .ctrl = iext, .timestamp = me.timestamp };
|
||||
if (ioctl(fd, SNDCTL_MIX_READ, &mv) >= 0)
|
||||
{
|
||||
mv.value -= me.minvalue;
|
||||
me.maxvalue -= me.minvalue;
|
||||
volume = (uint8_t) ((mv.value * 100 + me.maxvalue / 2) / me.maxvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (volume == -1) continue;
|
||||
|
||||
FFSoundDevice* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->identifier, path);
|
||||
char buf[16];
|
||||
int bufLen = snprintf(buf, ARRAY_SIZE(buf), "\n%d: ", mi.dev);
|
||||
assert(bufLen > 3);
|
||||
const char* pLine = memmem(sndstat.chars, sndstat.length, buf, (size_t) bufLen);
|
||||
if (pLine)
|
||||
{
|
||||
pLine += bufLen;
|
||||
const char* pEnd = strchr(pLine, '\n');
|
||||
if (!pEnd) pEnd = sndstat.chars + sndstat.length;
|
||||
ffStrbufInitNS(&device->name, (uint32_t) (pEnd - pLine), pLine);
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&device->name, mi.name);
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
ffStrbufInitF(&device->platformApi, "%s %s", info.product, info.version);
|
||||
device->volume = (uint8_t) volume;
|
||||
device->active = !!mi.enabled;
|
||||
device->main = defaultDev == idev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -109,6 +109,8 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
|
||||
ffStrbufEqualS(&result->processName, "chezmoi") || // #762
|
||||
ffStrbufEqualS(&result->processName, "proot") ||
|
||||
ffStrbufEqualS(&result->processName, "script") ||
|
||||
ffStrbufEqualS(&result->processName, "init") ||
|
||||
ffStrbufEqualS(&result->processName, "systemd") ||
|
||||
#ifdef __linux__
|
||||
ffStrbufStartsWithS(&result->processName, "flatpak-") || // #707
|
||||
#endif
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
#elif defined(__FreeBSD__)
|
||||
#define FF_SYSNAME "FreeBSD"
|
||||
#elif defined(__APPLE__)
|
||||
#define FF_SYSNAME "Darwin"
|
||||
#define FF_SYSNAME "macOS"
|
||||
#elif defined(_WIN32)
|
||||
#define FF_SYSNAME "WIN32"
|
||||
#define FF_SYSNAME "Windows"
|
||||
#elif defined(__sun)
|
||||
#define FF_SYSNAME "SunOS"
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
@@ -176,7 +176,7 @@ static const char* getWslg(FFstrbuf* result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool extractCtFvWmVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
|
||||
static bool extractCommonWmVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
|
||||
{
|
||||
int count = 0;
|
||||
sscanf(line, "%*d.%*d.%*d%n", &count);
|
||||
@@ -192,7 +192,7 @@ static const char* getCtwm(FFstrbuf* result)
|
||||
const char* error = ffFindExecutableInPath("ctwm", &path);
|
||||
if (error) return "Failed to find ctwm executable path";
|
||||
|
||||
ffBinaryExtractStrings(path.chars, extractCtFvWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
ffBinaryExtractStrings(path.chars, extractCommonWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
if (result->length > 0) return NULL;
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
@@ -215,7 +215,7 @@ static const char* getFvwm(FFstrbuf* result)
|
||||
const char* error = ffFindExecutableInPath("fvwm", &path);
|
||||
if (error) return "Failed to find fvwm executable path";
|
||||
|
||||
ffBinaryExtractStrings(path.chars, extractCtFvWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
ffBinaryExtractStrings(path.chars, extractCommonWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
if (result->length > 0) return NULL;
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
@@ -232,6 +232,29 @@ static const char* getFvwm(FFstrbuf* result)
|
||||
return "Failed to run command `fvwm -version`";
|
||||
}
|
||||
|
||||
static const char* getOpenbox(FFstrbuf* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
const char* error = ffFindExecutableInPath("openbox", &path);
|
||||
if (error) return "Failed to find openbox executable path";
|
||||
|
||||
ffBinaryExtractStrings(path.chars, extractCommonWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
if (result->length > 0) return NULL;
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
path.chars,
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL)
|
||||
{ // Openbox 3.6.1\n...
|
||||
ffStrbufSubstrBeforeFirstC(result, '\n');
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Failed to run command `openbox --version`";
|
||||
}
|
||||
|
||||
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
|
||||
{
|
||||
if (!wmName)
|
||||
@@ -255,5 +278,8 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE
|
||||
if (ffStrbufEqualS(wmName, "fvwm"))
|
||||
return getFvwm(result);
|
||||
|
||||
if (ffStrbufEqualS(wmName, "Openbox"))
|
||||
return getOpenbox(result);
|
||||
|
||||
return "Unsupported WM";
|
||||
}
|
||||
|
||||
@@ -2,7 +2,3 @@
|
||||
|
||||
#define FASTFETCH_DATATEXT_JSON_HELP @DATATEXT_JSON_HELP@
|
||||
#define FASTFETCH_DATATEXT_STRUCTURE @DATATEXT_STRUCTURE@
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define FASTFETCH_DATATEXT_NOWPLAYING @DATATEXT_NOWPLAYING@
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
▂🬭⎻⎻🬭▂
|
||||
▁▂━▂🬭🬭🭗 🬁🬭🬭▂▁━▂▁
|
||||
🬂🬂🮂━🮂▔ ▔🮂━🮂🬂🬂🬿
|
||||
🭄🬨▍ 🬜🮂▔ ▁▂▂🬭🬭▂▂▁ ▔🮂🬪 🮈🬕
|
||||
🭄🭙▐▎ 🭃██████████🭎 🭢🮇▌🭤
|
||||
🭄🭙 ▐🭄🭙 🭋█████🭜█████🭀 🭤🭏▌ 🭤🭏
|
||||
🭗 🮉🭛 🭃███🭝🭙 🭥🭒███🭎 🭦▋ 🭢
|
||||
▟🬮━🭷🭘 🭋████▄▂ ▂▄████🭀 🭣━🬯🭏
|
||||
🭕╾🭺🬽 🭃██🭡 🭖██🭐 🭈╼🬡🭠
|
||||
🬼 🮉🭀 🭋███΄ 🭤███🭀 🭋▊ 🭇
|
||||
🬾 ▐🬾▁▁ 🭃██ ██🭐 ▁▁🭉🭫▌ 🭉🭠
|
||||
🬾🮈▎ ▔🮂🬂▀🬎🬎 🮅🬎▀🬂🮂▔ 🮇▌🭉
|
||||
🭿▍ ▂▁ ▁▂🬜΄🮈🬲
|
||||
🭥🬭🬭▂▁━▂▁ ▁▂━▂🬭🬭🭚
|
||||
▔⎺━▔🮂🬂🬂🬼 🭇🬂🬂🮂▔━⎺▔
|
||||
⠈🮂🭷╾🭄╼🬂🮂΄
|
||||
@@ -1,6 +1,6 @@
|
||||
$2,--, $1| $2,--,
|
||||
$2| `-, $1,^, $2,-' |
|
||||
$2 `, `-, $3(/ \) $2,-' ,'
|
||||
$2 `, `-, $1(/ \) $2,-' ,'
|
||||
$2 `-, `-,$1/ \$2,-' ,-'
|
||||
$2 `------$1( )$2------'
|
||||
$2 ,----------$1( )$2----------,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#####
|
||||
#####
|
||||
#####
|
||||
######
|
||||
######
|
||||
#####
|
||||
##### #####
|
||||
###### #####
|
||||
###### #####
|
||||
###### ######
|
||||
##### ######
|
||||
##### #####
|
||||
#####
|
||||
######
|
||||
######
|
||||
######
|
||||
#####
|
||||
#####
|
||||
@@ -0,0 +1,19 @@
|
||||
__ygg@@@@@@@@@ggy__
|
||||
_yg@@@@@@@@@@@@@@@@@@@@@gy_
|
||||
_a@@@@@@@@@@@@@@@@@@@@@@@@@@@@@y_
|
||||
_a@@@@@@@@@@@@@@@@@@@@@@@$2#$1@@@@@@@@@g_
|
||||
a@@@@@@@@@@@@@$2###$1@@@@@@@@$2##$1@@@@$2##$1@@@@@k
|
||||
g@@@@@@@$2###$1@@@$2#####$1@@@@@@@$2##$1@@$2###$1@@@@@@@k
|
||||
a@@@@@@@@$2#####$1@$2#####$1@@@@@@$2##$1@@$2###$1@@@@@@@@@k
|
||||
j@@@@@@@@@$2############$1@@@@@$2##$1@$2###$1@@@@@@@@@@@k
|
||||
g@@@@@@@@@$2#####################$1@@@@@@@@@@@@@@
|
||||
@@@@@@@@@$2##########################$1@@@@@@@@@@
|
||||
0@@@@@@@@$2###########################$1@@@@@@@@@
|
||||
~@@@@@@@$2############################$1@@@@@@@@F
|
||||
9@@@@@@$2##########################$1@@@@@@@@@P
|
||||
4@@@@@@$2######################$1@@@@@@@@@@@P
|
||||
~@@@@@@$2################$1@@@@@@@@@@@@@@@F
|
||||
`4@@@@@@$2#######$1@@@@@@@@@@@@@@@@@@@@P`
|
||||
`~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@F`
|
||||
~~4@@@@@@@@@@@@@@@@@@@@@P~~
|
||||
`~~=R@@@@@@@@@P=~~~
|
||||
+235
-210
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ static void* logoResize(const void* image, size_t width, size_t height, void* ex
|
||||
FFLogoImageResult ffLogoPrintImageIM6(FFLogoRequestData* requestData)
|
||||
{
|
||||
FF_LIBRARY_LOAD(imageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI" FF_LIBRARY_EXTENSION, 8, "libMagickCore-6.Q16" FF_LIBRARY_EXTENSION, 8)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
|
||||
FFLogoImageResult result = ffLogoPrintImageImpl(requestData, &(FFIMData) {
|
||||
.resizeFunc = logoResize,
|
||||
|
||||
@@ -19,7 +19,7 @@ FFLogoImageResult ffLogoPrintImageIM7(FFLogoRequestData* requestData)
|
||||
"libMagickCore-7.Q16" FF_LIBRARY_EXTENSION, 11,
|
||||
"libMagickCore-7.Q16HDRI-10" FF_LIBRARY_EXTENSION, -1 // Required for Windows
|
||||
)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
|
||||
FFLogoImageResult result = ffLogoPrintImageImpl(requestData, &(FFIMData) {
|
||||
.resizeFunc = logoResize,
|
||||
|
||||
@@ -708,8 +708,8 @@ static bool printImageChafa(FFLogoRequestData* requestData, const ImageData* ima
|
||||
|
||||
FFLogoImageResult ffLogoPrintImageImpl(FFLogoRequestData* requestData, const FFIMData* imData)
|
||||
{
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, MagickCoreGenesis, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, MagickCoreTerminus, FF_LOGO_IMAGE_RESULT_INIT_ERROR);
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, MagickCoreGenesis, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, MagickCoreTerminus, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, AcquireExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, DestroyExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
FF_LIBRARY_LOAD_SYMBOL(imData->library, AcquireImageInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
|
||||
|
||||
+61
-29
@@ -436,6 +436,13 @@ static void logoPrintNone(void)
|
||||
|
||||
static bool logoPrintBuiltinIfExists(const FFstrbuf* name, FFLogoSize size)
|
||||
{
|
||||
if(name->chars[0] == '~' || name->chars[0] == '.' || name->chars[0] == '/'
|
||||
#if _WIN32
|
||||
|| (ffCharIsEnglishAlphabet(name->chars[0]) && name->chars[1] == ':') // Windows drive letter
|
||||
#endif
|
||||
)
|
||||
return false; // Paths
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(name, "none"))
|
||||
{
|
||||
logoPrintNone();
|
||||
@@ -466,21 +473,22 @@ static bool logoPrintData(bool doColorReplacement, FFstrbuf* source)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void updateLogoPath(void)
|
||||
static bool updateLogoPath(void)
|
||||
{
|
||||
FFOptionsLogo* options = &instance.config.logo;
|
||||
|
||||
if(ffPathExists(options->source.chars, FF_PATHTYPE_FILE))
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (ffStrbufEqualS(&options->source, "-")) // stdin
|
||||
return;
|
||||
return true;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate();
|
||||
if (ffPathExpandEnv(options->source.chars, &fullPath) && ffPathExists(fullPath.chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
ffStrbufSet(&options->source, &fullPath);
|
||||
return;
|
||||
ffStrbufDestroy(&options->source);
|
||||
ffStrbufInitMove(&options->source, &fullPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance.state.platform.dataDirs)
|
||||
@@ -492,10 +500,13 @@ static void updateLogoPath(void)
|
||||
|
||||
if(ffPathExists(fullPath.chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
ffStrbufSet(&options->source, &fullPath);
|
||||
break;
|
||||
ffStrbufDestroy(&options->source);
|
||||
ffStrbufInitMove(&options->source, &fullPath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool logoPrintFileIfExists(bool doColorReplacement, bool raw)
|
||||
@@ -579,7 +590,13 @@ static bool logoTryKnownType(void)
|
||||
return logoPrintData(false, &source);
|
||||
}
|
||||
|
||||
updateLogoPath(); //We sure have a file, resolve relative paths
|
||||
//We sure have a file, resolve relative paths
|
||||
if (!updateLogoPath())
|
||||
{
|
||||
if (instance.config.display.showErrors)
|
||||
fprintf(stderr, "Logo: Failed to resolve logo source: %s\n", options->source.chars);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(options->type == FF_LOGO_TYPE_FILE)
|
||||
return logoPrintFileIfExists(true, false);
|
||||
@@ -642,31 +659,46 @@ void ffLogoPrint(void)
|
||||
return;
|
||||
|
||||
//Make sure the logo path is set correctly.
|
||||
updateLogoPath();
|
||||
if (updateLogoPath())
|
||||
{
|
||||
if (ffStrbufEndsWithIgnCaseS(&options->source, ".raw"))
|
||||
{
|
||||
if(logoPrintFileIfExists(false, true))
|
||||
return;
|
||||
}
|
||||
|
||||
const FFTerminalResult* terminal = ffDetectTerminal();
|
||||
if (!ffStrbufEndsWithIgnCaseS(&options->source, ".txt"))
|
||||
{
|
||||
const FFTerminalResult* terminal = ffDetectTerminal();
|
||||
|
||||
//Terminal emulators that support kitty graphics protocol.
|
||||
bool supportsKitty =
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "kitty") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "konsole") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "wezterm") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "ghostty") ||
|
||||
#ifdef __APPLE__
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "WarpTerminal") ||
|
||||
#else
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "warp") ||
|
||||
#endif
|
||||
false;
|
||||
//Terminal emulators that support kitty graphics protocol.
|
||||
bool supportsKitty =
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "kitty") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "konsole") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "wezterm") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst") ||
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "ghostty") ||
|
||||
#ifdef __APPLE__
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "WarpTerminal") ||
|
||||
#else
|
||||
ffStrbufIgnCaseEqualS(&terminal->processName, "warp") ||
|
||||
#endif
|
||||
false;
|
||||
|
||||
//Try to load the logo as an image. If it succeeds, print it and return.
|
||||
if(logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false))
|
||||
return;
|
||||
//Try to load the logo as an image. If it succeeds, print it and return.
|
||||
if(logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false))
|
||||
return;
|
||||
}
|
||||
|
||||
//Try to load the logo as a file. If it succeeds, print it and return.
|
||||
if(logoPrintFileIfExists(true, false))
|
||||
return;
|
||||
//Try to load the logo as a file. If it succeeds, print it and return.
|
||||
if(logoPrintFileIfExists(true, false))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (instance.config.display.showErrors)
|
||||
fprintf(stderr, "Logo: Failed to resolve logo source: %s\n", options->source.chars);
|
||||
}
|
||||
|
||||
logoPrintDetected(FF_LOGO_SIZE_UNKNOWN);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -92,7 +92,7 @@ void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -123,7 +123,7 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -122,7 +122,7 @@ void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_va
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -67,7 +67,7 @@ void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -67,7 +67,7 @@ void ffParseBootmgrJsonObject(FFBootmgrOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -144,7 +144,7 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -149,7 +149,7 @@ void ffParseBtrfsJsonObject(FFBtrfsOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -84,7 +84,7 @@ void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -68,7 +68,7 @@ void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -181,7 +181,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -78,7 +78,7 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -142,7 +142,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -154,7 +154,7 @@ void ffParseCPUCacheJsonObject(FFCPUCacheOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -27,6 +27,12 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
|
||||
if (*percent == *percent)
|
||||
{
|
||||
sumValue += *percent;
|
||||
|
||||
#if WIN32
|
||||
// Windows may return values greater than 100%, cap them to 100%
|
||||
if (*percent > 100) *percent = 100;
|
||||
#endif
|
||||
|
||||
if (*percent > maxValue)
|
||||
{
|
||||
maxValue = *percent;
|
||||
@@ -42,6 +48,10 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
|
||||
++index;
|
||||
}
|
||||
double avgValue = sumValue / (double) valueCount;
|
||||
#if WIN32
|
||||
// See above comment
|
||||
if (avgValue > 100) avgValue = 100;
|
||||
#endif
|
||||
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
|
||||
@@ -138,7 +148,7 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -65,7 +65,7 @@ void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -34,7 +34,7 @@ void ffParseCustomJsonObject(FFCustomOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -134,7 +134,7 @@ void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
+10
-2
@@ -125,7 +125,8 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index
|
||||
bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT);
|
||||
bool isReadOnly = !!(disk->type & FF_DISK_VOLUME_TYPE_READONLY_BIT);
|
||||
|
||||
uint64_t duration = ffTimeGetNow() - disk->createTime;
|
||||
uint64_t now = ffTimeGetNow();
|
||||
uint64_t duration = now - disk->createTime;
|
||||
uint32_t milliseconds = (uint32_t) (duration % 1000);
|
||||
duration /= 1000;
|
||||
uint32_t seconds = (uint32_t) (duration % 60);
|
||||
@@ -136,6 +137,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index
|
||||
duration /= 24;
|
||||
uint32_t days = (uint32_t) duration;
|
||||
|
||||
FFTimeGetAgeResult age = ffTimeGetAge(disk->createTime, now);
|
||||
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(usedPretty, "size-used"),
|
||||
FF_FORMAT_ARG(totalPretty, "size-total"),
|
||||
@@ -158,6 +160,9 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index
|
||||
FF_FORMAT_ARG(milliseconds, "milliseconds"),
|
||||
FF_FORMAT_ARG(disk->mountpoint, "mountpoint"),
|
||||
FF_FORMAT_ARG(disk->mountFrom, "mount-from"),
|
||||
FF_FORMAT_ARG(age.years, "years"),
|
||||
FF_FORMAT_ARG(age.daysOfYear, "days-of-year"),
|
||||
FF_FORMAT_ARG(age.yearsFraction, "years-fraction"),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -299,7 +304,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
@@ -523,6 +528,9 @@ static FFModuleBaseInfo ffModuleInfo = {
|
||||
{"Milliseconds after creation", "milliseconds"},
|
||||
{"Mount point / drive letter", "mountpoint"},
|
||||
{"Mount from (device path)", "mount-from"},
|
||||
{"Years integer after creation", "years"},
|
||||
{"Days of year after creation", "days-of-year"},
|
||||
{"Years fraction after creation", "years-fraction"},
|
||||
}))
|
||||
};
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -261,7 +261,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -85,7 +85,7 @@ void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -71,7 +71,7 @@ void ffParseEditorJsonObject(FFEditorOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -58,7 +58,7 @@ void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -97,7 +97,7 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -255,7 +255,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -84,7 +84,7 @@ void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -60,7 +60,7 @@ void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -65,7 +65,7 @@ void ffParseInitSystemJsonObject(FFInitSystemOptions* options, yyjson_val* modul
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -48,7 +48,7 @@ void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -65,7 +65,7 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
@@ -122,7 +122,7 @@ void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module)
|
||||
yyjson_obj_foreach(module, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
if(ffStrEqualsIgnCase(key, "type"))
|
||||
if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition"))
|
||||
continue;
|
||||
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user