mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da0db042fa | |||
| ae5732e2a8 | |||
| 1f05a33807 | |||
| f090951abc | |||
| 855fd6edee | |||
| d4bd4401a8 | |||
| 689feb39a4 | |||
| 0f64e2830a | |||
| 3e24cdc752 | |||
| dc9c285a0b | |||
| 1d03c9c85e | |||
| 4eae11df64 | |||
| eba13d5485 | |||
| 16b875ef5a | |||
| 366138e1bd | |||
| 7fe18a5b7c | |||
| 39cd8cfb4c | |||
| 8b441c85e5 | |||
| f66e901c44 | |||
| 3815823a20 | |||
| 33ff4870dc | |||
| 479731f076 | |||
| d2f3f47457 | |||
| 5ea89ecba5 | |||
| 865f57bd76 | |||
| e98e2a3d52 | |||
| 6bb748869e | |||
| 654721b8c5 | |||
| 0542eac1b9 | |||
| b9faf8d77f | |||
| 61f848146a | |||
| 4175dfdc3a | |||
| 861d9006d7 | |||
| 7ba07bd2e0 | |||
| 9fee36a286 | |||
| 2fc9230b29 | |||
| 5fb1286e15 | |||
| a4cace4765 | |||
| c6d2467a83 | |||
| db0d38202e | |||
| 9fbb23b135 | |||
| 3a990e495b | |||
| 648530ee8f | |||
| b12a59cdaf | |||
| 83c1fe26e6 | |||
| 217f98a36c | |||
| 1011e21ba8 | |||
| 08c6a6e4cb | |||
| 5e9fcaf7ca | |||
| 8b838cef61 | |||
| 22d9d8e196 | |||
| a789b8330a | |||
| 903ecf37f7 | |||
| c4a876f6aa | |||
| 82285ebeb4 | |||
| 36dadcdc7f | |||
| 030c05429a | |||
| a462a12370 | |||
| b386365d95 | |||
| 158db9d7c7 | |||
| 407bfa8c95 | |||
| 1449290e9e | |||
| 4c0ea7354d | |||
| 71cba2451a | |||
| ef3b5df048 | |||
| 3e98034e55 | |||
| 1c89101522 | |||
| 757e6271ff | |||
| c5c846aa22 | |||
| 23a59a15ec | |||
| 4798c619d0 | |||
| 023e767237 | |||
| 688d9b00ab | |||
| c2fe2f70dc | |||
| 3430c10ec2 | |||
| 9afcc00201 | |||
| cd783d1267 | |||
| 81480532e2 | |||
| 982e8a0117 | |||
| 8af88a3376 | |||
| 9ed2f13c78 | |||
| d7ea774d71 | |||
| a4b9784c48 | |||
| 3fe2d8091a | |||
| 78c903c403 | |||
| c42711ee26 | |||
| 367264e549 | |||
| 36a0c273f9 | |||
| 418106c485 | |||
| 1058e876a7 | |||
| 8721cc1ab5 | |||
| e12642e0b9 | |||
| 315bbb3020 | |||
| 0576d4ca26 | |||
| c309dbb844 | |||
| c71b04ba93 | |||
| f3417b1b05 | |||
| c597b7ec3a | |||
| 8b4586b914 | |||
| b65a0e2543 | |||
| 6e15a44168 | |||
| 6bd3d2c434 | |||
| 29644ef904 | |||
| 39dfcb6f10 | |||
| 882b17834c | |||
| bdd2908e6a | |||
| d4a402f4dd | |||
| 115b293ff5 | |||
| 6831c095ec | |||
| 81fb146869 | |||
| 35b54fd064 | |||
| 866e65749e | |||
| e157b9a51f | |||
| 74c89cc03f | |||
| 229c6674a4 | |||
| ab8ad7ffc0 | |||
| 6805cb16fb | |||
| e596d76430 | |||
| de4afb6507 | |||
| beb5f479d9 | |||
| e660e61027 | |||
| e3cdecdb14 | |||
| 40320e5efa | |||
| c2fd057126 | |||
| ea1ef0f347 | |||
| 04456d9807 | |||
| 18240524dc | |||
| 42b7d567a1 | |||
| 2790493cba | |||
| 8eabc49e12 | |||
| 3252812699 | |||
| 3fa308386f | |||
| 84ee7cef7c | |||
| 57f6aff2de | |||
| d745d7afef | |||
| 510a1f57f8 | |||
| a1c9b24755 | |||
| 75e6f48dfd | |||
| ed7b12e733 | |||
| 9c56839c97 | |||
| 6647980ce3 | |||
| 80f8b086ca | |||
| 8c2dd1aeac | |||
| ae3c6f1e63 | |||
| 7cc381339c | |||
| aa58a0999d | |||
| 4580f3fd54 | |||
| 6c0c4fa2cf | |||
| 526324be38 | |||
| efb0f335e1 | |||
| 9b23ce94ab | |||
| 47000f2aaf | |||
| cb3ca73f60 | |||
| fd0b35f21a | |||
| 0e7dda4043 | |||
| 5f7b9d2473 | |||
| f8cbe4c008 | |||
| 41df915f29 | |||
| ef440a015d | |||
| 180cbce3a2 | |||
| 64ec76f5a6 | |||
| 9860fb67d4 | |||
| 08cbba1d9d | |||
| 095149a4e9 | |||
| a561a96a5f | |||
| 073d6a9337 | |||
| 6851c9cc1a | |||
| 2862f466f3 | |||
| 5e3fdc6c33 | |||
| 03fe5803de | |||
| 6d36ec55c5 | |||
| f098cdbf69 | |||
| 07d3fe3044 | |||
| 636b6fc43d | |||
| ccfba6786c | |||
| 7c2c631807 |
@@ -59,6 +59,10 @@ strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
|
||||
|
||||
If you cannot do the instructions above, please upload the core dump file:
|
||||
|
||||
## If fastfetch is slow
|
||||
|
||||
Use `time fastfetch --stat` to show time usage for each module.
|
||||
|
||||
## If my image logo didn't show / work
|
||||
|
||||
<!-- Please make sure the terminal does support the image protocol you used. Note Gnome terminal doesn't support any image protocols -->
|
||||
|
||||
@@ -11,7 +11,7 @@ Tip: A logo can be displayed by fastfetch without getting into fastfetch's offic
|
||||
|
||||
# OS
|
||||
```
|
||||
Paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
|
||||
Paste content of /etc/os-release and /etc/lsb-release here. If none of these files exist, describe a way to identify the distro
|
||||
```
|
||||
|
||||
# Ascii
|
||||
|
||||
+131
-88
@@ -14,66 +14,16 @@ jobs:
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
run: sudo apt update && sudo apt install -y codespell
|
||||
run: |
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y codespell
|
||||
|
||||
- name: Run Spellchecker
|
||||
run: codespell
|
||||
|
||||
linux-buildtest:
|
||||
name: Linux build test
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
compiler: [
|
||||
{ cc: gcc, cxx: "g++" },
|
||||
{ cc: clang, cxx: "clang++" },
|
||||
{ cc: "musl-gcc", cxx: "musl-g++" }
|
||||
]
|
||||
enableFeatures: [ON, OFF]
|
||||
exclude:
|
||||
# The feature libraries are all build against glibc, so they can't be used with musl
|
||||
- compiler: { cc: "musl-gcc", cxx: "musl-g++" }
|
||||
enableFeatures: ON
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libddcutil-dev libchafa-dev libdrm-dev directx-headers-dev
|
||||
|
||||
- name: configure project
|
||||
env:
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} -DENABLE_DRM=${{ matrix.enableFeatures }} -DENABLE_DDCUTIL=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: run fastfetch --list-features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
Linux-old-amd64:
|
||||
name: Linux-old-amd64
|
||||
runs-on: ubuntu-20.04
|
||||
no-features-test:
|
||||
name: No-features-test
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -84,28 +34,12 @@ jobs:
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_LIBNM=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
@@ -124,15 +58,9 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-old-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
runs-on: ubuntu-22.04 # Ubuntu 22.04 uses Glibc 2.35. Should be fine with Debian 12, which uses Glibc 2.36 (https://packages.debian.org/source/bookworm/glibc)
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -146,12 +74,12 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -230,9 +158,126 @@ jobs:
|
||||
name: fastfetch-linux-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv7:
|
||||
name: Linux-armv7
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv7
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
|
||||
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
|
||||
dpkg -i *.deb
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv7
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-amd64:
|
||||
name: Musl-amd64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: run
|
||||
run: |
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-aarch64:
|
||||
name: Musl-aarch64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
with:
|
||||
arch: aarch64
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: run
|
||||
run: |
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-musl-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-12
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -495,6 +540,9 @@ jobs:
|
||||
needs:
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- linux-armv7
|
||||
- musl-amd64
|
||||
- musl-aarch64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
- freebsd-aarch64
|
||||
@@ -513,11 +561,6 @@ jobs:
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: rm old artifacts
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
rm -rf fastfetch-*-old-*
|
||||
|
||||
- name: create release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
|
||||
+147
@@ -1,3 +1,150 @@
|
||||
# 2.11.5
|
||||
|
||||
Bugfix:
|
||||
|
||||
* Fix logo printing for OpenMandriva (#896)
|
||||
* Remove `--os-file` in help messages
|
||||
|
||||
# 2.11.4
|
||||
|
||||
Changes:
|
||||
|
||||
* Fastfetch will print a colorless ascii logo in `--pipe` mode for better `lolcat` compatibility. `fastfetch | lolcat` should work and no `--pipe false` needed.
|
||||
* Previously the logo would be disabled in `--pipe` mode.
|
||||
* `--os-file` was removed and CMake option `-DCUSTOM_OS_RELEASE_PATH=/path/to/os-release` was added. This option should not used in most cases.
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix possible out-of-bound memory access (#868)
|
||||
* Fix Apple Terminal detection (macOS, Terminal)
|
||||
* Fix doubled output in custom formation (#852)
|
||||
* Fix deprecation warning for macOS 14.0 hopefully (#860, macOS, Camera)
|
||||
* Fix memory leaks when passing informative options
|
||||
* Fix JSON config `size.ndigits` doesn't work
|
||||
|
||||
Features:
|
||||
|
||||
* Enable `--pipe` mode if environment variable `$NO_COLOR` is set
|
||||
* Support Armbian and Proxmox distro detection (OS, Linux)
|
||||
|
||||
Logo:
|
||||
|
||||
* Add Armbian
|
||||
|
||||
# 2.11.3
|
||||
|
||||
Hotfix for nix (https://github.com/NixOS/nixpkgs/issues/308849#issuecomment-2093962376)
|
||||
|
||||
Features:
|
||||
* Add cmake option `CUSTOM_AMDGPU_IDS_PATH` for specifying custom path of `amdgpu.ids`
|
||||
|
||||
Bugfixes:
|
||||
* Fix hanging when detecting disconnected network drive (Disk, Windows)
|
||||
* Ensure line ending is printed when printing image logo errors (Logo)
|
||||
* Revert image logo limitation change in 2.11.2; allow image logo in SSH session and tmux again (#861, Logo)
|
||||
* Fix doubled output in custom formation (PhysicalDisk, Windows)
|
||||
|
||||
# 2.11.2
|
||||
|
||||
Hotfix for Debian 11
|
||||
|
||||
Changes:
|
||||
* Error messages when trying to print image logo will only be printed with `--show-errors`
|
||||
* When generating JSON output, fastfetch will generate an empty array when no result is detected, instead of an error.
|
||||
|
||||
Bugfixes:
|
||||
* Fix segfault in Debian 11 and some old kernels. Regression introduced in 2.11.0 (#845, GPU, Linux)
|
||||
* Don't try detecting version of raw `sh` shell (#849, Shell, Linux)
|
||||
* Trim `\r` on Windows
|
||||
|
||||
Features:
|
||||
* Check xdg state home for nix user packages (#837, Packages, Linux)
|
||||
* Disable image logos in ssh and tmux sessions (#839)
|
||||
* Support MX Linux distro detection (#847, OS, Linux)
|
||||
|
||||
Logo:
|
||||
* Add KernelOS
|
||||
* Fix name of DraugerOS
|
||||
* Add missing `FF_LOGO_LINE_TYPE_SMALL_BIT` flags
|
||||
* Add MX2
|
||||
|
||||
# 2.11.1
|
||||
|
||||
Hotfix for Android
|
||||
|
||||
Bugfixes:
|
||||
* Fix uninitialized variables which can cause crashes (#760 #838, Battery, Android)
|
||||
* Don't detect hyfetch as shell when used as backend of [hyfetch](https://github.com/hykilpikonna/hyfetch)
|
||||
* Fix incorrect information in man page (#828)
|
||||
|
||||
Features:
|
||||
* Support sorcery package manager detection (Packages, Linux)
|
||||
* Make `--custom-format` optional (Custom)
|
||||
* Make `/` an alias of `C:\` for `--disk-folders` (Disk, Windows)
|
||||
* Build for Linux armv7
|
||||
|
||||
Logo:
|
||||
* Fix colors of Source Mage logo
|
||||
|
||||
# 2.11.0
|
||||
|
||||
Changes:
|
||||
* Default `hideCursor` to false. It doesn't make much difference but makes user's terminal unusable if fastfetch is not exited correctly.
|
||||
* Linux amd64 binaries are built with Ubuntu 20.04 again (#808)
|
||||
|
||||
Bugfixes:
|
||||
* Fix swap usage detection in x86-32 build (Windows, Swap)
|
||||
* Fix minimum cmake version support (#810)
|
||||
* Fix wifi detection on platforms that don't use NetworkManager (#811, Wifi, Linux)
|
||||
* Fix NixOS wrapped process name (#814, Terminal, Linux)
|
||||
* Fix GPU type detection for AMD cards (#816, GPU, Linux)
|
||||
* Silence system deprecation warnings (#822, Camera, macOS)
|
||||
|
||||
Features:
|
||||
* Add basic support DE detection support for UKUI (DE, Linux)
|
||||
* Support printing total number of nix / flatpak / brew packages (Packages)
|
||||
* See `fastfetch -h packages-format` for detail
|
||||
* Better max CPU frequency detection support with `CPUID / 16H` instruction (CPU, Windows)
|
||||
* This requires Intel Core I Gen 6 or newer, and with `Virtual Machine Platform` Windows feature disabled. X86 only.
|
||||
* Improve performance of nix packages detection (Packages, Linux)
|
||||
* Make config specified in JSONC overridable by command line flags
|
||||
* Note this change only make global config overridable; module configs are still not
|
||||
* Suggest increasing `--processing-timeout` when child process timeouts
|
||||
* Only detect folders that specified by `--disk-folders`
|
||||
* Previously `--disk-folders` only omits unmatched disks from output
|
||||
* This option can be used to improve detection performance by ignoring slow network drives
|
||||
|
||||
# 2.10.2
|
||||
|
||||
Bugfixes:
|
||||
* Fix a regression that detect x11 as wayland (#805, WM, Linux)
|
||||
|
||||
# 2.10.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix build with `-DENABLE_DBUS=OFF` (Linux)
|
||||
|
||||
# 2.10.0
|
||||
|
||||
Changes:
|
||||
* We now always detect max frequency of GPUs for consistent, instead of current frequency
|
||||
|
||||
Features:
|
||||
* Improve display detection for wlroots based WMs. Fastfetch now correctly reports fractional scale factors in hyprland (Display, Linux)
|
||||
* Improve GPU detection on Linux (GPU, Linux)
|
||||
* Support GPU memory usage detection for AMD GPUs
|
||||
* Support GPU frequency detection for Intel GPUs
|
||||
* Improve performance of Gnome version detection (DE, Linux)
|
||||
* Improve performance of kitty version detection (Terminal, Linux)
|
||||
* Detect refresh rate when using `--ds-force-drm sysfs-only` (Display, Linux)
|
||||
* Add option `--ts-version` to disable terminal and shell version detection. Mainly for benchmarking purposes
|
||||
* Improve performance of detecting WSL version (Host, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Correctly detect `/bin/sh` as current shell if it's used as default shell (#798, Shell, Linux)
|
||||
* Work around an issue which CPU module reports incorrect CPU frequency that is too high (#800, CPU, Linux)
|
||||
* Don't print ANSI escape codes in `--pipe` mode
|
||||
|
||||
# 2.9.2
|
||||
|
||||
Changes:
|
||||
|
||||
+47
-14
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.9.2
|
||||
VERSION 2.11.5
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -75,9 +75,12 @@ option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
option(ENABLE_PROPRIETARY_GPU_DRIVER_API "Enable proprietary GPU driver API (NVML, IGCL and AGS)" ON)
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
|
||||
|
||||
if (LINUX)
|
||||
set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
|
||||
set(CUSTOM_AMDGPU_IDS_PATH "" CACHE STRING "Custom path to file amdgpu.ids, defaults to `/usr/share/libdrm/amdgpu.ids`")
|
||||
set(CUSTOM_OS_RELEASE_PATH "" CACHE STRING "Custom path to file os-release, defaults to `/etc/os-release`")
|
||||
endif()
|
||||
|
||||
####################
|
||||
@@ -254,7 +257,7 @@ file(GLOB LOGO_FILES "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)
|
||||
get_filename_component(file "${file}" NAME_WLE)
|
||||
get_filename_component(file "${file}" NAME_WE)
|
||||
string(TOUPPER "${file}" file)
|
||||
string(REGEX REPLACE "\\$\\{c([0-9]+)\\}" "$\\1" content "${content}")
|
||||
set(LOGO_BUILTIN_H "${LOGO_BUILTIN_H}#define FASTFETCH_DATATEXT_LOGO_${file} ${content}\n")
|
||||
@@ -399,7 +402,10 @@ if(LINUX)
|
||||
src/detection/diskio/diskio_linux.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
@@ -517,7 +523,10 @@ elseif(BSD)
|
||||
src/detection/diskio/diskio_bsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
@@ -777,6 +786,14 @@ if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
|
||||
endif()
|
||||
if(NOT "${CUSTOM_AMDGPU_IDS_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of amdgpu.ids: ${CUSTOM_AMDGPU_IDS_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
|
||||
endif()
|
||||
if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
|
||||
endif()
|
||||
|
||||
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
|
||||
if(NOT ENABLE_${VARNAME})
|
||||
@@ -926,10 +943,6 @@ if(ENABLE_THREADS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_PCI_MEMORY)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_PCI_MEMORY)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
@@ -1131,17 +1144,37 @@ else() # We don't use this in Windows
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
if(IS_MUSL)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
|
||||
find_program(HAVE_DPKG "dpkg")
|
||||
if(HAVE_DPKG)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB")
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
if(NOT IS_MUSL)
|
||||
EXECUTE_PROCESS (
|
||||
COMMAND getconf GNU_LIBC_VERSION
|
||||
OUTPUT_VARIABLE GLIBC_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
STRING (REPLACE "glibc " "" GLIBC_VERSION ${GLIBC_VERSION})
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= ${GLIBC_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_program(HAVE_RPMBUILD "rpmbuild")
|
||||
if(HAVE_RPMBUILD)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# Development help
|
||||
|
||||
This file is not an official documentation!
|
||||
Here i just add things that are easy to forget.
|
||||
|
||||
## Features i am planning to implement
|
||||
|
||||
### Specific
|
||||
|
||||
- [ ] Split the project in different libs / executables, all linking static by default:
|
||||
- `libffdetect`: contains all the detection stuff. To be used by anything that needs system information
|
||||
- `libffprint`: contains the printing functions, logos, format etc
|
||||
- `fastfetch` and `flashfetch`: Executables, that initialize the config of libffprint. Fist one at runtime, second one at compile time
|
||||
- [ ] Make LocalIP module more configurable
|
||||
- [ ] Automatic migrate old config files to newer versions
|
||||
- [ ] ZSH completions
|
||||
- [ ] Fish completions
|
||||
- [ ] Make CPU usage detection much faster and more accurate
|
||||
- [ ] Detect CPU usage in a common detection method and expose it both to the cpuUsage module and the cpu format string
|
||||
- [ ] Per session caching
|
||||
|
||||
### General
|
||||
- More presets
|
||||
- More logos
|
||||
- More package managers
|
||||
- More DE detections
|
||||
- More WM theme detections
|
||||
- More terminal font detections
|
||||
- Performance optimizations
|
||||
- More module specific options
|
||||
- Better error handling, especially the messages shown when using --show-errors
|
||||
- Using package managers libraries for package count detection instead own. E.g. using libalpm instead of counting files in /var/lib/pacman/local
|
||||
- Better documentation (especially default config file and the various --help options. Colored output?)
|
||||
- General feature parity with neofetch, to demonstrate supremity of c
|
||||
@@ -27,11 +27,11 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
|
||||
|
||||
### Linux
|
||||
|
||||
Some distros packaged a outdated fastfetch version. Older version is not supported, please always ensure that the latest version is used.
|
||||
Some distros packaged an outdated fastfetch version. Older version is not supported, please always ensure that the latest version is used.
|
||||
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or above)
|
||||
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch-<version>-Linux.deb` (for Ubuntu 22.04 or above and Debian 12 or above).
|
||||
* Arch Linux: `sudo pacman -S fastfetch`. You can also find fastfetch [on the AUR](https://aur.archlinux.org/packages/fastfetch-git).
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
* Arch Linux: `sudo pacman -S fastfetch`
|
||||
* Fedora: `sudo dnf install fastfetch`
|
||||
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
|
||||
* Alpine: `apk add --upgrade fastfetch`
|
||||
@@ -41,7 +41,9 @@ Some distros packaged a outdated fastfetch version. Older version is not support
|
||||
|
||||
Replace sudo with doas depending on what you use.
|
||||
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging)
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging).
|
||||
|
||||
If fastfetch is not packaged for your distro or an outdated version is packaged, [linuxbrew](https://brew.sh/) is a good alternate: `brew install fastfetch`
|
||||
|
||||
### macOS
|
||||
|
||||
|
||||
@@ -360,7 +360,6 @@ __fastfetch_completion()
|
||||
local FF_OPTIONS_PATH=(
|
||||
"-c"
|
||||
"--config"
|
||||
"--os-file"
|
||||
"--lib-pci"
|
||||
"--lib-vulkan"
|
||||
"--lib-wayland"
|
||||
|
||||
Vendored
+12
@@ -1,3 +1,15 @@
|
||||
fastfetch (2.9.2) jammy; urgency=medium
|
||||
|
||||
* Update to 2.9.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 16 Apr 2024 16:32:40 +0800
|
||||
|
||||
fastfetch (2.9.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.9.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Apr 2024 09:34:30 +0800
|
||||
|
||||
fastfetch (2.8.10) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.10
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.8.10_source.buildinfo universe/utils optional
|
||||
fastfetch_2.9.2_source.buildinfo universe/utils optional
|
||||
|
||||
+5
-8
@@ -107,12 +107,12 @@ To list all available modules, use \fB \-\-list\-modules \fR
|
||||
|
||||
.SS "Config Files"
|
||||
|
||||
fastfetch supports two types of config files. The legacy
|
||||
configuration files and a JSONC based format.
|
||||
Fastfetch uses JSONC based format for configuration. Fastfetch doesn't generate
|
||||
config file automatically; it should be generated manually by \fB \-\-gen\-config\fR.
|
||||
The config file will be saved in \fB~/.config/fastfetch/config.jsonc\fR by default.
|
||||
|
||||
A JSONC config file is a JSON file that also supports comments with (//). Those
|
||||
files must have the extension '.jsonc'. You can migrate a legacy config
|
||||
file to the JSONC format by using \fB\-\-gen\-config\fR.
|
||||
files must have the extension '.jsonc'.
|
||||
|
||||
The specified configuration/preset files are searched in the following order:
|
||||
|
||||
@@ -122,10 +122,7 @@ The specified configuration/preset files are searched in the following order:
|
||||
|
||||
3. relative to /usr/share/fastfetch/presets/
|
||||
|
||||
When both a '.jsonc' and a '.conf' file with the same name is found,
|
||||
the '.jsonc' file is preferred.
|
||||
|
||||
Fastfetch provides some default presets. List them with \fB \-\-print\-available\-presets\fR.
|
||||
Fastfetch provides some default presets. List them with \fB\-\-list\-presets\fR.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR neofetch (1)
|
||||
|
||||
+15
-9
@@ -294,10 +294,6 @@
|
||||
"type": "string",
|
||||
"description": "The name of the player to use for module Media and Player. Linux only"
|
||||
},
|
||||
"osFile": {
|
||||
"type": "string",
|
||||
"description": "Set the path to the file containing OS information. Linux only"
|
||||
},
|
||||
"dsForceDrm": {
|
||||
"description": "Force display detection to use DRM. Linux only",
|
||||
"oneOf": [
|
||||
@@ -549,6 +545,11 @@
|
||||
"type": "boolean",
|
||||
"description": "Whether to disable the stdout application buffer",
|
||||
"default": false
|
||||
},
|
||||
"tsVersion": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to detect and display the version of terminal and shell. Mainly for benchmarking",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -674,6 +675,7 @@
|
||||
"board",
|
||||
"break",
|
||||
"brightness",
|
||||
"camera",
|
||||
"chassis",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
@@ -767,6 +769,10 @@
|
||||
"const": "board",
|
||||
"description": "Print mather board name and other info"
|
||||
},
|
||||
{
|
||||
"const": "camera",
|
||||
"description": "Print available cameras"
|
||||
},
|
||||
{
|
||||
"const": "cursor",
|
||||
"description": "Print cursor style name"
|
||||
@@ -1107,6 +1113,9 @@
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1164,10 +1173,7 @@
|
||||
"description": "Text to print",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"format"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Display",
|
||||
@@ -1228,7 +1234,7 @@
|
||||
},
|
||||
"folders": {
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points"
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options"
|
||||
},
|
||||
"showExternal": {
|
||||
"type": "boolean",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "file:///C:/msys64/home/zhang/fastfetch/doc/json_schema.json",
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small",
|
||||
"padding": {
|
||||
"top": 1
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"separator": "",
|
||||
"keyWidth": 15
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"key": "╭───────────╮",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
// draw borders first to make colors of left and right border consistant
|
||||
"key": "│ │\u001b[11D\u001b[31m user",
|
||||
"type": "title",
|
||||
"format": "{1}"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[32m hname",
|
||||
"type": "title",
|
||||
"format": "{2}"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[33m uptime",
|
||||
"type": "uptime"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[34m distro",
|
||||
"type": "os"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[35m kernel",
|
||||
"type": "kernel"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[36m desktop",
|
||||
"type": "de"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[31m term",
|
||||
"type": "terminal"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[32m shell",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[33m cpu",
|
||||
"type": "cpu"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[34m disk",
|
||||
"type": "disk",
|
||||
"folders": "/"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[35m memory",
|
||||
"type": "memory"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[36m network",
|
||||
"type": "localip",
|
||||
"format": "{1} ({4})"
|
||||
},
|
||||
{
|
||||
"key": "├───────────┤",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"key": "│ │\u001b[11D\u001b[m colors",
|
||||
"type": "colors",
|
||||
"symbol": "circle"
|
||||
},
|
||||
{
|
||||
"key": "╰───────────╯",
|
||||
"type": "custom"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -9,8 +9,7 @@
|
||||
"modules": [
|
||||
{
|
||||
"type": "theme",
|
||||
"key": "T",
|
||||
"format": "{7}"
|
||||
"key": "T"
|
||||
},
|
||||
{
|
||||
"type": "icons",
|
||||
|
||||
+9
-12
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"display": {
|
||||
"size": {
|
||||
"maxPrefix": "MB",
|
||||
"ndigits": 0
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
{
|
||||
"type": "os",
|
||||
"format": "{3} {12}"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"format": "{/2}{-}{/}{2}{?3} {3}{?}"
|
||||
},
|
||||
"os",
|
||||
"host",
|
||||
"kernel",
|
||||
"uptime",
|
||||
"packages",
|
||||
@@ -23,10 +23,7 @@
|
||||
"de",
|
||||
"wm",
|
||||
"wmtheme",
|
||||
{
|
||||
"type": "theme",
|
||||
"format": "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}"
|
||||
},
|
||||
"theme",
|
||||
"icons",
|
||||
"terminal",
|
||||
{
|
||||
|
||||
Vendored
+257
@@ -1229,6 +1229,18 @@ typedef struct _ctl_lda_args_t ctl_lda_args_t;
|
||||
/// @brief Forward-declare ctl_dce_args_t
|
||||
typedef struct _ctl_dce_args_t ctl_dce_args_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Forward-declare ctl_wire_format_t
|
||||
typedef struct _ctl_wire_format_t ctl_wire_format_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Forward-declare ctl_get_set_wire_format_config_t
|
||||
typedef struct _ctl_get_set_wire_format_config_t ctl_get_set_wire_format_config_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Forward-declare ctl_display_settings_t
|
||||
typedef struct _ctl_display_settings_t ctl_display_settings_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Forward-declare ctl_engine_properties_t
|
||||
typedef struct _ctl_engine_properties_t ctl_engine_properties_t;
|
||||
@@ -2029,6 +2041,8 @@ typedef enum _ctl_std_display_feature_flag_t
|
||||
CTL_STD_DISPLAY_FEATURE_FLAG_VESA_COMPRESSION = CTL_BIT(4), ///< [out] Is display compression (VESA DSC) supported
|
||||
CTL_STD_DISPLAY_FEATURE_FLAG_HDR = CTL_BIT(5), ///< [out] Is HDR supported
|
||||
CTL_STD_DISPLAY_FEATURE_FLAG_HDMI_QMS = CTL_BIT(6), ///< [out] Is HDMI QMS supported
|
||||
CTL_STD_DISPLAY_FEATURE_FLAG_HDR10_PLUS_CERTIFIED = CTL_BIT(7), ///< [out] Is HDR10+ certified
|
||||
CTL_STD_DISPLAY_FEATURE_FLAG_VESA_HDR_CERTIFIED = CTL_BIT(8), ///< [out] Is VESA HDR certified - for future use
|
||||
CTL_STD_DISPLAY_FEATURE_FLAG_MAX = 0x80000000
|
||||
|
||||
} ctl_std_display_feature_flag_t;
|
||||
@@ -2042,6 +2056,7 @@ typedef enum _ctl_intel_display_feature_flag_t
|
||||
CTL_INTEL_DISPLAY_FEATURE_FLAG_DPST = CTL_BIT(0), ///< [out] Is DPST supported
|
||||
CTL_INTEL_DISPLAY_FEATURE_FLAG_LACE = CTL_BIT(1), ///< [out] Is LACE supported
|
||||
CTL_INTEL_DISPLAY_FEATURE_FLAG_DRRS = CTL_BIT(2), ///< [out] Is DRRS supported
|
||||
CTL_INTEL_DISPLAY_FEATURE_FLAG_ARC_ADAPTIVE_SYNC_CERTIFIED = CTL_BIT(3),///< [out] Is Intel Arc certified adaptive sync display
|
||||
CTL_INTEL_DISPLAY_FEATURE_FLAG_MAX = 0x80000000
|
||||
|
||||
} ctl_intel_display_feature_flag_t;
|
||||
@@ -4398,6 +4413,232 @@ ctlGetSetDynamicContrastEnhancement(
|
||||
ctl_dce_args_t* pDceArgs ///< [in,out] Dynamic Contrast Enhancement arguments
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Color model
|
||||
typedef enum _ctl_wire_format_color_model_t
|
||||
{
|
||||
CTL_WIRE_FORMAT_COLOR_MODEL_RGB = 0, ///< Color model RGB
|
||||
CTL_WIRE_FORMAT_COLOR_MODEL_YCBCR_420 = 1, ///< Color model YCBCR 420
|
||||
CTL_WIRE_FORMAT_COLOR_MODEL_YCBCR_422 = 2, ///< Color model YCBCR 422
|
||||
CTL_WIRE_FORMAT_COLOR_MODEL_YCBCR_444 = 3, ///< Color model YCBCR 444
|
||||
CTL_WIRE_FORMAT_COLOR_MODEL_MAX
|
||||
|
||||
} ctl_wire_format_color_model_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Operation type
|
||||
typedef enum _ctl_wire_format_operation_type_t
|
||||
{
|
||||
CTL_WIRE_FORMAT_OPERATION_TYPE_GET = 0, ///< Get request
|
||||
CTL_WIRE_FORMAT_OPERATION_TYPE_SET = 1, ///< Set request
|
||||
CTL_WIRE_FORMAT_OPERATION_TYPE_RESTORE_DEFAULT = 2, ///< Restore to default values
|
||||
CTL_WIRE_FORMAT_OPERATION_TYPE_MAX
|
||||
|
||||
} ctl_wire_format_operation_type_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Wire Format
|
||||
typedef struct _ctl_wire_format_t
|
||||
{
|
||||
uint32_t Size; ///< [in] size of this structure
|
||||
uint8_t Version; ///< [in] version of this structure
|
||||
ctl_wire_format_color_model_t ColorModel; ///< [in,out] Color model
|
||||
ctl_output_bpc_flags_t ColorDepth; ///< [in,out] Color Depth
|
||||
|
||||
} ctl_wire_format_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef CTL_MAX_WIREFORMAT_COLOR_MODELS_SUPPORTED
|
||||
/// @brief Maximum Wire Formats Supported
|
||||
#define CTL_MAX_WIREFORMAT_COLOR_MODELS_SUPPORTED 4
|
||||
#endif // CTL_MAX_WIREFORMAT_COLOR_MODELS_SUPPORTED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get Set Wire Format
|
||||
typedef struct _ctl_get_set_wire_format_config_t
|
||||
{
|
||||
uint32_t Size; ///< [in] size of this structure
|
||||
uint8_t Version; ///< [in] version of this structure
|
||||
ctl_wire_format_operation_type_t Operation; ///< [in] Get/Set Operation
|
||||
ctl_wire_format_t SupportedWireFormat[CTL_MAX_WIREFORMAT_COLOR_MODELS_SUPPORTED]; ///< [out] Array of WireFormats supported
|
||||
ctl_wire_format_t WireFormat; ///< [in,out] Current/Requested WireFormat based on Operation. During SET
|
||||
///< Operation, if multiple bpc is set, the MIN bpc will be applied
|
||||
|
||||
} ctl_get_set_wire_format_config_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get/Set Color Format and Color Depth
|
||||
///
|
||||
/// @details
|
||||
/// - Get and Set the Color Format and Color Depth of a target
|
||||
///
|
||||
/// @returns
|
||||
/// - CTL_RESULT_SUCCESS
|
||||
/// - CTL_RESULT_ERROR_UNINITIALIZED
|
||||
/// - CTL_RESULT_ERROR_DEVICE_LOST
|
||||
/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE
|
||||
/// + `nullptr == hDisplayOutput`
|
||||
/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER
|
||||
/// + `nullptr == pGetSetWireFormatSetting`
|
||||
/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version"
|
||||
/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid data passed as argument, WireFormat is not supported"
|
||||
/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE - "Display not active"
|
||||
/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type"
|
||||
/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle"
|
||||
/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface"
|
||||
/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle"
|
||||
CTL_APIEXPORT ctl_result_t CTL_APICALL
|
||||
ctlGetSetWireFormat(
|
||||
ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output
|
||||
ctl_get_set_wire_format_config_t* pGetSetWireFormatSetting ///< [in][release] Get/Set Wire Format settings to be fetched/applied
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Various display settings
|
||||
typedef uint32_t ctl_display_setting_flags_t;
|
||||
typedef enum _ctl_display_setting_flag_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_FLAG_LOW_LATENCY = CTL_BIT(0), ///< Low latency
|
||||
CTL_DISPLAY_SETTING_FLAG_SOURCE_TM = CTL_BIT(1),///< Source tone mapping
|
||||
CTL_DISPLAY_SETTING_FLAG_CONTENT_TYPE = CTL_BIT(2), ///< Content type
|
||||
CTL_DISPLAY_SETTING_FLAG_QUANTIZATION_RANGE = CTL_BIT(3), ///< Quantization range, full range or limited range
|
||||
CTL_DISPLAY_SETTING_FLAG_PICTURE_AR = CTL_BIT(4), ///< Picture aspect ratio
|
||||
CTL_DISPLAY_SETTING_FLAG_AUDIO = CTL_BIT(5), ///< Audio settings
|
||||
CTL_DISPLAY_SETTING_FLAG_MAX = 0x80000000
|
||||
|
||||
} ctl_display_setting_flag_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Low latency setting
|
||||
typedef enum _ctl_display_setting_low_latency_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_LOW_LATENCY_DEFAULT = 0, ///< Default
|
||||
CTL_DISPLAY_SETTING_LOW_LATENCY_DISABLED = 1, ///< Disabled
|
||||
CTL_DISPLAY_SETTING_LOW_LATENCY_ENABLED = 2, ///< Enabled
|
||||
CTL_DISPLAY_SETTING_LOW_LATENCY_MAX
|
||||
|
||||
} ctl_display_setting_low_latency_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Source tone mapping setting
|
||||
typedef enum _ctl_display_setting_sourcetm_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_SOURCETM_DEFAULT = 0, ///< Default
|
||||
CTL_DISPLAY_SETTING_SOURCETM_DISABLED = 1, ///< Disabled
|
||||
CTL_DISPLAY_SETTING_SOURCETM_ENABLED = 2, ///< Enabled
|
||||
CTL_DISPLAY_SETTING_SOURCETM_MAX
|
||||
|
||||
} ctl_display_setting_sourcetm_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Content type settings
|
||||
typedef enum _ctl_display_setting_content_type_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_CONTENT_TYPE_DEFAULT = 0, ///< Default content type used by driver. Driver will use internal
|
||||
///< techniques to determine content type and indicate to panel
|
||||
CTL_DISPLAY_SETTING_CONTENT_TYPE_DISABLED = 1, ///< Content type indication is disabled
|
||||
CTL_DISPLAY_SETTING_CONTENT_TYPE_DESKTOP = 2, ///< Typical desktop with a mix of text and graphics
|
||||
CTL_DISPLAY_SETTING_CONTENT_TYPE_MEDIA = 3, ///< Video or media content
|
||||
CTL_DISPLAY_SETTING_CONTENT_TYPE_GAMING = 4, ///< Gaming content
|
||||
CTL_DISPLAY_SETTING_CONTENT_TYPE_MAX
|
||||
|
||||
} ctl_display_setting_content_type_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Quantization range
|
||||
typedef enum _ctl_display_setting_quantization_range_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_QUANTIZATION_RANGE_DEFAULT = 0, ///< Default based on video format
|
||||
CTL_DISPLAY_SETTING_QUANTIZATION_RANGE_LIMITED_RANGE = 1, ///< Limited range
|
||||
CTL_DISPLAY_SETTING_QUANTIZATION_RANGE_FULL_RANGE = 2, ///< Full range
|
||||
CTL_DISPLAY_SETTING_QUANTIZATION_RANGE_MAX
|
||||
|
||||
} ctl_display_setting_quantization_range_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Picture aspect ratio
|
||||
typedef uint32_t ctl_display_setting_picture_ar_flags_t;
|
||||
typedef enum _ctl_display_setting_picture_ar_flag_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_DEFAULT = CTL_BIT(0), ///< Default picture aspect ratio
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_DISABLED = CTL_BIT(1), ///< Picture aspect ratio indication is explicitly disabled
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_AR_4_3 = CTL_BIT(2),///< Aspect ratio of 4:3
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_AR_16_9 = CTL_BIT(3), ///< Aspect ratio of 16:9
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_AR_64_27 = CTL_BIT(4), ///< Aspect ratio of 64:27 or 21:9 anamorphic
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_AR_256_135 = CTL_BIT(5),///< Aspect ratio of 256:135
|
||||
CTL_DISPLAY_SETTING_PICTURE_AR_FLAG_MAX = 0x80000000
|
||||
|
||||
} ctl_display_setting_picture_ar_flag_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Audio settings
|
||||
typedef enum _ctl_display_setting_audio_t
|
||||
{
|
||||
CTL_DISPLAY_SETTING_AUDIO_DEFAULT = 0, ///< Default audio settings, always enumerated and enabled if display
|
||||
///< supports it
|
||||
CTL_DISPLAY_SETTING_AUDIO_DISABLED = 1, ///< Forcefully disable display audio end point enumeration to OS
|
||||
CTL_DISPLAY_SETTING_AUDIO_MAX
|
||||
|
||||
} ctl_display_setting_audio_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get/Set end display settings
|
||||
typedef struct _ctl_display_settings_t
|
||||
{
|
||||
uint32_t Size; ///< [in] size of this structure
|
||||
uint8_t Version; ///< [in] version of this structure
|
||||
bool Set; ///< [in] Flag to indicate Set or Get operation. Default option for all
|
||||
///< features are reserved for Set=true calls, which will reset the setting
|
||||
///< to driver defaults.
|
||||
ctl_display_setting_flags_t SupportedFlags; ///< [out] Display setting flags supported by the display.
|
||||
ctl_display_setting_flags_t ControllableFlags; ///< [out] Display setting flags which can be controlled by the caller.
|
||||
///< Features which doesn't have this flag set cannot be changed by caller.
|
||||
ctl_display_setting_flags_t ValidFlags; ///< [in,out] Display setting flags which caller can use to indicate the
|
||||
///< features it's interested in. This cannot have a bit set which is not
|
||||
///< supported by SupportedFlags and ControllableFlags.
|
||||
ctl_display_setting_low_latency_t LowLatency; ///< [in,out] Low latency state of panel. For HDR10+ Gaming this need to be
|
||||
///< in ENABLED state.
|
||||
ctl_display_setting_sourcetm_t SourceTM; ///< [in,out] Source tone mapping state known to panel. For HDR10+ Gaming
|
||||
///< this need to be in ENABLED state.
|
||||
ctl_display_setting_content_type_t ContentType; ///< [in,out] Source content type known to panel.
|
||||
ctl_display_setting_quantization_range_t QuantizationRange; ///< [in,out] Quantization range
|
||||
ctl_display_setting_picture_ar_flags_t SupportedPictureAR; ///< [out] Supported Picture aspect ratios
|
||||
ctl_display_setting_picture_ar_flag_t PictureAR;///< [in,out] Picture aspect ratio
|
||||
ctl_display_setting_audio_t AudioSettings; ///< [in,out] Audio settings
|
||||
uint32_t Reserved[25]; ///< [out] Reserved fields for future enumerations
|
||||
|
||||
} ctl_display_settings_t;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get/Set Display settings
|
||||
///
|
||||
/// @details
|
||||
/// - To get/set end display settings like low latency, HDR10+ signaling
|
||||
/// etc. which are controlled via info-frames/secondary data packets
|
||||
///
|
||||
/// @returns
|
||||
/// - CTL_RESULT_SUCCESS
|
||||
/// - CTL_RESULT_ERROR_UNINITIALIZED
|
||||
/// - CTL_RESULT_ERROR_DEVICE_LOST
|
||||
/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE
|
||||
/// + `nullptr == hDisplayOutput`
|
||||
/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER
|
||||
/// + `nullptr == pDisplaySettings`
|
||||
/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version"
|
||||
/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle"
|
||||
/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface"
|
||||
/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle"
|
||||
/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure"
|
||||
/// - ::CTL_RESULT_ERROR_INVALID_NULL_HANDLE - "Invalid or Null handle passed"
|
||||
/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer"
|
||||
/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type"
|
||||
/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid combination of parameters"
|
||||
CTL_APIEXPORT ctl_result_t CTL_APICALL
|
||||
ctlGetSetDisplaySettings(
|
||||
ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output
|
||||
ctl_display_settings_t* pDisplaySettings ///< [in,out] End display capabilities
|
||||
);
|
||||
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
#pragma endregion // display
|
||||
@@ -7229,6 +7470,22 @@ typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetDynamicContrastEnhancement_t)(
|
||||
);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Function-pointer for ctlGetSetWireFormat
|
||||
typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetWireFormat_t)(
|
||||
ctl_display_output_handle_t,
|
||||
ctl_get_set_wire_format_config_t*
|
||||
);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Function-pointer for ctlGetSetDisplaySettings
|
||||
typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetDisplaySettings_t)(
|
||||
ctl_display_output_handle_t,
|
||||
ctl_display_settings_t*
|
||||
);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Function-pointer for ctlEnumEngineGroups
|
||||
typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumEngineGroups_t)(
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/intel/drivers.gpu.control-library",
|
||||
"license": "./LICENSE",
|
||||
"version": "e1776b7be2ceead1296204371447b27860d25a66",
|
||||
"version": "v184",
|
||||
"author": "Intel Corporation"
|
||||
}
|
||||
|
||||
Vendored
+740
-25
@@ -153,6 +153,27 @@ typedef struct nvmlDevice_st* nvmlDevice_t;
|
||||
*/
|
||||
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE 16
|
||||
|
||||
/**
|
||||
* PCI information about a GPU device.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
unsigned int domain; //!< The PCI domain on which the device's bus resides, 0 to 0xffffffff
|
||||
unsigned int bus; //!< The bus on which the device resides, 0 to 0xff
|
||||
unsigned int device; //!< The device's id on the bus, 0 to 31
|
||||
|
||||
unsigned int pciDeviceId; //!< The combined 16-bit device id and 16-bit vendor id
|
||||
unsigned int pciSubSystemId; //!< The 32-bit Sub System Device ID
|
||||
|
||||
unsigned int baseClass; //!< The 8-bit PCI base class code
|
||||
unsigned int subClass; //!< The 8-bit PCI sub class code
|
||||
|
||||
char busId[NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE]; //!< The tuple domain:bus:device.function PCI identifier (& NULL terminator)
|
||||
} nvmlPciInfoExt_v1_t;
|
||||
typedef nvmlPciInfoExt_v1_t nvmlPciInfoExt_t;
|
||||
#define nvmlPciInfoExt_v1 NVML_STRUCT_VERSION(PciInfoExt, 1)
|
||||
|
||||
/**
|
||||
* PCI information about a GPU device.
|
||||
*/
|
||||
@@ -482,11 +503,16 @@ typedef enum nvmlGpuP2PStatus_enum
|
||||
typedef enum nvmlGpuP2PCapsIndex_enum
|
||||
{
|
||||
NVML_P2P_CAPS_INDEX_READ = 0,
|
||||
NVML_P2P_CAPS_INDEX_WRITE,
|
||||
NVML_P2P_CAPS_INDEX_NVLINK,
|
||||
NVML_P2P_CAPS_INDEX_ATOMICS,
|
||||
NVML_P2P_CAPS_INDEX_PROP,
|
||||
NVML_P2P_CAPS_INDEX_UNKNOWN
|
||||
NVML_P2P_CAPS_INDEX_WRITE = 1,
|
||||
NVML_P2P_CAPS_INDEX_NVLINK = 2,
|
||||
NVML_P2P_CAPS_INDEX_ATOMICS = 3,
|
||||
NVML_P2P_CAPS_INDEX_PCI = 4,
|
||||
/*
|
||||
* DO NOT USE! NVML_P2P_CAPS_INDEX_PROP is deprecated.
|
||||
* Use NVML_P2P_CAPS_INDEX_PCI instead.
|
||||
*/
|
||||
NVML_P2P_CAPS_INDEX_PROP = NVML_P2P_CAPS_INDEX_PCI,
|
||||
NVML_P2P_CAPS_INDEX_UNKNOWN = 5,
|
||||
}nvmlGpuP2PCapsIndex_t;
|
||||
|
||||
/**
|
||||
@@ -526,6 +552,8 @@ typedef enum nvmlSamplingType_enum
|
||||
NVML_PROCESSOR_CLK_SAMPLES = 5, //!< To represent processor clock samples
|
||||
NVML_MEMORY_CLK_SAMPLES = 6, //!< To represent memory clock samples
|
||||
NVML_MODULE_POWER_SAMPLES = 7, //!< To represent module power samples for total module starting Grace Hopper
|
||||
NVML_JPG_UTILIZATION_SAMPLES = 8, //!< To represent percent of time during which NVJPG remains busy
|
||||
NVML_OFA_UTILIZATION_SAMPLES = 9, //!< To represent percent of time during which NVOFA remains busy
|
||||
|
||||
// Keep this last
|
||||
NVML_SAMPLINGTYPE_COUNT
|
||||
@@ -1005,6 +1033,7 @@ typedef enum nvmlReturn_enum
|
||||
NVML_ERROR_DEPRECATED = 26, //!< The requested functionality has been deprecated
|
||||
NVML_ERROR_NOT_READY = 27, //!< The system is not ready for the request
|
||||
NVML_ERROR_GPU_NOT_FOUND = 28, //!< No GPUs were found
|
||||
NVML_ERROR_INVALID_STATE = 29, //!< Resource not in correct state to perform requested operation
|
||||
NVML_ERROR_UNKNOWN = 999 //!< An internal driver error occurred
|
||||
} nvmlReturn_t;
|
||||
|
||||
@@ -1150,11 +1179,14 @@ typedef enum nvmlVgpuDriverCapability_enum
|
||||
*/
|
||||
typedef enum nvmlDeviceVgpuCapability_enum
|
||||
{
|
||||
NVML_DEVICE_VGPU_CAP_FRACTIONAL_MULTI_VGPU = 0, //!< Fractional vGPU profiles on this GPU can be used in multi-vGPU configurations
|
||||
NVML_DEVICE_VGPU_CAP_HETEROGENEOUS_TIMESLICE_PROFILES = 1, //!< Supports concurrent execution of timesliced vGPU profiles of differing types
|
||||
NVML_DEVICE_VGPU_CAP_HETEROGENEOUS_TIMESLICE_SIZES = 2, //!< Supports concurrent execution of timesliced vGPU profiles of differing framebuffer sizes
|
||||
NVML_DEVICE_VGPU_CAP_READ_DEVICE_BUFFER_BW = 3, //!< GPU device's read_device_buffer expected bandwidth capacity in megabytes per second
|
||||
NVML_DEVICE_VGPU_CAP_WRITE_DEVICE_BUFFER_BW = 4, //!< GPU device's write_device_buffer expected bandwidth capacity in megabytes per second
|
||||
NVML_DEVICE_VGPU_CAP_FRACTIONAL_MULTI_VGPU = 0, //!< Query if the fractional vGPU profiles on this GPU can be used in multi-vGPU configurations
|
||||
NVML_DEVICE_VGPU_CAP_HETEROGENEOUS_TIMESLICE_PROFILES = 1, //!< Query if the GPU support concurrent execution of timesliced vGPU profiles of differing types
|
||||
NVML_DEVICE_VGPU_CAP_HETEROGENEOUS_TIMESLICE_SIZES = 2, //!< Query if the GPU support concurrent execution of timesliced vGPU profiles of differing framebuffer sizes
|
||||
NVML_DEVICE_VGPU_CAP_READ_DEVICE_BUFFER_BW = 3, //!< Query the GPU's read_device_buffer expected bandwidth capacity in megabytes per second
|
||||
NVML_DEVICE_VGPU_CAP_WRITE_DEVICE_BUFFER_BW = 4, //!< Query the GPU's write_device_buffer expected bandwidth capacity in megabytes per second
|
||||
NVML_DEVICE_VGPU_CAP_DEVICE_STREAMING = 5, //!< Query if vGPU profiles on the GPU supports migration data streaming
|
||||
NVML_DEVICE_VGPU_CAP_MINI_QUARTER_GPU = 6, //!< Set/Get support for mini-quarter vGPU profiles
|
||||
NVML_DEVICE_VGPU_CAP_COMPUTE_MEDIA_ENGINE_GPU = 7, //!< Set/Get support for compute media engine vGPU profiles
|
||||
// Keep this last
|
||||
NVML_DEVICE_VGPU_CAP_COUNT
|
||||
} nvmlDeviceVgpuCapability_t;
|
||||
@@ -1181,6 +1213,8 @@ typedef enum nvmlDeviceVgpuCapability_enum
|
||||
|
||||
#define INVALID_GPU_INSTANCE_ID 0xFFFFFFFF
|
||||
|
||||
#define NVML_INVALID_VGPU_PLACEMENT_ID 0xFFFF
|
||||
|
||||
/*!
|
||||
* Macros for vGPU instance's virtualization capabilities bitfield.
|
||||
*/
|
||||
@@ -1207,6 +1241,41 @@ typedef unsigned int nvmlVgpuTypeId_t;
|
||||
|
||||
typedef unsigned int nvmlVgpuInstance_t;
|
||||
|
||||
/**
|
||||
* Structure to store the vGPU heterogeneous mode of device -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
unsigned int mode; //!< The vGPU heterogeneous mode
|
||||
} nvmlVgpuHeterogeneousMode_v1_t;
|
||||
typedef nvmlVgpuHeterogeneousMode_v1_t nvmlVgpuHeterogeneousMode_t;
|
||||
#define nvmlVgpuHeterogeneousMode_v1 NVML_STRUCT_VERSION(VgpuHeterogeneousMode, 1)
|
||||
|
||||
/**
|
||||
* Structure to store the placement ID of vGPU instance -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
unsigned int placementId; //!< Placement ID of the active vGPU instance
|
||||
} nvmlVgpuPlacementId_v1_t;
|
||||
typedef nvmlVgpuPlacementId_v1_t nvmlVgpuPlacementId_t;
|
||||
#define nvmlVgpuPlacementId_v1 NVML_STRUCT_VERSION(VgpuPlacementId, 1)
|
||||
|
||||
/**
|
||||
* Structure to store the list of vGPU placements -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
unsigned int placementSize; //!< The number of slots occupied by the vGPU type
|
||||
unsigned int count; //!< Count of placement IDs fetched
|
||||
unsigned int *placementIds; //!< Placement IDs for the vGPU type
|
||||
} nvmlVgpuPlacementList_v1_t;
|
||||
typedef nvmlVgpuPlacementList_v1_t nvmlVgpuPlacementList_t;
|
||||
#define nvmlVgpuPlacementList_v1 NVML_STRUCT_VERSION(VgpuPlacementList, 1)
|
||||
|
||||
/**
|
||||
* Structure to store Utilization Value and vgpuInstance
|
||||
*/
|
||||
@@ -1220,6 +1289,35 @@ typedef struct nvmlVgpuInstanceUtilizationSample_st
|
||||
nvmlValue_t decUtil; //!< Decoder Util Value
|
||||
} nvmlVgpuInstanceUtilizationSample_t;
|
||||
|
||||
/**
|
||||
* Structure to store Utilization Value and vgpuInstance Info -- Version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned long long timeStamp; //!< CPU Timestamp in microseconds
|
||||
nvmlVgpuInstance_t vgpuInstance; //!< vGPU Instance
|
||||
nvmlValue_t smUtil; //!< SM (3D/Compute) Util Value
|
||||
nvmlValue_t memUtil; //!< Frame Buffer Memory Util Value
|
||||
nvmlValue_t encUtil; //!< Encoder Util Value
|
||||
nvmlValue_t decUtil; //!< Decoder Util Value
|
||||
nvmlValue_t jpgUtil; //!< Jpeg Util Value
|
||||
nvmlValue_t ofaUtil; //!< Ofa Util Value
|
||||
} nvmlVgpuInstanceUtilizationInfo_v1_t;
|
||||
|
||||
/**
|
||||
* Structure to store recent utilization for vGPU instances running on a device -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
nvmlValueType_t sampleValType; //!< Hold the type of returned sample values
|
||||
unsigned int vgpuInstanceCount; //!< Hold the number of vGPU instances
|
||||
unsigned long long lastSeenTimeStamp; //!< Return only samples with timestamp greater than lastSeenTimeStamp
|
||||
nvmlVgpuInstanceUtilizationInfo_v1_t *vgpuUtilArray; //!< The array (allocated by caller) in which vGPU utilization are returned
|
||||
} nvmlVgpuInstancesUtilizationInfo_v1_t;
|
||||
typedef nvmlVgpuInstancesUtilizationInfo_v1_t nvmlVgpuInstancesUtilizationInfo_t;
|
||||
#define nvmlVgpuInstancesUtilizationInfo_v1 NVML_STRUCT_VERSION(VgpuInstancesUtilizationInfo, 1)
|
||||
|
||||
/**
|
||||
* Structure to store Utilization Value, vgpuInstance and subprocess information
|
||||
*/
|
||||
@@ -1235,6 +1333,36 @@ typedef struct nvmlVgpuProcessUtilizationSample_st
|
||||
unsigned int decUtil; //!< Decoder Util Value
|
||||
} nvmlVgpuProcessUtilizationSample_t;
|
||||
|
||||
/**
|
||||
* Structure to store Utilization Value, vgpuInstance and subprocess information for process running on vGPU instance -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char processName[NVML_VGPU_NAME_BUFFER_SIZE]; //!< Name of process running within the vGPU VM
|
||||
unsigned long long timeStamp; //!< CPU Timestamp in microseconds
|
||||
nvmlVgpuInstance_t vgpuInstance; //!< vGPU Instance
|
||||
unsigned int pid; //!< PID of process running within the vGPU VM
|
||||
unsigned int smUtil; //!< SM (3D/Compute) Util Value
|
||||
unsigned int memUtil; //!< Frame Buffer Memory Util Value
|
||||
unsigned int encUtil; //!< Encoder Util Value
|
||||
unsigned int decUtil; //!< Decoder Util Value
|
||||
unsigned int jpgUtil; //!< Jpeg Util Value
|
||||
unsigned int ofaUtil; //!< Ofa Util Value
|
||||
} nvmlVgpuProcessUtilizationInfo_v1_t;
|
||||
|
||||
/**
|
||||
* Structure to store recent utilization, vgpuInstance and subprocess information for processes running on vGPU instances active on a device -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
unsigned int vgpuProcessCount; //!< Hold the number of processes running on vGPU instances
|
||||
unsigned long long lastSeenTimeStamp; //!< Return only samples with timestamp greater than lastSeenTimeStamp
|
||||
nvmlVgpuProcessUtilizationInfo_v1_t *vgpuProcUtilArray; //!< The array (allocated by caller) in which utilization of processes running on vGPU instances are returned
|
||||
} nvmlVgpuProcessesUtilizationInfo_v1_t;
|
||||
typedef nvmlVgpuProcessesUtilizationInfo_v1_t nvmlVgpuProcessesUtilizationInfo_t;
|
||||
#define nvmlVgpuProcessesUtilizationInfo_v1 NVML_STRUCT_VERSION(VgpuProcessesUtilizationInfo, 1)
|
||||
|
||||
/**
|
||||
* vGPU scheduler policies
|
||||
*/
|
||||
@@ -1392,6 +1520,34 @@ typedef struct nvmlProcessUtilizationSample_st
|
||||
unsigned int decUtil; //!< Decoder Util Value
|
||||
} nvmlProcessUtilizationSample_t;
|
||||
|
||||
/**
|
||||
* Structure to store utilization value and process Id -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned long long timeStamp; //!< CPU Timestamp in microseconds
|
||||
unsigned int pid; //!< PID of process
|
||||
unsigned int smUtil; //!< SM (3D/Compute) Util Value
|
||||
unsigned int memUtil; //!< Frame Buffer Memory Util Value
|
||||
unsigned int encUtil; //!< Encoder Util Value
|
||||
unsigned int decUtil; //!< Decoder Util Value
|
||||
unsigned int jpgUtil; //!< Jpeg Util Value
|
||||
unsigned int ofaUtil; //!< Ofa Util Value
|
||||
} nvmlProcessUtilizationInfo_v1_t;
|
||||
|
||||
/**
|
||||
* Structure to store utilization and process ID for each running process -- version 1
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< The version number of this struct
|
||||
unsigned int processSamplesCount; //!< Caller-supplied array size, and returns number of processes running
|
||||
unsigned long long lastSeenTimeStamp; //!< Return only samples with timestamp greater than lastSeenTimeStamp
|
||||
nvmlProcessUtilizationInfo_v1_t *procUtilArray; //!< The array (allocated by caller) of the utilization of GPU SM, framebuffer, video encoder, video decoder, JPEG, and OFA
|
||||
} nvmlProcessesUtilizationInfo_v1_t;
|
||||
typedef nvmlProcessesUtilizationInfo_v1_t nvmlProcessesUtilizationInfo_t;
|
||||
#define nvmlProcessesUtilizationInfo_v1 NVML_STRUCT_VERSION(ProcessesUtilizationInfo, 1)
|
||||
|
||||
/**
|
||||
* Structure to store license expiry date and time values
|
||||
*/
|
||||
@@ -1429,6 +1585,29 @@ typedef struct nvmlGridLicensableFeatures_st
|
||||
nvmlGridLicensableFeature_t gridLicensableFeatures[NVML_GRID_LICENSE_FEATURE_MAX_COUNT]; //!< Array of vGPU software licensable features.
|
||||
} nvmlGridLicensableFeatures_t;
|
||||
|
||||
/**
|
||||
* Structure to store SRAM uncorrectable error counters
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int version; //!< the API version number
|
||||
unsigned long long aggregateUncParity; //!< aggregate uncorrectable parity error count
|
||||
unsigned long long aggregateUncSecDed; //!< aggregate uncorrectable SEC-DED error count
|
||||
unsigned long long aggregateCor; //!< aggregate correctable error count
|
||||
unsigned long long volatileUncParity; //!< volatile uncorrectable parity error count
|
||||
unsigned long long volatileUncSecDed; //!< volatile uncorrectable SEC-DED error count
|
||||
unsigned long long volatileCor; //!< volatile correctable error count
|
||||
unsigned long long aggregateUncBucketL2; //!< aggregate uncorrectable error count for L2 cache bucket
|
||||
unsigned long long aggregateUncBucketSm; //!< aggregate uncorrectable error count for SM bucket
|
||||
unsigned long long aggregateUncBucketPcie; //!< aggregate uncorrectable error count for PCIE bucket
|
||||
unsigned long long aggregateUncBucketMcu; //!< aggregate uncorrectable error count for Microcontroller bucket
|
||||
unsigned long long aggregateUncBucketOther; //!< aggregate uncorrectable error count for Other bucket
|
||||
unsigned int bThresholdExceeded; //!< if the error threshold of field diag is exceeded
|
||||
} nvmlEccSramErrorStatus_v1_t;
|
||||
|
||||
typedef nvmlEccSramErrorStatus_v1_t nvmlEccSramErrorStatus_t;
|
||||
#define nvmlEccSramErrorStatus_v1 NVML_STRUCT_VERSION(EccSramErrorStatus, 1)
|
||||
|
||||
/**
|
||||
* GSP firmware
|
||||
*/
|
||||
@@ -1837,7 +2016,9 @@ typedef struct nvmlGpuDynamicPstatesInfo_st
|
||||
#define NVML_FI_DEV_TEMPERATURE_MEM_MAX_TLIMIT 195 //!< T.Limit temperature after which GPU may begin SW slowdown due to memory temperature
|
||||
#define NVML_FI_DEV_TEMPERATURE_GPU_MAX_TLIMIT 196 //!< T.Limit temperature after which GPU may be throttled below base clock
|
||||
|
||||
#define NVML_FI_MAX 197 //!< One greater than the largest field ID defined above
|
||||
#define NVML_FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE 199 //!< MIG mode independent, MIG query capable device. 1=yes. 0=no.
|
||||
|
||||
#define NVML_FI_MAX 200 //!< One greater than the largest field ID defined above
|
||||
|
||||
/**
|
||||
* Information for a Field Value Sample
|
||||
@@ -2248,9 +2429,10 @@ typedef struct nvmlAccountingStats_st {
|
||||
*/
|
||||
typedef enum nvmlEncoderQueryType_enum
|
||||
{
|
||||
NVML_ENCODER_QUERY_H264 = 0, //!< H264 encoder
|
||||
NVML_ENCODER_QUERY_HEVC = 1, //!< HEVC encoder
|
||||
NVML_ENCODER_QUERY_AV1 = 2 //!< AV1 encoder
|
||||
NVML_ENCODER_QUERY_H264 = 0x00, //!< H264 encoder
|
||||
NVML_ENCODER_QUERY_HEVC = 0x01, //!< HEVC encoder
|
||||
NVML_ENCODER_QUERY_AV1 = 0x02, //!< AV1 encoder
|
||||
NVML_ENCODER_QUERY_UNKNOWN = 0xFF //!< Unknown encoder
|
||||
}nvmlEncoderType_t;
|
||||
|
||||
/**
|
||||
@@ -2399,6 +2581,26 @@ typedef struct nvmlConfComputeSystemState_st {
|
||||
unsigned int devToolsMode;
|
||||
} nvmlConfComputeSystemState_t;
|
||||
|
||||
/**
|
||||
* Confidential Compute Multigpu mode values
|
||||
*/
|
||||
#define NVML_CC_SYSTEM_MULTIGPU_NONE 0
|
||||
#define NVML_CC_SYSTEM_MULTIGPU_PROTECTED_PCIE 1
|
||||
|
||||
/**
|
||||
* Confidential Compute System settings
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
unsigned int environment;
|
||||
unsigned int ccFeature;
|
||||
unsigned int devToolsMode;
|
||||
unsigned int multiGpuMode;
|
||||
} nvmlSystemConfComputeSettings_v1_t;
|
||||
|
||||
typedef nvmlSystemConfComputeSettings_v1_t nvmlSystemConfComputeSettings_t;
|
||||
#define nvmlSystemConfComputeSettings_v1 NVML_STRUCT_VERSION(SystemConfComputeSettings, 1)
|
||||
|
||||
/**
|
||||
* Protected memory size
|
||||
*/
|
||||
@@ -2436,6 +2638,8 @@ typedef struct nvmlConfComputeGpuCertificate_st {
|
||||
#define NVML_CC_GPU_CEC_ATTESTATION_REPORT_SIZE 0x1000
|
||||
#define NVML_CC_CEC_ATTESTATION_REPORT_NOT_PRESENT 0
|
||||
#define NVML_CC_CEC_ATTESTATION_REPORT_PRESENT 1
|
||||
#define NVML_CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MIN 50
|
||||
#define NVML_CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MAX 75
|
||||
|
||||
typedef struct nvmlConfComputeGpuAttestationReport_st {
|
||||
unsigned int isCecAttestationReportPresent;
|
||||
@@ -2446,6 +2650,24 @@ typedef struct nvmlConfComputeGpuAttestationReport_st {
|
||||
unsigned char cecAttestationReport[NVML_CC_GPU_CEC_ATTESTATION_REPORT_SIZE];
|
||||
} nvmlConfComputeGpuAttestationReport_t;
|
||||
|
||||
typedef struct nvmlConfComputeSetKeyRotationThresholdInfo_st {
|
||||
unsigned int version;
|
||||
unsigned long long maxAttackerAdvantage;
|
||||
} nvmlConfComputeSetKeyRotationThresholdInfo_v1_t;
|
||||
|
||||
typedef nvmlConfComputeSetKeyRotationThresholdInfo_v1_t nvmlConfComputeSetKeyRotationThresholdInfo_t;
|
||||
#define nvmlConfComputeSetKeyRotationThresholdInfo_v1 \
|
||||
NVML_STRUCT_VERSION(ConfComputeSetKeyRotationThresholdInfo, 1)
|
||||
|
||||
typedef struct nvmlConfComputeGetKeyRotationThresholdInfo_st {
|
||||
unsigned int version;
|
||||
unsigned long long attackerAdvantage;
|
||||
} nvmlConfComputeGetKeyRotationThresholdInfo_v1_t;
|
||||
|
||||
typedef nvmlConfComputeGetKeyRotationThresholdInfo_v1_t nvmlConfComputeGetKeyRotationThresholdInfo_t;
|
||||
#define nvmlConfComputeGetKeyRotationThresholdInfo_v1 \
|
||||
NVML_STRUCT_VERSION(ConfComputeGetKeyRotationThresholdInfo, 1)
|
||||
|
||||
/** @} */
|
||||
|
||||
#define NVML_GPU_FABRIC_UUID_LEN 16
|
||||
@@ -2464,6 +2686,55 @@ typedef struct {
|
||||
nvmlGpuFabricState_t state; //!< Current state of GPU registration process
|
||||
} nvmlGpuFabricInfo_t;
|
||||
|
||||
#define NVML_GPU_FABRIC_HEALTH_MASK_DEGRADED_BW_NOT_SUPPORTED 0
|
||||
#define NVML_GPU_FABRIC_HEALTH_MASK_DEGRADED_BW_TRUE 1
|
||||
#define NVML_GPU_FABRIC_HEALTH_MASK_DEGRADED_BW_FALSE 2
|
||||
|
||||
#define NVML_GPU_FABRIC_HEALTH_MASK_SHIFT_DEGRADED_BW 0
|
||||
#define NVML_GPU_FABRIC_HEALTH_MASK_WIDTH_DEGRADED_BW 0x11
|
||||
|
||||
/**
|
||||
* GPU Fabric Health Status Mask for various fields can be obtained
|
||||
* using the below macro.
|
||||
* Ex - NVML_GPU_FABRIC_HEALTH_GET(var, _DEGRADED_BW)
|
||||
*/
|
||||
#define NVML_GPU_FABRIC_HEALTH_GET(var, type) \
|
||||
(((var) >> NVML_GPU_FABRIC_HEALTH_MASK_SHIFT##type) & \
|
||||
(NVML_GPU_FABRIC_HEALTH_MASK_WIDTH##type))
|
||||
|
||||
/**
|
||||
* GPU Fabric Health Status Mask for various fields can be tested
|
||||
* using the below macro.
|
||||
* Ex - NVML_GPU_FABRIC_HEALTH_TEST(var, _DEGRADED_BW, _TRUE)
|
||||
*/
|
||||
#define NVML_GPU_FABRIC_HEALTH_TEST(var, type, val) \
|
||||
(NVML_GPU_FABRIC_HEALTH_GET(var, type) == \
|
||||
NVML_GPU_FABRIC_HEALTH_MASK##type##val)
|
||||
|
||||
/**
|
||||
* GPU Fabric information (v2).
|
||||
*
|
||||
* Version 2 adds the \ref nvmlGpuFabricInfo_v2_t.version field
|
||||
* to the start of the structure, and the \ref nvmlGpuFabricInfo_v2_t.healthMask
|
||||
* field to the end. This structure is not backwards-compatible with
|
||||
* \ref nvmlGpuFabricInfo_t.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int version; //!< Structure version identifier (set to \ref nvmlGpuFabricInfo_v2)
|
||||
unsigned char clusterUuid[NVML_GPU_FABRIC_UUID_LEN]; //!< Uuid of the cluster to which this GPU belongs
|
||||
nvmlReturn_t status; //!< Error status, if any. Must be checked only if state returns "complete".
|
||||
unsigned int cliqueId; //!< ID of the fabric clique to which this GPU belongs
|
||||
nvmlGpuFabricState_t state; //!< Current state of GPU registration process
|
||||
unsigned int healthMask; //!< GPU Fabric health Status Mask
|
||||
} nvmlGpuFabricInfo_v2_t;
|
||||
|
||||
typedef nvmlGpuFabricInfo_v2_t nvmlGpuFabricInfoV_t;
|
||||
|
||||
/**
|
||||
* Version identifier value for \ref nvmlGpuFabricInfo_v2_t.version.
|
||||
*/
|
||||
#define nvmlGpuFabricInfo_v2 NVML_STRUCT_VERSION(GpuFabricInfo, 2)
|
||||
|
||||
/**
|
||||
* Device Scope - This is useful to retrieve the telemetry at GPU and module (e.g. GPU + CPU) level
|
||||
*/
|
||||
@@ -3414,6 +3685,19 @@ nvmlReturn_t DECLDIR nvmlDeviceSetCpuAffinity(nvmlDevice_t device);
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceClearCpuAffinity(nvmlDevice_t device);
|
||||
|
||||
/**
|
||||
* Get the NUMA node of the given GPU device.
|
||||
* This only applies to platforms where the GPUs are NUMA nodes.
|
||||
*
|
||||
* @param[in] device The device handle
|
||||
* @param[out] node NUMA node ID of the device
|
||||
*
|
||||
* @returns
|
||||
* - \ref NVML_SUCCESS if the NUMA node is retrieved successfully
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if request is not supported on the current platform
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device \a node is invalid
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetNumaNodeId(nvmlDevice_t device, unsigned int *node);
|
||||
/**
|
||||
* Retrieve the common ancestor for two devices
|
||||
* For all products.
|
||||
@@ -3726,6 +4010,25 @@ nvmlReturn_t DECLDIR nvmlDeviceGetDisplayActive(nvmlDevice_t device, nvmlEnableS
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetPersistenceMode(nvmlDevice_t device, nvmlEnableState_t *mode);
|
||||
|
||||
/**
|
||||
* Retrieves PCI attributes of this device.
|
||||
*
|
||||
* For all products.
|
||||
*
|
||||
* See \ref nvmlPciInfoExt_t for details on the available PCI info.
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param pci Reference in which to return the PCI info
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if \a pci has been populated
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pci is NULL
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetPciInfoExt(nvmlDevice_t device, nvmlPciInfoExt_t *pci);
|
||||
|
||||
/**
|
||||
* Retrieves the PCI attributes of this device.
|
||||
*
|
||||
@@ -5423,7 +5726,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetMPSComputeRunningProcesses_v3(nvmlDevice_t dev
|
||||
*
|
||||
* To determine the size of the @ref plist->procArray array to allocate, call the function with
|
||||
* @ref plist->numProcArrayEntries set to zero and @ref plist->procArray set to NULL. The return
|
||||
* code will be either NVML_ERROR_INSUFFICIENT_SIZE (if there are valid processes of type
|
||||
* code will be either NVML_ERROR_INSUFFICIENT_SIZE (if there are valid processes of type
|
||||
* @ref plist->mode to report on, in which case the @ref plist->numProcArrayEntries field will
|
||||
* indicate the required number of entries in the array) or NVML_SUCCESS (if no processes of type
|
||||
* @ref plist->mode exist).
|
||||
@@ -5708,7 +6011,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetPcieSpeed(nvmlDevice_t device, unsigned int *p
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param adaptiveClockStatus The current adaptive clocking status, either
|
||||
* @ref NVML_ADAPTIVE_CLOCKING_INFO_STATUS_DISABLED
|
||||
* @ref NVML_ADAPTIVE_CLOCKING_INFO_STATUS_DISABLED
|
||||
* or @ref NVML_ADAPTIVE_CLOCKING_INFO_STATUS_ENABLED
|
||||
*
|
||||
* @return
|
||||
@@ -5735,7 +6038,10 @@ nvmlReturn_t DECLDIR nvmlDeviceGetAdaptiveClockInfoStatus(nvmlDevice_t device, u
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetBusType(nvmlDevice_t device, nvmlBusType_t *type);
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Deprecated: Will be deprecated in a future release. Use \ref nvmlDeviceGetGpuFabricInfoV instead
|
||||
*
|
||||
* Get fabric information associated with the device.
|
||||
*
|
||||
* %HOPPER_OR_NEWER%
|
||||
@@ -5746,6 +6052,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetBusType(nvmlDevice_t device, nvmlBusType_t *ty
|
||||
* This API reports the current state of the GPU in the NVLink fabric
|
||||
* along with other useful information.
|
||||
*
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param gpuFabricInfo Information about GPU fabric state
|
||||
*
|
||||
@@ -5755,6 +6062,30 @@ nvmlReturn_t DECLDIR nvmlDeviceGetBusType(nvmlDevice_t device, nvmlBusType_t *ty
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetGpuFabricInfo(nvmlDevice_t device, nvmlGpuFabricInfo_t *gpuFabricInfo);
|
||||
|
||||
/**
|
||||
* Versioned wrapper around \ref nvmlDeviceGetGpuFabricInfo that accepts a versioned
|
||||
* \ref nvmlGpuFabricInfo_v2_t or later output structure.
|
||||
*
|
||||
* @note The caller must set the \ref nvmlGpuFabricInfoV_t.version field to the
|
||||
* appropriate version prior to calling this function. For example:
|
||||
* \code
|
||||
* nvmlGpuFabricInfoV_t fabricInfo =
|
||||
* { .version = nvmlGpuFabricInfo_v2 };
|
||||
* nvmlReturn_t result = nvmlDeviceGetGpuFabricInfoV(device,&fabricInfo);
|
||||
* \endcode
|
||||
*
|
||||
* %HOPPER_OR_NEWER%
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param gpuFabricInfo Information about GPU fabric state
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't support gpu fabric
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetGpuFabricInfoV(nvmlDevice_t device,
|
||||
nvmlGpuFabricInfoV_t *gpuFabricInfo);
|
||||
|
||||
/**
|
||||
* Get Conf Computing System capabilities.
|
||||
*
|
||||
@@ -5877,6 +6208,42 @@ nvmlReturn_t DECLDIR nvmlDeviceGetConfComputeGpuCertificate(nvmlDevice_t device,
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetConfComputeGpuAttestationReport(nvmlDevice_t device,
|
||||
nvmlConfComputeGpuAttestationReport_t *gpuAtstReport);
|
||||
/**
|
||||
* Get Conf Computing key rotation threshold detail.
|
||||
*
|
||||
* %HOPPER_OR_NEWER%
|
||||
* Supported on Linux, Windows TCC.
|
||||
*
|
||||
* @param pKeyRotationThrInfo Reference in which to return the key rotation threshold data
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if \a gpu key rotation threshold info has been populated
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a memory is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlSystemGetConfComputeKeyRotationThresholdInfo(
|
||||
nvmlConfComputeGetKeyRotationThresholdInfo_t *pKeyRotationThrInfo);
|
||||
|
||||
/**
|
||||
* Get Conf Computing System Settings.
|
||||
*
|
||||
* %HOPPER_OR_NEWER%
|
||||
* Supported on Linux, Windows TCC.
|
||||
*
|
||||
* @param settings System CC settings
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if the query is success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a counters is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_ARGUMENT_VERSION_MISMATCH if the provided version is invalid/unsupported
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlSystemGetConfComputeSettings(nvmlSystemConfComputeSettings_t *settings);
|
||||
|
||||
/**
|
||||
* Retrieve GSP firmware version.
|
||||
@@ -6241,6 +6608,52 @@ nvmlReturn_t DECLDIR nvmlDeviceGetClkMonStatus(nvmlDevice_t device, nvmlClkMonSt
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetProcessUtilization(nvmlDevice_t device, nvmlProcessUtilizationSample_t *utilization,
|
||||
unsigned int *processSamplesCount, unsigned long long lastSeenTimeStamp);
|
||||
|
||||
/**
|
||||
* Retrieves the recent utilization and process ID for all running processes
|
||||
*
|
||||
* For Maxwell &tm; or newer fully supported devices.
|
||||
*
|
||||
* Reads recent utilization of GPU SM (3D/Compute), framebuffer, video encoder, and video decoder, jpeg decoder, OFA (Optical Flow Accelerator)
|
||||
* for all running processes. Utilization values are returned as an array of utilization sample structures in the caller-supplied buffer pointed at
|
||||
* by \a procesesUtilInfo->procUtilArray. One utilization sample structure is returned per process running, that had some non-zero utilization
|
||||
* during the last sample period. It includes the CPU timestamp at which the samples were recorded. Individual utilization values
|
||||
* are returned as "unsigned int" values.
|
||||
*
|
||||
* The caller should allocate a buffer of size processSamplesCount * sizeof(nvmlProcessUtilizationInfo_t). If the buffer is too small, the API will
|
||||
* return \a NVML_ERROR_INSUFFICIENT_SIZE, with the recommended minimal buffer size at \a procesesUtilInfo->processSamplesCount. The caller should
|
||||
* invoke the function again with the allocated buffer passed in \a procesesUtilInfo->procUtilArray, and \a procesesUtilInfo->processSamplesCount
|
||||
* set to the number no less than the recommended value by the previous API return.
|
||||
*
|
||||
* On successful return, the function updates \a procesesUtilInfo->processSamplesCount with the number of process utilization info structures
|
||||
* that were actually written. This may differ from a previously read value as instances are created or destroyed.
|
||||
*
|
||||
* \a procesesUtilInfo->lastSeenTimeStamp represents the CPU timestamp in microseconds at which utilization samples were last read. Set it to 0
|
||||
* to read utilization based on all the samples maintained by the driver's internal sample buffer. Set \a procesesUtilInfo->lastSeenTimeStamp
|
||||
* to a timeStamp retrieved from a previous query to read utilization since the previous query.
|
||||
*
|
||||
* \a procesesUtilInfo->version is the version number of the structure nvmlProcessesUtilizationInfo_t, the caller should set the correct version
|
||||
* number to retrieve the specific version of processes utilization information.
|
||||
*
|
||||
* @note On MIG-enabled GPUs, querying process utilization is not currently supported.
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param procesesUtilInfo Pointer to the caller-provided structure of nvmlProcessesUtilizationInfo_t.
|
||||
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if \a procesesUtilInfo->procUtilArray has been populated
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a procesesUtilInfo is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature
|
||||
* - \ref NVML_ERROR_NOT_FOUND if sample entries are not found
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH if the version of \a procesesUtilInfo is invalid
|
||||
* - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a procesesUtilInfo->procUtilArray is NULL, or the buffer size of procesesUtilInfo->procUtilArray is too small.
|
||||
* The caller should check the minimul array size from the returned procesesUtilInfo->processSamplesCount, and call
|
||||
* the function again with a buffer no smaller than procesesUtilInfo->processSamplesCount * sizeof(nvmlProcessUtilizationInfo_t)
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetProcessesUtilizationInfo(nvmlDevice_t device, nvmlProcessesUtilizationInfo_t *procesesUtilInfo);
|
||||
|
||||
/** @} */
|
||||
|
||||
/***************************************************************************************************/
|
||||
@@ -6960,6 +7373,30 @@ nvmlReturn_t DECLDIR nvmlDeviceSetConfComputeUnprotectedMemSize(nvmlDevice_t dev
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlSystemSetConfComputeGpusReadyState(unsigned int isAcceptingWork);
|
||||
|
||||
/**
|
||||
* Set Conf Computing key rotation threshold.
|
||||
*
|
||||
* %HOPPER_OR_NEWER%
|
||||
* Supported on Linux, Windows TCC.
|
||||
*
|
||||
* This function is to set the confidential compute key rotation threshold parameters.
|
||||
* @ref pKeyRotationThrInfo->maxAttackerAdvantage should be in the range from
|
||||
* NVML_CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MIN to NVML_CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MAX.
|
||||
* Default value is 60.
|
||||
*
|
||||
* @param pKeyRotationThrInfo Reference to the key rotation threshold data
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if \a key rotation threashold max attacker advantage has been set
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a memory is NULL
|
||||
* - \ref NVML_ERROR_INVALID_STATE if confidential compute GPU ready state is enabled
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlSystemSetConfComputeKeyRotationThresholdInfo(
|
||||
nvmlConfComputeSetKeyRotationThresholdInfo_t *pKeyRotationThrInfo);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -7648,15 +8085,180 @@ nvmlReturn_t DECLDIR nvmlDeviceGetHostVgpuMode(nvmlDevice_t device, nvmlHostVgpu
|
||||
* @param virtualMode virtualization mode. One of NVML_GPU_VIRTUALIZATION_?
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if \a pVirtualMode is set
|
||||
* - \ref NVML_SUCCESS if \a virtualMode is set
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pVirtualMode is NULL
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a virtualMode is NULL
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if setting of virtualization mode is not supported.
|
||||
* - \ref NVML_ERROR_NO_PERMISSION if setting of virtualization mode is not allowed for this client.
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceSetVirtualizationMode(nvmlDevice_t device, nvmlGpuVirtualizationMode_t virtualMode);
|
||||
|
||||
/**
|
||||
* Get the vGPU heterogeneous mode for the device.
|
||||
*
|
||||
* When in heterogeneous mode, a vGPU can concurrently host timesliced vGPUs with differing framebuffer sizes.
|
||||
*
|
||||
* On successful return, the function returns \a pHeterogeneousMode->mode with the current vGPU heterogeneous mode.
|
||||
* \a pHeterogeneousMode->version is the version number of the structure nvmlVgpuHeterogeneousMode_t, the caller should
|
||||
* set the correct version number to retrieve the vGPU heterogeneous mode.
|
||||
* \a pHeterogeneousMode->mode can either be \ref NVML_FEATURE_ENABLED or \ref NVML_FEATURE_DISABLED.
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param pHeterogeneousMode Pointer to the caller-provided structure of nvmlVgpuHeterogeneousMode_t
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device is invalid or \a pHeterogeneousMode is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't support this feature
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH If the version of \a pHeterogeneousMode is invalid
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetVgpuHeterogeneousMode(nvmlDevice_t device, nvmlVgpuHeterogeneousMode_t *pHeterogeneousMode);
|
||||
|
||||
/**
|
||||
* Enable or disable vGPU heterogeneous mode for the device.
|
||||
*
|
||||
* When in heterogeneous mode, a vGPU can concurrently host timesliced vGPUs with differing framebuffer sizes.
|
||||
*
|
||||
* API would return an appropriate error code upon unsuccessful activation. For example, the heterogeneous mode
|
||||
* set will fail with error \ref NVML_ERROR_IN_USE if any vGPU instance is active on the device. The caller of this API
|
||||
* is expected to shutdown the vGPU VMs and retry setting the \a mode.
|
||||
* On successful return, the function updates the vGPU heterogeneous mode with the user provided \a pHeterogeneousMode->mode.
|
||||
* \a pHeterogeneousMode->version is the version number of the structure nvmlVgpuHeterogeneousMode_t, the caller should
|
||||
* set the correct version number to set the vGPU heterogeneous mode.
|
||||
*
|
||||
* @param device Identifier of the target device
|
||||
* @param pHeterogeneousMode Pointer to the caller-provided structure of nvmlVgpuHeterogeneousMode_t
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device or \a pHeterogeneousMode is NULL or \a pHeterogeneousMode->mode is invalid
|
||||
* - \ref NVML_ERROR_IN_USE If the \a device is in use
|
||||
* - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If MIG is enabled or \a device doesn't support this feature
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH If the version of \a pHeterogeneousMode is invalid
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceSetVgpuHeterogeneousMode(nvmlDevice_t device, const nvmlVgpuHeterogeneousMode_t *pHeterogeneousMode);
|
||||
|
||||
/**
|
||||
* Query the placement ID of active vGPU instance.
|
||||
*
|
||||
* When in vGPU heterogeneous mode, this function returns a valid placement ID as \a pPlacement->placementId
|
||||
* else NVML_INVALID_VGPU_PLACEMENT_ID is returned.
|
||||
* \a pPlacement->version is the version number of the structure nvmlVgpuPlacementId_t, the caller should
|
||||
* set the correct version number to get placement id of the vGPU instance \a vgpuInstance.
|
||||
*
|
||||
* @param vgpuInstance Identifier of the target vGPU instance
|
||||
* @param pPlacement Pointer to vGPU placement ID structure \a nvmlVgpuPlacementId_t
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS If information is successfully retrieved
|
||||
* - \ref NVML_ERROR_NOT_FOUND If \a vgpuInstance does not match a valid active vGPU instance
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a vgpuInstance is invalid or \a pPlacement is NULL
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH If the version of \a pPlacement is invalid
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlVgpuInstanceGetPlacementId(nvmlVgpuInstance_t vgpuInstance, nvmlVgpuPlacementId_t *pPlacement);
|
||||
|
||||
/**
|
||||
* Query the supported vGPU placement ID of the vGPU type.
|
||||
*
|
||||
* An array of supported vGPU placement IDs for the vGPU type ID indicated by \a vgpuTypeId is returned in the
|
||||
* caller-supplied buffer of \a pPlacementList->placementIds. Memory needed for the placementIds array should be
|
||||
* allocated based on maximum instances of a vGPU type which can be queried via \ref nvmlVgpuTypeGetMaxInstances().
|
||||
*
|
||||
* This function will return supported placement IDs even if GPU is not in vGPU heterogeneous mode.
|
||||
*
|
||||
* @param device Identifier of the target device
|
||||
* @param vgpuTypeId Handle to vGPU type. The vGPU type ID
|
||||
* @param pPlacementList Pointer to the vGPU placement structure \a nvmlVgpuPlacementList_t
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device or \a vgpuTypeId is invalid or \a pPlacementList is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device or \a vgpuTypeId isn't supported
|
||||
* - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH If the version of \a pPlacementList is invalid
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetVgpuTypeSupportedPlacements(nvmlDevice_t device, nvmlVgpuTypeId_t vgpuTypeId, nvmlVgpuPlacementList_t *pPlacementList);
|
||||
|
||||
/**
|
||||
* Query the creatable vGPU placement ID of the vGPU type.
|
||||
*
|
||||
* An array of creatable vGPU placement IDs for the vGPU type ID indicated by \a vgpuTypeId is returned in the
|
||||
* caller-supplied buffer of \a pPlacementList->placementIds. Memory needed for the placementIds array should be
|
||||
* allocated based on maximum instances of a vGPU type which can be queried via \ref nvmlVgpuTypeGetMaxInstances().
|
||||
* The creatable vGPU placement IDs may differ over time, as there may be restrictions on what type of vGPU the
|
||||
* vGPU instance is running.
|
||||
*
|
||||
* The function will return \ref NVML_ERROR_NOT_SUPPORTED if the \a device is not in vGPU heterogeneous mode.
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param vgpuTypeId Handle to vGPU type. The vGPU type ID
|
||||
* @param pPlacementList Pointer to the list of vGPU placement structure \a nvmlVgpuPlacementList_t
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device or \a vgpuTypeId is invalid or \a pPlacementList is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device or \a vgpuTypeId isn't supported
|
||||
* - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH If the version of \a pPlacementList is invalid
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetVgpuTypeCreatablePlacements(nvmlDevice_t device, nvmlVgpuTypeId_t vgpuTypeId, nvmlVgpuPlacementList_t *pPlacementList);
|
||||
|
||||
/**
|
||||
* Retrieve the static GSP heap size of the vGPU type in bytes
|
||||
*
|
||||
* @param vgpuTypeId Handle to vGPU type
|
||||
* @param gspHeapSize Reference to return the GSP heap size value
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Successful completion
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a vgpuTypeId is invalid, or \a gspHeapSize is NULL
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlVgpuTypeGetGspHeapSize(nvmlVgpuTypeId_t vgpuTypeId, unsigned long long *gspHeapSize);
|
||||
|
||||
/**
|
||||
* Retrieve the static framebuffer reservation of the vGPU type in bytes
|
||||
*
|
||||
* @param vgpuTypeId Handle to vGPU type
|
||||
* @param fbReservation Reference to return the framebuffer reservation
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Successful completion
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a vgpuTypeId is invalid, or \a fbReservation is NULL
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlVgpuTypeGetFbReservation(nvmlVgpuTypeId_t vgpuTypeId, unsigned long long *fbReservation);
|
||||
|
||||
/**
|
||||
* Set the desirable vGPU capability of a device
|
||||
*
|
||||
* Refer to the \a nvmlDeviceVgpuCapability_t structure for the specific capabilities that can be set.
|
||||
* See \ref nvmlEnableState_t for available state.
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param capability Specifies the \a nvmlDeviceVgpuCapability_t to be set
|
||||
* @param state The target capability mode
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS Successful completion
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device is invalid, or \a capability is invalid, or \a state is invalid
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED The API is not supported in current state, or \a device not in vGPU mode
|
||||
* - \ref NVML_ERROR_UNKNOWN On any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceSetVgpuCapabilities(nvmlDevice_t device, nvmlDeviceVgpuCapability_t capability, nvmlEnableState_t state);
|
||||
|
||||
/**
|
||||
* Retrieve the vGPU Software licensable features.
|
||||
*
|
||||
@@ -8774,6 +9376,52 @@ nvmlReturn_t DECLDIR nvmlDeviceGetVgpuUtilization(nvmlDevice_t device, unsigned
|
||||
nvmlValueType_t *sampleValType, unsigned int *vgpuInstanceSamplesCount,
|
||||
nvmlVgpuInstanceUtilizationSample_t *utilizationSamples);
|
||||
|
||||
/**
|
||||
* Retrieves recent utilization for vGPU instances running on a physical GPU (device).
|
||||
*
|
||||
* For Kepler &tm; or newer fully supported devices.
|
||||
*
|
||||
* Reads recent utilization of GPU SM (3D/Compute), framebuffer, video encoder, video decoder, jpeg decoder, and OFA for vGPU
|
||||
* instances running on a device. Utilization values are returned as an array of utilization sample structures in the caller-supplied
|
||||
* buffer pointed at by \a vgpuUtilInfo->vgpuUtilArray. One utilization sample structure is returned per vGPU instance, and includes the
|
||||
* CPU timestamp at which the samples were recorded. Individual utilization values are returned as "unsigned int" values
|
||||
* in nvmlValue_t unions. The function sets the caller-supplied \a vgpuUtilInfo->sampleValType to NVML_VALUE_TYPE_UNSIGNED_INT to
|
||||
* indicate the returned value type.
|
||||
*
|
||||
* To read utilization values, first determine the size of buffer required to hold the samples by invoking the function with
|
||||
* \a vgpuUtilInfo->vgpuUtilArray set to NULL. The function will return NVML_ERROR_INSUFFICIENT_SIZE, with the current vGPU instance
|
||||
* count in \a vgpuUtilInfo->vgpuInstanceCount, or NVML_SUCCESS if the current vGPU instance count is zero. The caller should allocate
|
||||
* a buffer of size vgpuUtilInfo->vgpuInstanceCount * sizeof(nvmlVgpuInstanceUtilizationInfo_t). Invoke the function again with
|
||||
* the allocated buffer passed in \a vgpuUtilInfo->vgpuUtilArray, and \a vgpuUtilInfo->vgpuInstanceCount set to the number of entries the
|
||||
* buffer is sized for.
|
||||
*
|
||||
* On successful return, the function updates \a vgpuUtilInfo->vgpuInstanceCount with the number of vGPU utilization sample
|
||||
* structures that were actually written. This may differ from a previously read value as vGPU instances are created or
|
||||
* destroyed.
|
||||
*
|
||||
* \a vgpuUtilInfo->lastSeenTimeStamp represents the CPU timestamp in microseconds at which utilization samples were last read. Set it to 0
|
||||
* to read utilization based on all the samples maintained by the driver's internal sample buffer. Set \a vgpuUtilInfo->lastSeenTimeStamp
|
||||
* to a timeStamp retrieved from a previous query to read utilization since the previous query.
|
||||
*
|
||||
* @param device The identifier for the target device
|
||||
* @param vgpuUtilInfo Pointer to the caller-provided structure of nvmlVgpuInstancesUtilizationInfo_t
|
||||
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if utilization samples are successfully retrieved
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a vgpuUtilInfo is NULL, or \a vgpuUtilInfo->vgpuInstanceCount is 0
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH if the version of \a vgpuUtilInfo is invalid
|
||||
* - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a vgpuUtilInfo->vgpuUtilArray is NULL, or the buffer size of vgpuUtilInfo->vgpuInstanceCount is too small.
|
||||
* The caller should check the current vGPU instance count from the returned vgpuUtilInfo->vgpuInstanceCount, and call
|
||||
* the function again with a buffer of size vgpuUtilInfo->vgpuInstanceCount * sizeof(nvmlVgpuInstanceUtilizationInfo_t)
|
||||
* - \ref NVML_ERROR_NOT_FOUND if sample entries are not found
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetVgpuInstancesUtilizationInfo(nvmlDevice_t device,
|
||||
nvmlVgpuInstancesUtilizationInfo_t *vgpuUtilInfo);
|
||||
|
||||
/**
|
||||
* Retrieves current utilization for processes running on vGPUs on a physical GPU (device).
|
||||
*
|
||||
@@ -8820,6 +9468,52 @@ nvmlReturn_t DECLDIR nvmlDeviceGetVgpuUtilization(nvmlDevice_t device, unsigned
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetVgpuProcessUtilization(nvmlDevice_t device, unsigned long long lastSeenTimeStamp,
|
||||
unsigned int *vgpuProcessSamplesCount,
|
||||
nvmlVgpuProcessUtilizationSample_t *utilizationSamples);
|
||||
|
||||
/**
|
||||
* Retrieves recent utilization for processes running on vGPU instances on a physical GPU (device).
|
||||
*
|
||||
* For Maxwell &tm; or newer fully supported devices.
|
||||
*
|
||||
* Reads recent utilization of GPU SM (3D/Compute), framebuffer, video encoder, video decoder, jpeg decoder, and OFA for processes running
|
||||
* on vGPU instances active on a device. Utilization values are returned as an array of utilization sample structures in the caller-supplied
|
||||
* buffer pointed at by \a vgpuProcUtilInfo->vgpuProcUtilArray. One utilization sample structure is returned per process running
|
||||
* on vGPU instances, that had some non-zero utilization during the last sample period. It includes the CPU timestamp at which
|
||||
* the samples were recorded. Individual utilization values are returned as "unsigned int" values.
|
||||
*
|
||||
* To read utilization values, first determine the size of buffer required to hold the samples by invoking the function with
|
||||
* \a vgpuProcUtilInfo->vgpuProcUtilArray set to NULL. The function will return NVML_ERROR_INSUFFICIENT_SIZE, with the current processes' count
|
||||
* running on vGPU instances in \a vgpuProcUtilInfo->vgpuProcessCount. The caller should allocate a buffer of size
|
||||
* vgpuProcUtilInfo->vgpuProcessCount * sizeof(nvmlVgpuProcessUtilizationSample_t). Invoke the function again with the allocated buffer passed
|
||||
* in \a vgpuProcUtilInfo->vgpuProcUtilArray, and \a vgpuProcUtilInfo->vgpuProcessCount set to the number of entries the buffer is sized for.
|
||||
*
|
||||
* On successful return, the function updates \a vgpuProcUtilInfo->vgpuProcessCount with the number of vGPU sub process utilization sample
|
||||
* structures that were actually written. This may differ from a previously read value depending on the number of processes that are active
|
||||
* in any given sample period.
|
||||
*
|
||||
* vgpuProcUtilInfo->lastSeenTimeStamp represents the CPU timestamp in microseconds at which utilization samples were last read. Set it to 0
|
||||
* to read utilization based on all the samples maintained by the driver's internal sample buffer. Set vgpuProcUtilInfo->lastSeenTimeStamp
|
||||
* to a timeStamp retrieved from a previous query to read utilization since the previous query.
|
||||
*
|
||||
* @param device The identifier for the target device
|
||||
* @param vgpuProcUtilInfo Pointer to the caller-provided structure of nvmlVgpuProcessesUtilizationInfo_t
|
||||
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if utilization samples are successfully retrieved
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a vgpuProcUtilInfo is null
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH if the version of \a vgpuProcUtilInfo is invalid
|
||||
* - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a vgpuProcUtilInfo->vgpuProcUtilArray is null, or supplied \a vgpuProcUtilInfo->vgpuProcessCount
|
||||
* is too small to return samples for all processes on vGPU instances currently executing on the device.
|
||||
* The caller should check the current processes count from the returned \a vgpuProcUtilInfo->vgpuProcessCount,
|
||||
* and call the function again with a buffer of size
|
||||
* vgpuProcUtilInfo->vgpuProcessCount * sizeof(nvmlVgpuProcessUtilizationSample_t)
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_NOT_FOUND if sample entries are not found
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetVgpuProcessesUtilizationInfo(nvmlDevice_t device, nvmlVgpuProcessesUtilizationInfo_t *vgpuProcUtilInfo);
|
||||
|
||||
/**
|
||||
* Queries the state of per process accounting mode on vGPU.
|
||||
*
|
||||
@@ -9304,7 +9998,7 @@ nvmlReturn_t DECLDIR nvmlDeviceSetMigMode(nvmlDevice_t device, unsigned int mode
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetMigMode(nvmlDevice_t device, unsigned int *currentMode, unsigned int *pendingMode);
|
||||
|
||||
/**
|
||||
* Get GPU instance profile information.
|
||||
* Get GPU instance profile information
|
||||
*
|
||||
* Information provided by this API is immutable throughout the lifetime of a MIG mode.
|
||||
*
|
||||
@@ -9319,7 +10013,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetMigMode(nvmlDevice_t device, unsigned int *cur
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device, \a profile or \a info are invalid
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't have MIG mode enabled or \a profile isn't supported
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't support MIG or \a profile isn't supported
|
||||
* - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstanceProfileInfo(nvmlDevice_t device, unsigned int profile,
|
||||
@@ -9360,7 +10054,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstanceProfileInfoV(nvmlDevice_t device, u
|
||||
* Get GPU instance placements.
|
||||
*
|
||||
* A placement represents the location of a GPU instance within a device. This API only returns all the possible
|
||||
* placements for the given profile.
|
||||
* placements for the given profile regardless of whether MIG is enabled or not.
|
||||
* A created GPU instance occupies memory slices described by its placement. Creation of new GPU instance will
|
||||
* fail if there is overlap with the already occupied memory slices.
|
||||
*
|
||||
@@ -9379,7 +10073,7 @@ nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstanceProfileInfoV(nvmlDevice_t device, u
|
||||
* - \ref NVML_SUCCESS Upon success
|
||||
* - \ref NVML_ERROR_UNINITIALIZED If library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT If \a device, \a profileId or \a count are invalid
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't have MIG mode enabled or \a profileId isn't supported
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED If \a device doesn't support MIG or \a profileId isn't supported
|
||||
* - \ref NVML_ERROR_NO_PERMISSION If user doesn't have permission to perform the operation
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetGpuInstancePossiblePlacements_v2(nvmlDevice_t device, unsigned int profileId,
|
||||
@@ -10287,7 +10981,7 @@ nvmlReturn_t DECLDIR nvmlSystemGetNvlinkBwMode(unsigned int *nvlinkBwMode);
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*
|
||||
* @see NVML_FI_DEV_POWER_AVERAGE
|
||||
* @see NVML_FI_DEV_POWER_AVERAGE
|
||||
* @see NVML_FI_DEV_POWER_INSTANT
|
||||
* @see NVML_FI_DEV_POWER_MIN_LIMIT
|
||||
* @see NVML_FI_DEV_POWER_MAX_LIMIT
|
||||
@@ -10295,7 +10989,28 @@ nvmlReturn_t DECLDIR nvmlSystemGetNvlinkBwMode(unsigned int *nvlinkBwMode);
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceSetPowerManagementLimit_v2(nvmlDevice_t device, nvmlPowerValue_v2_t *powerValue);
|
||||
|
||||
|
||||
/**
|
||||
* Get SRAM ECC error status of this device.
|
||||
*
|
||||
* For Ampere &tm; or newer fully supported devices.
|
||||
* Requires root/admin permissions.
|
||||
*
|
||||
* See \ref nvmlEccSramErrorStatus_v1_t for more information on the struct.
|
||||
*
|
||||
* @param device The identifier of the target device
|
||||
* @param status Returns SRAM ECC error status
|
||||
*
|
||||
* @return
|
||||
* - \ref NVML_SUCCESS if \a limit has been set
|
||||
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
|
||||
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a counters is NULL
|
||||
* - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature
|
||||
* - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible
|
||||
* - \ref NVML_ERROR_VERSION_MISMATCH if the version of \a nvmlEccSramErrorStatus_t is invalid
|
||||
* - \ref NVML_ERROR_UNKNOWN on any unexpected error
|
||||
*/
|
||||
nvmlReturn_t DECLDIR nvmlDeviceGetSramEccErrorStatus(nvmlDevice_t device,
|
||||
nvmlEccSramErrorStatus_t *status);
|
||||
/**
|
||||
* NVML API versioning support
|
||||
*/
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/NVIDIA/nvidia-settings/blob/main/src/nvml.h",
|
||||
"license": "Embed in source",
|
||||
"version": "545.23.06",
|
||||
"version": "550.54.14",
|
||||
"author": "NVIDIA Corporation"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
bool ffParseModuleOptions(const char* key, const char* value)
|
||||
{
|
||||
if (!ffStrStartsWith(key, "--") || !isalpha(key[2])) return false;
|
||||
if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false;
|
||||
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
@@ -102,7 +102,7 @@ static void parseStructureCommand(
|
||||
}
|
||||
}
|
||||
|
||||
if(isalpha(line[0]))
|
||||
if(ffCharIsEnglishAlphabet(line[0]))
|
||||
{
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
|
||||
+6
-4
@@ -181,22 +181,24 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
|
||||
return reply;
|
||||
}
|
||||
|
||||
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result)
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result)
|
||||
{
|
||||
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
|
||||
if(reply == NULL)
|
||||
return;
|
||||
return false;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(reply);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ffDBusGetValue(dbus, &rootIterator, result);
|
||||
bool ret = ffDBusGetValue(dbus, &rootIterator, result);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(reply);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_DBUS
|
||||
|
||||
+1
-1
@@ -48,6 +48,6 @@ bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
|
||||
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result);
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method);
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
|
||||
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
|
||||
+5
-5
@@ -238,9 +238,6 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_DDCUTIL
|
||||
"libddcutil\n"
|
||||
#endif
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
"videodev2\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
"Directx Headers\n"
|
||||
#endif
|
||||
@@ -250,8 +247,11 @@ void ffListFeatures(void)
|
||||
#ifdef FF_USE_SYSTEM_YYJSON
|
||||
"System yyjson\n"
|
||||
#endif
|
||||
#ifdef FF_USE_PCI_MEMORY
|
||||
"PCI memory\n"
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
"linux/videodev2\n"
|
||||
#endif
|
||||
#if __has_include(<linux/wireless.h>)
|
||||
"linux/wireless\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/unused.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
@@ -133,6 +133,9 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
|
||||
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
{
|
||||
if (instance.config.display.pipe)
|
||||
return "Not supported in --pipe mode";
|
||||
|
||||
struct termios oldTerm, newTerm;
|
||||
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
|
||||
return "tcgetattr(STDIN_FILENO, &oldTerm) failed";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
@@ -174,6 +175,9 @@ void ffListFilesRecursively(const char* path, bool pretty)
|
||||
|
||||
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
{
|
||||
if (instance.config.display.pipe)
|
||||
return "Not supported in --pipe mode";
|
||||
|
||||
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD prev_mode;
|
||||
GetConsoleMode(hInput, &prev_mode);
|
||||
|
||||
@@ -94,7 +94,7 @@ static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc
|
||||
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
if(!isalpha(type[0])) return false;
|
||||
if(!ffCharIsEnglishAlphabet(type[0])) return false;
|
||||
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
//Clang doesn't define __SANITIZE_ADDRESS__ but defines __has_feature(address_sanitizer)
|
||||
#if defined(__has_feature)
|
||||
#if !defined(__SANITIZE_ADDRESS__) && defined(__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
#define __SANITIZE_ADDRESS__
|
||||
#endif
|
||||
|
||||
@@ -8,10 +8,7 @@ static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const ar
|
||||
{
|
||||
const char* error = ffProcessAppendOutput(buffer, argv, false);
|
||||
if (!error)
|
||||
{
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
}
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -19,9 +16,6 @@ static inline const char* ffProcessAppendStdErr(FFstrbuf* buffer, char* const ar
|
||||
{
|
||||
const char* error = ffProcessAppendOutput(buffer, argv, true);
|
||||
if (!error)
|
||||
{
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
}
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout";
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
{
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "WaitForSingleObject(hChildPipeRead) failed or timeout";
|
||||
return "WaitForSingleObject(hChildPipeRead) failed or timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
|
||||
|
||||
+29
-36
@@ -1,5 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef _WIN32
|
||||
@@ -95,50 +97,44 @@ bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
|
||||
|
||||
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
FILE* file = fopen(filename, "r");
|
||||
if(file == NULL)
|
||||
FF_AUTO_CLOSE_FILE FILE* file = fopen(filename, "r");
|
||||
if (file == NULL)
|
||||
return false;
|
||||
|
||||
bool valueStorage[4];
|
||||
bool* unsetValues;
|
||||
bool valueStorage[32];
|
||||
bool* unsetValues = valueStorage;
|
||||
|
||||
if(numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
|
||||
if (numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
|
||||
unsetValues = malloc(sizeof(bool) * numQueries);
|
||||
else
|
||||
unsetValues = valueStorage;
|
||||
|
||||
bool allSet = true;
|
||||
for(uint32_t i = 0; i < numQueries; i++)
|
||||
for (uint32_t i = 0; i < numQueries; i++)
|
||||
{
|
||||
if((unsetValues[i] = queries[i].buffer->length == 0))
|
||||
unsetValues[i] = queries[i].buffer->length == 0;
|
||||
if (unsetValues[i])
|
||||
allSet = false;
|
||||
}
|
||||
|
||||
if(allSet)
|
||||
goto done;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (getline(&line, &len, file) != -1)
|
||||
if (!allSet)
|
||||
{
|
||||
for(uint32_t i = 0; i < numQueries; i++)
|
||||
{
|
||||
if(!unsetValues[i])
|
||||
continue;
|
||||
FF_AUTO_FREE char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
uint32_t currentLength = queries[i].buffer->length;
|
||||
queries[i].buffer->length = 0;
|
||||
if(!ffParsePropLine(line, queries[i].start, queries[i].buffer))
|
||||
queries[i].buffer->length = currentLength;
|
||||
while (getline(&line, &len, file) != -1)
|
||||
{
|
||||
for(uint32_t i = 0; i < numQueries; i++)
|
||||
{
|
||||
if(!unsetValues[i])
|
||||
continue;
|
||||
|
||||
uint32_t currentLength = queries[i].buffer->length;
|
||||
queries[i].buffer->length = 0;
|
||||
if(!ffParsePropLine(line, queries[i].start, queries[i].buffer))
|
||||
queries[i].buffer->length = currentLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
done:
|
||||
fclose(file);
|
||||
if(unsetValues != valueStorage)
|
||||
free(unsetValues);
|
||||
return true;
|
||||
@@ -154,16 +150,13 @@ bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uin
|
||||
{
|
||||
bool foundAFile = false;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, dirPrefix, *list)
|
||||
{
|
||||
//We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it.
|
||||
ffStrbufSet(&baseDir, dirPrefix);
|
||||
ffStrbufAppendS(&baseDir, relativeFile);
|
||||
|
||||
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
|
||||
const uint32_t dirPrefixLength = dirPrefix->length;
|
||||
ffStrbufAppendS(dirPrefix, relativeFile);
|
||||
if(ffParsePropFileValues(dirPrefix->chars, numQueries, queries))
|
||||
foundAFile = true;
|
||||
ffStrbufSubstrBefore(dirPrefix, dirPrefixLength);
|
||||
|
||||
bool allSet = true;
|
||||
for(uint32_t k = 0; k < numQueries; k++)
|
||||
|
||||
+12
-9
@@ -702,6 +702,16 @@
|
||||
"type": "color",
|
||||
"default": "light_red"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "ts-version",
|
||||
"desc": "Whether to detect and display the version of terminal and shell",
|
||||
"remark": "Mainly for benchmarking",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"Library path": [
|
||||
@@ -927,17 +937,10 @@
|
||||
"default": "-"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "os-file",
|
||||
"desc": "Set the additional file path which containing OS information",
|
||||
"remark": "Linux only",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "disk-folders",
|
||||
"desc": "A colon (semicolon on Windows) separated list of folder paths for the disk output",
|
||||
"desc": "A colon (semicolon on Windows) separated list of folder paths to be detected",
|
||||
"remark": "On Windows, a drive latter must be upper cased and end with \"\\\". \"/\" is used as an alias of the system drive. This option overrides other disk-show-* options",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"default": "Auto detection using mount-points"
|
||||
|
||||
@@ -3,7 +3,8 @@ Usage: fastfetch --color <color>
|
||||
<color> must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m".
|
||||
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||
Examples:
|
||||
--color 35: sets the color to magenta. `--color magenta` is also supported
|
||||
--color 4;92: sets the color to bright Green with underline
|
||||
--color 5;104: blinking text on a blue background
|
||||
--color 35: sets the color to magenta. `--color magenta` is also supported
|
||||
--color 38;5;38: sets the color to 38th color of ANSI 256 colors
|
||||
--color 4;92: sets the color to bright Green with underline
|
||||
--color 5;104: blinking text on a blue background
|
||||
If no color is set, the main color of the logo will be used.
|
||||
|
||||
@@ -40,6 +40,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
|
||||
@@ -77,6 +78,8 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
|
||||
ffStrbufAppendS(&battery->status, "AC powered");
|
||||
|
||||
@@ -170,8 +170,5 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
if(results->length == 0)
|
||||
return "\"/sys/class/power_supply/\" doesn't contain any battery folder";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "battery.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
@@ -20,11 +22,6 @@ NtPowerInformation(
|
||||
OUT PVOID OutputBuffer OPTIONAL,
|
||||
IN ULONG OutputBufferLength);
|
||||
|
||||
static inline void wrapCloseHandle(HANDLE* handle)
|
||||
{
|
||||
if(*handle)
|
||||
CloseHandle(*handle);
|
||||
}
|
||||
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
{
|
||||
if(*hdev)
|
||||
@@ -52,7 +49,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||
continue;
|
||||
|
||||
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
|
||||
HANDLE FF_AUTO_CLOSE_FD hBattery =
|
||||
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(hBattery == INVALID_HANDLE_VALUE)
|
||||
|
||||
@@ -1,10 +1,31 @@
|
||||
#include "camera.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#import <AVFoundation/AVCaptureDevice.h>
|
||||
|
||||
// warning: 'AVCaptureDeviceTypeExternalUnknown' is deprecated
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
|
||||
FF_SUPPRESS_IO(); // #822
|
||||
|
||||
AVCaptureDeviceType deviceType;
|
||||
|
||||
#ifdef MAC_OS_VERSION_14_0
|
||||
if (@available(macOS 14.0, *))
|
||||
{
|
||||
deviceType = AVCaptureDeviceTypeExternal;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
deviceType = AVCaptureDeviceTypeExternalUnknown;
|
||||
}
|
||||
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera, deviceType]
|
||||
mediaType:AVMediaTypeVideo
|
||||
position:AVCaptureDevicePositionUnspecified];
|
||||
if (!session)
|
||||
return "Failed to create AVCaptureDeviceDiscoverySession";
|
||||
|
||||
|
||||
@@ -18,3 +18,24 @@ const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffCPUAppleCodeToName(uint32_t code)
|
||||
{
|
||||
// https://github.com/AsahiLinux/docs/wiki/Codenames
|
||||
switch (code)
|
||||
{
|
||||
case 8103: return "Apple M1";
|
||||
case 6000: return "Apple M1 Pro";
|
||||
case 6001: return "Apple M1 Max";
|
||||
case 6002: return "Apple M1 Ultra";
|
||||
case 8112: return "Apple M2";
|
||||
case 6020: return "Apple M2 Pro";
|
||||
case 6021: return "Apple M2 Max";
|
||||
case 6022: return "Apple M2 Ultra";
|
||||
case 8122: return "Apple M3";
|
||||
case 6030: return "Apple M3 Pro";
|
||||
case 6031:
|
||||
case 6034: return "Apple M3 Max";
|
||||
default: return "Apple Silicon";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,3 +22,4 @@ typedef struct FFCPUResult
|
||||
|
||||
const char* ffCPUDetectByCpuid(FFCPUResult* cpu);
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
const char* ffCPUAppleCodeToName(uint32_t code);
|
||||
|
||||
@@ -210,23 +210,8 @@ void detectAsahi(FFCPUResult* cpu)
|
||||
char* modelName = memchr(content, '\0', (size_t) length) + 1;
|
||||
if (modelName - content < length && ffStrStartsWith(modelName, "apple,t"))
|
||||
{
|
||||
// https://github.com/AsahiLinux/docs/wiki/Codenames
|
||||
switch (strtoul(modelName + strlen("apple,t"), NULL, 10))
|
||||
{
|
||||
case 8103: ffStrbufSetStatic(&cpu->name, "Apple M1"); break;
|
||||
case 6000: ffStrbufSetStatic(&cpu->name, "Apple M1 Pro"); break;
|
||||
case 6001: ffStrbufSetStatic(&cpu->name, "Apple M1 Max"); break;
|
||||
case 6002: ffStrbufSetStatic(&cpu->name, "Apple M1 Ultra"); break;
|
||||
case 8112: ffStrbufSetStatic(&cpu->name, "Apple M2"); break;
|
||||
case 6020: ffStrbufSetStatic(&cpu->name, "Apple M2 Pro"); break;
|
||||
case 6021: ffStrbufSetStatic(&cpu->name, "Apple M2 Max"); break;
|
||||
case 6022: ffStrbufSetStatic(&cpu->name, "Apple M2 Ultra"); break;
|
||||
case 8122: ffStrbufSetStatic(&cpu->name, "Apple M3"); break;
|
||||
case 6030: ffStrbufSetStatic(&cpu->name, "Apple M3 Pro"); break;
|
||||
case 6031:
|
||||
case 6034: ffStrbufSetStatic(&cpu->name, "Apple M3 Max"); break;
|
||||
default: ffStrbufSetStatic(&cpu->name, "Apple Silicon"); break;
|
||||
}
|
||||
uint32_t deviceId = (uint32_t) strtoul(modelName + strlen("apple,t"), NULL, 10);
|
||||
ffStrbufSetStatic(&cpu->name, ffCPUAppleCodeToName(deviceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,31 @@ typedef struct FFSmbiosProcessorInfo
|
||||
uint16_t ThreadEnabled; // varies
|
||||
} FFSmbiosProcessorInfo;
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t base = 0, max = 0, bus = 0, unused = 0;
|
||||
if (!__get_cpuid(0x16, &base, &max, &bus, &unused))
|
||||
return "Unsupported instruction";
|
||||
|
||||
// cpuid returns 0 MHz when hyper-v is enabled
|
||||
if (base) cpu->frequencyBase = base / 1000.0;
|
||||
if (max) cpu->frequencyMax = max / 1000.0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline static const char* detectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
return "Unsupported platform";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
{
|
||||
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO];
|
||||
@@ -64,13 +89,12 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
return "No active CPU is found in SMBIOS data";
|
||||
}
|
||||
|
||||
if (data->MaxSpeed > 0 && data->MaxSpeed < 30000) // VMware reports weird values
|
||||
{
|
||||
double speed = data->MaxSpeed / 1000.0;
|
||||
if (cpu->frequencyBase < speed)
|
||||
cpu->frequencyMax = speed;
|
||||
}
|
||||
double speed = data->MaxSpeed / 1000.0;
|
||||
// Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base
|
||||
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2)
|
||||
return "Possible invalid CPU max speed in SMBIOS data. See #800";
|
||||
|
||||
cpu->frequencyMax = speed;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -115,6 +139,7 @@ static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
|
||||
if (detectSpeedByCpuid(cpu) != NULL || cpu->frequencyBase != cpu->frequencyBase)
|
||||
{
|
||||
uint32_t mhz;
|
||||
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||
@@ -142,7 +167,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
if (cpu->frequencyMax != cpu->frequencyMax)
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
if(options->temp)
|
||||
ffDetectSmbiosTemp(&cpu->temperature, NULL);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "de.h"
|
||||
|
||||
#include "common/dbus.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
@@ -12,19 +13,20 @@
|
||||
|
||||
static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
if(result->length == 0)
|
||||
{
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
}
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
{
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
}
|
||||
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
@@ -41,11 +43,25 @@ static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getGnomeByDbus(FF_MAYBE_UNUSED FFstrbuf* result)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
FFDBusData dbus;
|
||||
if (ffDBusLoadData(DBUS_BUS_SESSION, &dbus) != NULL)
|
||||
return "ffDBusLoadData() failed";
|
||||
|
||||
ffDBusGetPropertyString(&dbus, "org.gnome.Shell", "/org/gnome/Shell", "org.gnome.Shell", "ShellVersion", result);
|
||||
return NULL;
|
||||
#else // FF_HAVE_DBUS
|
||||
return "ffDBusLoadData() failed: dbus support not compiled in";
|
||||
#endif // FF_HAVE_DBUS
|
||||
}
|
||||
|
||||
static void getGnome(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gnome-shell/org.gnome.Extensions", "version :", result);
|
||||
getGnomeByDbus(result);
|
||||
|
||||
if (result->length == 0)
|
||||
if (result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
"gnome-shell",
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
#include "disk.h"
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks);
|
||||
bool ffDiskMatchMountpoint(FFDiskOptions* options, const char* mountpoint)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char separator = ';';
|
||||
#else
|
||||
const char separator = ':';
|
||||
#endif
|
||||
|
||||
uint32_t mountpointLength = (uint32_t) strlen(mountpoint);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < options->folders.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&options->folders, startIndex, separator);
|
||||
|
||||
uint32_t folderLength = colonIndex - startIndex;
|
||||
if (folderLength == mountpointLength && memcmp(options->folders.chars + startIndex, mountpoint, mountpointLength) == 0)
|
||||
return true;
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
{
|
||||
@@ -9,7 +32,7 @@ static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
const char* error = ffDetectDisksImpl(disks);
|
||||
const char* error = ffDetectDisksImpl(options, disks);
|
||||
|
||||
if (error) return error;
|
||||
if (disks->length == 0) return "No disks found";
|
||||
|
||||
@@ -26,3 +26,6 @@ typedef struct FFDisk
|
||||
* If error is not set, disks contains at least one disk.
|
||||
*/
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks /* list of FFDisk */);
|
||||
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks);
|
||||
bool ffDiskMatchMountpoint(FFDiskOptions* options, const char* mountpoint);
|
||||
|
||||
@@ -90,7 +90,7 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
int size = getfsstat(NULL, 0, MNT_WAIT);
|
||||
|
||||
@@ -103,7 +103,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
for(struct statfs* fs = buf; fs < buf + size; ++fs)
|
||||
{
|
||||
if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
|
||||
if(__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if(!ffDiskMatchMountpoint(options, fs->f_mntonname))
|
||||
continue;
|
||||
}
|
||||
else if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
|
||||
continue;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
@@ -31,7 +31,7 @@ static bool isPhysicalDevice(const struct mntent* device)
|
||||
|
||||
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
|
||||
if(ffStrEquals(device->mnt_type, "9p"))
|
||||
return true;
|
||||
return ffStrContains(device->mnt_opts, "aname=drvfs");
|
||||
|
||||
//ZFS pool
|
||||
if(ffStrEquals(device->mnt_type, "zfs"))
|
||||
@@ -250,7 +250,7 @@ static void detectStats(FFDisk* disk)
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
FILE* mountsFile = setmntent("/proc/mounts", "r");
|
||||
if(mountsFile == NULL)
|
||||
@@ -260,7 +260,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
while((device = getmntent(mountsFile)))
|
||||
{
|
||||
if(!isPhysicalDevice(device))
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(options, device->mnt_dir))
|
||||
continue;
|
||||
}
|
||||
else if(!isPhysicalDevice(device))
|
||||
continue;
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
|
||||
@@ -1,53 +1,102 @@
|
||||
#include "disk.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/thread.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
static unsigned __stdcall testRemoteVolumeAccessable(void* mountpoint)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(
|
||||
(wchar_t*) mountpoint,
|
||||
READ_CONTROL,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
wchar_t buf[MAX_PATH + 1];
|
||||
uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf);
|
||||
if (length == 0 || length >= sizeof(buf) / sizeof(*buf))
|
||||
return "GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf) failed";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
// For cross-platform portability; used by `presets/examples/13.jsonc`
|
||||
if (__builtin_expect(options->folders.length == 1 && options->folders.chars[0] == '/', 0))
|
||||
{
|
||||
wchar_t path[MAX_PATH + 1];
|
||||
GetSystemWindowsDirectoryW(path, sizeof(path) / sizeof(*path));
|
||||
ffStrbufSetF(&options->folders, "%c:\\", (char) path[0]);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
wchar_t* mountpoint = buf + i;
|
||||
|
||||
ffStrbufSetWS(&buffer, mountpoint);
|
||||
i += buffer.length;
|
||||
|
||||
UINT driveType = GetDriveTypeW(mountpoint);
|
||||
if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
|
||||
if (__builtin_expect((long) options->folders.length, 0))
|
||||
{
|
||||
i += (uint32_t)wcslen(mountpoint);
|
||||
continue;
|
||||
if (!ffDiskMatchMountpoint(options, buffer.chars))
|
||||
continue;
|
||||
}
|
||||
else if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
continue;
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
|
||||
if(!GetDiskFreeSpaceExW(
|
||||
disk->filesUsed = 0;
|
||||
disk->filesTotal = 0;
|
||||
disk->bytesTotal = 0;
|
||||
disk->bytesFree = 0;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
disk->bytesAvailable = 0;
|
||||
disk->createTime = 0;
|
||||
ffStrbufInit(&disk->filesystem);
|
||||
ffStrbufInit(&disk->name);
|
||||
ffStrbufInitMove(&disk->mountpoint, &buffer);
|
||||
ffStrbufInit(&disk->mountFrom);
|
||||
disk->type = driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM
|
||||
? FF_DISK_VOLUME_TYPE_EXTERNAL_BIT
|
||||
: driveType == DRIVE_FIXED
|
||||
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
|
||||
: FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
|
||||
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
|
||||
{
|
||||
wchar_t volumeName[MAX_PATH + 1];
|
||||
mountpoint[2] = L'\0';
|
||||
if(QueryDosDeviceW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
|
||||
ffStrbufSetWS(&disk->mountFrom, volumeName);
|
||||
mountpoint[2] = L'\\';
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (driveType == DRIVE_REMOTE)
|
||||
{
|
||||
FFThreadType thread = ffThreadCreate(testRemoteVolumeAccessable, mountpoint);
|
||||
if (!ffThreadJoin(thread, 500))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
GetDiskFreeSpaceExW(
|
||||
mountpoint,
|
||||
(PULARGE_INTEGER)&disk->bytesAvailable,
|
||||
(PULARGE_INTEGER)&disk->bytesTotal,
|
||||
(PULARGE_INTEGER)&disk->bytesFree
|
||||
))
|
||||
{
|
||||
disk->bytesTotal = 0;
|
||||
disk->bytesFree = 0;
|
||||
disk->bytesAvailable = 0;
|
||||
}
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
);
|
||||
|
||||
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
|
||||
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
else if(driveType == DRIVE_FIXED)
|
||||
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
|
||||
ffStrbufInit(&disk->filesystem);
|
||||
ffStrbufInit(&disk->name);
|
||||
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
|
||||
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
|
||||
@@ -74,25 +123,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
if(GetFileAttributesExW(mountpoint, GetFileExInfoStandard, &data) && data.ftCreationTime.dwHighDateTime > 0)
|
||||
disk->createTime = (*(uint64_t*) &data.ftCreationTime - 116444736000000000ull) / 10000ull;
|
||||
else
|
||||
disk->createTime = 0;
|
||||
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
|
||||
{
|
||||
wchar_t volumeName[MAX_PATH + 1];
|
||||
mountpoint[2] = L'\0';
|
||||
if(QueryDosDeviceW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
|
||||
ffStrbufInitWS(&disk->mountFrom, volumeName);
|
||||
else
|
||||
ffStrbufInit(&disk->mountFrom);
|
||||
}
|
||||
|
||||
//Unsupported
|
||||
disk->filesUsed = 0;
|
||||
disk->filesTotal = 0;
|
||||
|
||||
i += disk->mountpoint.length;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define FF_DE_PRETTY_BUDGIE "Budgie"
|
||||
#define FF_DE_PRETTY_CDE "CDE"
|
||||
#define FF_DE_PRETTY_UNITY "Unity"
|
||||
#define FF_DE_PRETTY_UKUI "UKUI"
|
||||
|
||||
#define FF_WM_PRETTY_KWIN "KWin"
|
||||
#define FF_WM_PRETTY_MUTTER "Mutter"
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "common/settings.h"
|
||||
@@ -57,3 +60,43 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
//This fills in missing information about WM / DE by using env vars and iterating processes
|
||||
ffdsDetectWMDE(ds);
|
||||
}
|
||||
|
||||
bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName)
|
||||
{
|
||||
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name
|
||||
// The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc."
|
||||
// However I can't find a better method to get the edid data
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
|
||||
DIR* dirp = opendir(drmDirPath);
|
||||
if(dirp == NULL)
|
||||
return false;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
const char* plainName = entry->d_name;
|
||||
if (ffStrStartsWith(plainName, "card"))
|
||||
{
|
||||
const char* tmp = strchr(plainName + strlen("card"), '-');
|
||||
if (tmp) plainName = tmp + 1;
|
||||
}
|
||||
if (ffStrEquals(plainName, connName))
|
||||
{
|
||||
ffStrbufAppendF(edidName, "%s%s/edid", drmDirPath, entry->d_name);
|
||||
|
||||
uint8_t edidData[128];
|
||||
if(ffReadFileData(edidName->chars, sizeof(edidData), edidData) == sizeof(edidData))
|
||||
{
|
||||
ffStrbufClear(edidName);
|
||||
ffEdidGetName(edidData, edidName);
|
||||
closedir(dirp);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ffStrbufClear(edidName);
|
||||
closedir(dirp);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName);
|
||||
|
||||
const char* ffdsConnectWlroots(FFDisplayServerResult* result);
|
||||
void ffdsConnectWayland(FFDisplayServerResult* result);
|
||||
|
||||
void ffdsConnectXcbRandr(FFDisplayServerResult* result);
|
||||
|
||||
@@ -36,31 +36,28 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
|
||||
ffStrbufAppendS(&drmDir, "/modes");
|
||||
|
||||
char modes[32];
|
||||
if (ffReadFileData(drmDir.chars, sizeof(modes), modes) < 3)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned width = 0, height = 0;
|
||||
double refreshRate = 0;
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
|
||||
|
||||
int scanned = sscanf(modes, "%ux%u", &width, &height);
|
||||
if(scanned == 2 && width > 0 && height > 0)
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
|
||||
ffStrbufAppendS(&drmDir, "/edid");
|
||||
|
||||
uint8_t edidData[128];
|
||||
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData))
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
ffStrbufAppendS(&drmDir, "/edid");
|
||||
ffEdidGetName(edidData, &name);
|
||||
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
|
||||
ffStrbufAppendS(&drmDir, "/modes");
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
|
||||
uint8_t edidData[128];
|
||||
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData))
|
||||
ffEdidGetName(edidData, &name);
|
||||
else
|
||||
char modes[32];
|
||||
if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3)
|
||||
{
|
||||
sscanf(modes, "%ux%u", &width, &height);
|
||||
const char* plainName = entry->d_name;
|
||||
if (ffStrStartsWith(plainName, "card"))
|
||||
{
|
||||
@@ -69,20 +66,20 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
|
||||
}
|
||||
ffStrbufAppendS(&name, plainName);
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(
|
||||
result,
|
||||
width, height,
|
||||
0,
|
||||
0, 0,
|
||||
0,
|
||||
&name,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(
|
||||
result,
|
||||
width, height,
|
||||
refreshRate,
|
||||
0, 0,
|
||||
0,
|
||||
&name,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,352 +0,0 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
#include "common/library.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/thread.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include <wayland-client.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
|
||||
typedef struct WaylandData
|
||||
{
|
||||
FFDisplayServerResult* result;
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
|
||||
FF_LIBRARY_SYMBOL(wl_display_roundtrip)
|
||||
struct wl_display* display;
|
||||
const struct wl_interface* ffwl_output_interface;
|
||||
} WaylandData;
|
||||
|
||||
typedef struct WaylandDisplay
|
||||
{
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
int32_t scale;
|
||||
enum wl_output_transform transform;
|
||||
FFDisplayType type;
|
||||
FFstrbuf name;
|
||||
FFstrbuf description;
|
||||
FFstrbuf vendorAndModelId;
|
||||
FFstrbuf edidName;
|
||||
} WaylandDisplay;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
struct ucred ucred;
|
||||
socklen_t len = sizeof(struct ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
|
||||
return;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate();
|
||||
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
|
||||
ffReadFileBuffer(procPath.chars, &result->wmProcessName);
|
||||
ffStrbufTrimRightSpace(&result->wmProcessName);
|
||||
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
|
||||
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
|
||||
}
|
||||
#else
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_UNUSED(fd, result);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void stubListener(void* data, ...)
|
||||
{
|
||||
(void) data;
|
||||
}
|
||||
|
||||
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||
return;
|
||||
|
||||
WaylandDisplay* display = data;
|
||||
display->width = width;
|
||||
display->height = height;
|
||||
display->refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->scale = scale;
|
||||
}
|
||||
|
||||
static void waylandOutputGeometryListener(void *data,
|
||||
FF_MAYBE_UNUSED struct wl_output *output,
|
||||
FF_MAYBE_UNUSED int32_t x,
|
||||
FF_MAYBE_UNUSED int32_t y,
|
||||
FF_MAYBE_UNUSED int32_t physical_width,
|
||||
FF_MAYBE_UNUSED int32_t physical_height,
|
||||
FF_MAYBE_UNUSED int32_t subpixel,
|
||||
const char *make,
|
||||
const char *model,
|
||||
int32_t transform)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->transform = (enum wl_output_transform) transform;
|
||||
if (make && !ffStrEqualsIgnCase(make, "unknown") && model && !ffStrEqualsIgnCase(model, "unknown"))
|
||||
{
|
||||
ffStrbufAppendS(&display->vendorAndModelId, make);
|
||||
ffStrbufAppendS(&display->vendorAndModelId, model);
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchDrmConnector(const char* wlName, FFstrbuf* edidName)
|
||||
{
|
||||
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name
|
||||
// The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc."
|
||||
// However I can't find a better method to get the edid data
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
|
||||
DIR* dirp = opendir(drmDirPath);
|
||||
if(dirp == NULL)
|
||||
return false;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
const char* plainName = entry->d_name;
|
||||
if (ffStrStartsWith(plainName, "card"))
|
||||
{
|
||||
const char* tmp = strchr(plainName + strlen("card"), '-');
|
||||
if (tmp) plainName = tmp + 1;
|
||||
}
|
||||
if (ffStrEquals(plainName, wlName))
|
||||
{
|
||||
ffStrbufAppendF(edidName, "%s%s/edid", drmDirPath, entry->d_name);
|
||||
|
||||
uint8_t edidData[128];
|
||||
if(ffReadFileData(edidName->chars, sizeof(edidData), edidData) == sizeof(edidData))
|
||||
{
|
||||
ffStrbufClear(edidName);
|
||||
ffEdidGetName(edidData, edidName);
|
||||
closedir(dirp);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ffStrbufClear(edidName);
|
||||
closedir(dirp);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void waylandOutputNameListener(void *data, FF_MAYBE_UNUSED struct wl_output *output, const char *name)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
if(ffStrStartsWith(name, "eDP-"))
|
||||
display->type = FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(ffStrStartsWith(name, "HDMI-"))
|
||||
display->type = FF_DISPLAY_TYPE_EXTERNAL;
|
||||
matchDrmConnector(name, &display->edidName);
|
||||
ffStrbufAppendS(&display->name, name);
|
||||
}
|
||||
|
||||
static void waylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED struct wl_output* wl_output, const char* description)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
while (*description == ' ') ++description;
|
||||
if (!ffStrEquals(description, "Unknown Display"))
|
||||
ffStrbufAppendS(&display->description, description);
|
||||
}
|
||||
|
||||
static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
WaylandDisplay display = {
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
};
|
||||
ffStrbufInit(&display.name);
|
||||
ffStrbufInit(&display.description);
|
||||
ffStrbufInit(&display.vendorAndModelId);
|
||||
ffStrbufInit(&display.edidName);
|
||||
|
||||
// Dirty hack for #477
|
||||
// The order of these callbacks MUST follow `struct wl_output_listener`
|
||||
void* outputListener[] = {
|
||||
waylandOutputGeometryListener, // geometry
|
||||
waylandOutputModeListener, // mode
|
||||
stubListener, // done
|
||||
waylandOutputScaleListener, // scale
|
||||
waylandOutputNameListener, // name
|
||||
waylandOutputDescriptionListener, // description
|
||||
};
|
||||
static_assert(
|
||||
sizeof(outputListener) >= sizeof(struct wl_output_listener),
|
||||
"sizeof(outputListener) is too small. Please report it to fastfetch github issue"
|
||||
);
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
return;
|
||||
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270: {
|
||||
int32_t temp = display.width;
|
||||
display.width = display.height;
|
||||
display.height = temp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t rotation;
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
rotation = 90;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
rotation = 180;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
rotation = 270;
|
||||
break;
|
||||
default:
|
||||
rotation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(wldata->result,
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
: display.description.length
|
||||
? &display.description
|
||||
: display.vendorAndModelId.length
|
||||
? &display.vendorAndModelId : &display.name,
|
||||
display.type,
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
ffStrbufDestroy(&display.description);
|
||||
ffStrbufDestroy(&display.vendorAndModelId);
|
||||
ffStrbufDestroy(&display.name);
|
||||
ffStrbufDestroy(&display.edidName);
|
||||
}
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
{
|
||||
WaylandData* wldata = data;
|
||||
|
||||
if(ffStrEquals(interface, wldata->ffwl_output_interface->name))
|
||||
waylandOutputHandler(wldata, registry, name, version);
|
||||
}
|
||||
|
||||
bool detectWayland(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
|
||||
|
||||
WaylandData data;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false)
|
||||
|
||||
data.display = ffwl_display_connect(NULL);
|
||||
if(data.display == NULL)
|
||||
return false;
|
||||
|
||||
waylandDetectWM(ffwl_display_get_fd(data.display), result);
|
||||
|
||||
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
|
||||
if(registry == NULL)
|
||||
{
|
||||
ffwl_display_disconnect(data.display);
|
||||
return false;
|
||||
}
|
||||
|
||||
data.result = result;
|
||||
|
||||
struct wl_registry_listener registry_listener = {
|
||||
.global = waylandGlobalAddListener,
|
||||
.global_remove = (void*) stubListener
|
||||
};
|
||||
|
||||
data.ffwl_proxy_add_listener(registry, (void(**)(void)) ®istry_listener, &data);
|
||||
ffwl_display_dispatch(data.display);
|
||||
data.ffwl_display_roundtrip(data.display);
|
||||
|
||||
data.ffwl_proxy_destroy(registry);
|
||||
ffwl_display_disconnect(data.display);
|
||||
|
||||
//We successfully connected to wayland and detected the display.
|
||||
//So we can set set the session type to wayland.
|
||||
//This is used as an indicator that we are running wayland by the x11 backends.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffdsConnectWayland(FFDisplayServerResult* result)
|
||||
{
|
||||
//Wayland requires this to be set
|
||||
if(getenv("XDG_RUNTIME_DIR") == NULL)
|
||||
return;
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
if(detectWayland(result))
|
||||
return;
|
||||
#endif
|
||||
|
||||
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
|
||||
|
||||
//If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session.
|
||||
if(xdgSessionType != NULL && strcasecmp(xdgSessionType, "wayland") != 0)
|
||||
return;
|
||||
|
||||
//If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY or WAYLAND_SOCKET is set.
|
||||
//If not, there is no indicator for a wayland session
|
||||
if(xdgSessionType == NULL && getenv("WAYLAND_DISPLAY") == NULL && getenv("WAYLAND_SOCKET") == NULL)
|
||||
return;
|
||||
|
||||
//We are probably running a wayland compositor at this point,
|
||||
//but fastfetch was compiled without the required library, or loading the library failed.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
#include "wayland.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||
return;
|
||||
|
||||
WaylandDisplay* display = data;
|
||||
display->width = width;
|
||||
display->height = height;
|
||||
display->refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->scale = scale;
|
||||
}
|
||||
|
||||
static void waylandOutputGeometryListener(void *data,
|
||||
FF_MAYBE_UNUSED struct wl_output *output,
|
||||
FF_MAYBE_UNUSED int32_t x,
|
||||
FF_MAYBE_UNUSED int32_t y,
|
||||
FF_MAYBE_UNUSED int32_t physical_width,
|
||||
FF_MAYBE_UNUSED int32_t physical_height,
|
||||
FF_MAYBE_UNUSED int32_t subpixel,
|
||||
FF_MAYBE_UNUSED const char *make,
|
||||
FF_MAYBE_UNUSED const char *model,
|
||||
int32_t transform)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->transform = (enum wl_output_transform) transform;
|
||||
}
|
||||
|
||||
void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
.name = ffStrbufCreate(),
|
||||
.description = ffStrbufCreate(),
|
||||
.edidName = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
// Dirty hack for #477
|
||||
// The order of these callbacks MUST follow `struct wl_output_listener`
|
||||
void* outputListener[] = {
|
||||
waylandOutputGeometryListener, // geometry
|
||||
waylandOutputModeListener, // mode
|
||||
stubListener, // done
|
||||
waylandOutputScaleListener, // scale
|
||||
ffWaylandOutputNameListener, // name
|
||||
ffWaylandOutputDescriptionListener, // description
|
||||
};
|
||||
static_assert(
|
||||
sizeof(outputListener) >= sizeof(struct wl_output_listener),
|
||||
"sizeof(outputListener) is too small. Please report it to fastfetch github issue"
|
||||
);
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
return;
|
||||
|
||||
uint32_t rotation;
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
rotation = 90;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
rotation = 180;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
rotation = 270;
|
||||
break;
|
||||
default:
|
||||
rotation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
case 90:
|
||||
case 270: {
|
||||
int32_t temp = display.width;
|
||||
display.width = display.height;
|
||||
display.height = temp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(wldata->result,
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
: display.description.length && !ffStrbufEndsWithS(&display.description, "-unknown")
|
||||
? &display.description
|
||||
: &display.name,
|
||||
display.type,
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
ffStrbufDestroy(&display.description);
|
||||
ffStrbufDestroy(&display.name);
|
||||
ffStrbufDestroy(&display.edidName);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "../displayserver_linux.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "wayland.h"
|
||||
#include "wlr-output-management-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
struct ucred ucred;
|
||||
socklen_t len = sizeof(struct ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
|
||||
return;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate();
|
||||
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
|
||||
ffReadFileBuffer(procPath.chars, &result->wmProcessName);
|
||||
ffStrbufTrimRightSpace(&result->wmProcessName);
|
||||
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
|
||||
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
|
||||
}
|
||||
#else
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_UNUSED(fd, result);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
{
|
||||
WaylandData* wldata = data;
|
||||
|
||||
if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL) && ffStrEquals(interface, wldata->ffwl_output_interface->name))
|
||||
{
|
||||
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_GLOBAL;
|
||||
ffWaylandHandleGlobalOutput(wldata, registry, name, version);
|
||||
}
|
||||
else if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_ZWLR) && ffStrEquals(interface, zwlr_output_manager_v1_interface.name))
|
||||
{
|
||||
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_ZWLR;
|
||||
ffWaylandHandleZwlrOutput(wldata, registry, name, version);
|
||||
}
|
||||
}
|
||||
|
||||
bool detectWayland(FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
|
||||
|
||||
WaylandData data = {};
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false)
|
||||
|
||||
data.display = ffwl_display_connect(NULL);
|
||||
if(data.display == NULL)
|
||||
return false;
|
||||
|
||||
waylandDetectWM(ffwl_display_get_fd(data.display), result);
|
||||
|
||||
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
|
||||
if(registry == NULL)
|
||||
{
|
||||
ffwl_display_disconnect(data.display);
|
||||
return false;
|
||||
}
|
||||
|
||||
data.result = result;
|
||||
|
||||
struct wl_registry_listener registry_listener = {
|
||||
.global = waylandGlobalAddListener,
|
||||
.global_remove = (void*) stubListener
|
||||
};
|
||||
|
||||
data.ffwl_proxy_add_listener(registry, (void(**)(void)) ®istry_listener, &data);
|
||||
data.ffwl_display_roundtrip(data.display);
|
||||
|
||||
data.ffwl_proxy_destroy(registry);
|
||||
ffwl_display_disconnect(data.display);
|
||||
|
||||
//We successfully connected to wayland and detected the display.
|
||||
//So we can set set the session type to wayland.
|
||||
//This is used as an indicator that we are running wayland by the x11 backends.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
if(ffStrStartsWith(name, "eDP-"))
|
||||
display->type = FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(ffStrStartsWith(name, "HDMI-"))
|
||||
display->type = FF_DISPLAY_TYPE_EXTERNAL;
|
||||
ffdsMatchDrmConnector(name, &display->edidName);
|
||||
ffStrbufAppendS(&display->name, name);
|
||||
}
|
||||
|
||||
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
while (*description == ' ') ++description;
|
||||
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)"))
|
||||
ffStrbufAppendS(&display->description, description);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffdsConnectWayland(FFDisplayServerResult* result)
|
||||
{
|
||||
//Wayland requires this to be set
|
||||
if(getenv("XDG_RUNTIME_DIR") == NULL)
|
||||
return;
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
if(detectWayland(result))
|
||||
return;
|
||||
#endif
|
||||
|
||||
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
|
||||
|
||||
//If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session.
|
||||
if(xdgSessionType != NULL && !ffStrEqualsIgnCase(xdgSessionType, "wayland"))
|
||||
return;
|
||||
|
||||
//If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY or WAYLAND_SOCKET is set.
|
||||
//If not, there is no indicator for a wayland session
|
||||
if(xdgSessionType == NULL && getenv("WAYLAND_DISPLAY") == NULL && getenv("WAYLAND_SOCKET") == NULL)
|
||||
return;
|
||||
|
||||
//We are probably running a wayland compositor at this point,
|
||||
//but fastfetch was compiled without the required library, or loading the library failed.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include "../displayserver_linux.h"
|
||||
|
||||
typedef enum WaylandProtocolType
|
||||
{
|
||||
FF_WAYLAND_PROTOCOL_TYPE_NONE,
|
||||
FF_WAYLAND_PROTOCOL_TYPE_GLOBAL,
|
||||
FF_WAYLAND_PROTOCOL_TYPE_ZWLR,
|
||||
} WaylandProtocolType;
|
||||
|
||||
typedef struct WaylandData
|
||||
{
|
||||
FFDisplayServerResult* result;
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
|
||||
FF_LIBRARY_SYMBOL(wl_display_roundtrip)
|
||||
struct wl_display* display;
|
||||
const struct wl_interface* ffwl_output_interface;
|
||||
WaylandProtocolType protocolType;
|
||||
} WaylandData;
|
||||
|
||||
typedef struct WaylandDisplay
|
||||
{
|
||||
WaylandData* parent;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
double scale;
|
||||
enum wl_output_transform transform;
|
||||
FFDisplayType type;
|
||||
FFstrbuf name;
|
||||
FFstrbuf description;
|
||||
FFstrbuf edidName;
|
||||
void* internal;
|
||||
} WaylandDisplay;
|
||||
|
||||
inline static void stubListener(void* data, ...)
|
||||
{
|
||||
(void) data;
|
||||
}
|
||||
|
||||
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name);
|
||||
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description);
|
||||
|
||||
void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
void ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
|
||||
#endif
|
||||
+1298
File diff suppressed because it is too large
Load Diff
+160
@@ -0,0 +1,160 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
/*
|
||||
* Copyright © 2019 Purism SPC
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this
|
||||
* software and its documentation for any purpose is hereby granted
|
||||
* without fee, provided that the above copyright notice appear in
|
||||
* all copies and that both that copyright notice and this permission
|
||||
* notice appear in supporting documentation, and that the name of
|
||||
* the copyright holders not be used in advertising or publicity
|
||||
* pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <wayland-util.h>
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
|
||||
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
||||
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
||||
#else
|
||||
#define WL_PRIVATE
|
||||
#endif
|
||||
|
||||
extern const struct wl_interface zwlr_output_configuration_head_v1_interface;
|
||||
extern const struct wl_interface zwlr_output_configuration_v1_interface;
|
||||
extern const struct wl_interface zwlr_output_head_v1_interface;
|
||||
extern const struct wl_interface zwlr_output_mode_v1_interface;
|
||||
|
||||
static const struct wl_interface *wlr_output_management_unstable_v1_types[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&zwlr_output_configuration_v1_interface,
|
||||
NULL,
|
||||
&zwlr_output_head_v1_interface,
|
||||
&zwlr_output_mode_v1_interface,
|
||||
&zwlr_output_mode_v1_interface,
|
||||
&zwlr_output_configuration_head_v1_interface,
|
||||
&zwlr_output_head_v1_interface,
|
||||
&zwlr_output_head_v1_interface,
|
||||
&zwlr_output_mode_v1_interface,
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_manager_v1_requests[] = {
|
||||
{ "create_configuration", "nu", wlr_output_management_unstable_v1_types + 3 },
|
||||
{ "stop", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_manager_v1_events[] = {
|
||||
{ "head", "n", wlr_output_management_unstable_v1_types + 5 },
|
||||
{ "done", "u", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zwlr_output_manager_v1_interface = {
|
||||
"zwlr_output_manager_v1", 4,
|
||||
2, zwlr_output_manager_v1_requests,
|
||||
3, zwlr_output_manager_v1_events,
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_head_v1_requests[] = {
|
||||
{ "release", "3", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_head_v1_events[] = {
|
||||
{ "name", "s", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "description", "s", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "physical_size", "ii", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "mode", "n", wlr_output_management_unstable_v1_types + 6 },
|
||||
{ "enabled", "i", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "current_mode", "o", wlr_output_management_unstable_v1_types + 7 },
|
||||
{ "position", "ii", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "transform", "i", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "scale", "f", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "make", "2s", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "model", "2s", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "serial_number", "2s", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zwlr_output_head_v1_interface = {
|
||||
"zwlr_output_head_v1", 4,
|
||||
1, zwlr_output_head_v1_requests,
|
||||
14, zwlr_output_head_v1_events,
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_mode_v1_requests[] = {
|
||||
{ "release", "3", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_mode_v1_events[] = {
|
||||
{ "size", "ii", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "refresh", "i", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "preferred", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zwlr_output_mode_v1_interface = {
|
||||
"zwlr_output_mode_v1", 3,
|
||||
1, zwlr_output_mode_v1_requests,
|
||||
4, zwlr_output_mode_v1_events,
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_configuration_v1_requests[] = {
|
||||
{ "enable_head", "no", wlr_output_management_unstable_v1_types + 8 },
|
||||
{ "disable_head", "o", wlr_output_management_unstable_v1_types + 10 },
|
||||
{ "apply", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "test", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "destroy", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_configuration_v1_events[] = {
|
||||
{ "succeeded", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "failed", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "cancelled", "", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zwlr_output_configuration_v1_interface = {
|
||||
"zwlr_output_configuration_v1", 4,
|
||||
5, zwlr_output_configuration_v1_requests,
|
||||
3, zwlr_output_configuration_v1_events,
|
||||
};
|
||||
|
||||
static const struct wl_message zwlr_output_configuration_head_v1_requests[] = {
|
||||
{ "set_mode", "o", wlr_output_management_unstable_v1_types + 11 },
|
||||
{ "set_custom_mode", "iii", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "set_position", "ii", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "set_transform", "i", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "set_scale", "f", wlr_output_management_unstable_v1_types + 0 },
|
||||
{ "set_adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zwlr_output_configuration_head_v1_interface = {
|
||||
"zwlr_output_configuration_head_v1", 4,
|
||||
6, zwlr_output_configuration_head_v1_requests,
|
||||
0, NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
#include "wayland.h"
|
||||
#include "wlr-output-management-unstable-v1-client-protocol.h"
|
||||
|
||||
static void waylandZwlrTransformListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, int32_t transform)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
wldata->transform = (enum wl_output_transform) transform;
|
||||
}
|
||||
|
||||
static void waylandZwlrScaleListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, wl_fixed_t scale)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
wldata->scale = wl_fixed_to_double(scale);
|
||||
}
|
||||
|
||||
typedef struct WaylandZwlrMode
|
||||
{
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
struct zwlr_output_mode_v1* pMode;
|
||||
} WaylandZwlrMode;
|
||||
|
||||
static void waylandZwlrSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t width, int32_t height)
|
||||
{
|
||||
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
|
||||
mode->width = width;
|
||||
mode->height = height;
|
||||
}
|
||||
|
||||
static void waylandZwlrRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t rate)
|
||||
{
|
||||
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
|
||||
mode->refreshRate = rate;
|
||||
}
|
||||
|
||||
static const struct zwlr_output_mode_v1_listener modeListener = {
|
||||
.size = waylandZwlrSizeListener,
|
||||
.refresh = waylandZwlrRefreshListener,
|
||||
.preferred = (void*) stubListener,
|
||||
.finished = (void*) stubListener,
|
||||
};
|
||||
|
||||
static void waylandZwlrModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, struct zwlr_output_mode_v1 *mode)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
WaylandZwlrMode* newMode = ffListAdd((FFlist*) wldata->internal);
|
||||
newMode->pMode = mode;
|
||||
|
||||
// Strangely, the listener is called only in this function, but not in `waylandZwlrCurrentModeListener`
|
||||
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
|
||||
}
|
||||
|
||||
static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, struct zwlr_output_mode_v1 *mode)
|
||||
{
|
||||
// waylandZwlrModeListener is always run before this
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
WaylandZwlrMode* current = NULL;
|
||||
FF_LIST_FOR_EACH(WaylandZwlrMode, m, *(FFlist*) wldata->internal)
|
||||
{
|
||||
if (m->pMode == mode)
|
||||
{
|
||||
current = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
wldata->width = current->width;
|
||||
wldata->height = current->height;
|
||||
wldata->refreshRate = current->refreshRate;
|
||||
}
|
||||
|
||||
static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output_manager_v1 *zwlr_output_manager_v1, struct zwlr_output_head_v1 *head)
|
||||
{
|
||||
WaylandData* wldata = data;
|
||||
|
||||
const struct zwlr_output_head_v1_listener headListener = {
|
||||
.name = (void*) ffWaylandOutputNameListener,
|
||||
.description = (void*) ffWaylandOutputDescriptionListener,
|
||||
.physical_size = (void*) stubListener,
|
||||
.mode = waylandZwlrModeListener,
|
||||
.enabled = (void*) stubListener,
|
||||
.current_mode = waylandZwlrCurrentModeListener,
|
||||
.position = (void*) stubListener,
|
||||
.transform = waylandZwlrTransformListener,
|
||||
.scale = waylandZwlrScaleListener,
|
||||
.finished = (void*) stubListener,
|
||||
.make = (void*) stubListener,
|
||||
.model = (void*) stubListener,
|
||||
.serial_number = (void*) stubListener,
|
||||
.adaptive_sync = (void*) stubListener,
|
||||
};
|
||||
|
||||
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandZwlrMode));
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
.name = ffStrbufCreate(),
|
||||
.description = ffStrbufCreate(),
|
||||
.edidName = ffStrbufCreate(),
|
||||
.internal = &modes,
|
||||
};
|
||||
|
||||
wldata->ffwl_proxy_add_listener((struct wl_proxy*) head, (void(**)(void)) &headListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
return;
|
||||
|
||||
uint32_t rotation;
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
rotation = 90;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
rotation = 180;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
rotation = 270;
|
||||
break;
|
||||
default:
|
||||
rotation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
case 90:
|
||||
case 270: {
|
||||
int32_t temp = display.width;
|
||||
display.width = display.height;
|
||||
display.height = temp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(wldata->result,
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale + 0.5),
|
||||
(uint32_t) (display.height / display.scale + 0.5),
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
: display.description.length
|
||||
? &display.description
|
||||
: &display.name,
|
||||
display.type,
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
ffStrbufDestroy(&display.description);
|
||||
ffStrbufDestroy(&display.name);
|
||||
ffStrbufDestroy(&display.edidName);
|
||||
|
||||
// These must be released manually
|
||||
FF_LIST_FOR_EACH(WaylandZwlrMode, m, modes)
|
||||
wldata->ffwl_proxy_destroy((void*) m->pMode);
|
||||
wldata->ffwl_proxy_destroy((void*) head);
|
||||
}
|
||||
|
||||
void ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &zwlr_output_manager_v1_interface, version, name, zwlr_output_manager_v1_interface.name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
const struct zwlr_output_manager_v1_listener outputListener = {
|
||||
.head = waylandHandleZwlrHead,
|
||||
.done = (void*) stubListener,
|
||||
.finished = (void*) stubListener,
|
||||
};
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, wldata);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -75,7 +75,9 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name)
|
||||
ffStrEqualsIgnCase(name, "kwin_wayland_wrapper") ||
|
||||
ffStrEqualsIgnCase(name, "kwin_x11") ||
|
||||
ffStrEqualsIgnCase(name, "kwin_x11_wrapper") ||
|
||||
ffStrEqualsIgnCase(name, "kwin")
|
||||
ffStrEqualsIgnCase(name, "kwin") ||
|
||||
ffStrEndsWithIgnCase(name, "-kwin_wayland") ||
|
||||
ffStrEndsWithIgnCase(name, "-kwin_x11")
|
||||
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN);
|
||||
else if(
|
||||
ffStrEqualsIgnCase(name, "gnome-shell") ||
|
||||
@@ -231,6 +233,13 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
|
||||
ffStrbufSetS(&result->deProcessName, "dtsession");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CDE);
|
||||
}
|
||||
|
||||
else if(
|
||||
ffStrEqualsIgnCase(name, "ukui-session")
|
||||
) {
|
||||
ffStrbufSetS(&result->deProcessName, "ukui-session");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_UKUI);
|
||||
}
|
||||
}
|
||||
|
||||
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
|
||||
|
||||
@@ -14,7 +14,7 @@ struct FFIgclData {
|
||||
FF_LIBRARY_SYMBOL(ctlEnumMemoryModules)
|
||||
FF_LIBRARY_SYMBOL(ctlMemoryGetState)
|
||||
FF_LIBRARY_SYMBOL(ctlEnumFrequencyDomains)
|
||||
FF_LIBRARY_SYMBOL(ctlFrequencyGetState)
|
||||
FF_LIBRARY_SYMBOL(ctlFrequencyGetProperties)
|
||||
|
||||
bool inited;
|
||||
ctl_api_handle_t apiHandle;
|
||||
@@ -44,7 +44,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumMemoryModules)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumFrequencyDomains)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetState)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetProperties)
|
||||
|
||||
if (ffctlInit(&(ctl_init_args_t) {
|
||||
.AppVersion = CTL_MAKE_VERSION(CTL_IMPL_MAJOR_VERSION, CTL_IMPL_MINOR_VERSION),
|
||||
@@ -177,22 +177,21 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
|
||||
|
||||
if (result.frequency)
|
||||
{
|
||||
ctl_freq_handle_t freqs[16];
|
||||
uint32_t freqCount = sizeof(freqs) / sizeof(freqs[0]);
|
||||
if (igclData.ffctlEnumFrequencyDomains(device, &freqCount, freqs) == CTL_RESULT_SUCCESS && freqCount > 0)
|
||||
ctl_freq_handle_t domains[16];
|
||||
uint32_t domainCount = sizeof(domains) / sizeof(domains[0]);
|
||||
if (igclData.ffctlEnumFrequencyDomains(device, &domainCount, domains) == CTL_RESULT_SUCCESS && domainCount > 0)
|
||||
{
|
||||
double sumValue = 0;
|
||||
uint32_t availableCount = 0;
|
||||
for (uint32_t iFreq = 0; iFreq < freqCount; iFreq++)
|
||||
double maxValue = 0;
|
||||
ctl_freq_properties_t props = { .Size = sizeof(props), .Version = 0 };
|
||||
for (uint32_t iDomain = 0; iDomain < domainCount; iDomain++)
|
||||
{
|
||||
ctl_freq_state_t state = { .Size = sizeof(state), .Version = 0 };
|
||||
if (igclData.ffctlFrequencyGetState(freqs[iFreq], &state) == CTL_RESULT_SUCCESS)
|
||||
if (igclData.ffctlFrequencyGetProperties(domains[iDomain], &props) == CTL_RESULT_SUCCESS)
|
||||
{
|
||||
sumValue += state.actual;
|
||||
availableCount++;
|
||||
if (props.type == CTL_FREQ_DOMAIN_GPU && props.max > maxValue)
|
||||
maxValue = props.max;
|
||||
}
|
||||
}
|
||||
*result.frequency = (sumValue / availableCount) / 1000.;
|
||||
*result.frequency = maxValue / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+269
-93
@@ -1,6 +1,7 @@
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "detection/cpu/cpu.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/stringUtils.h"
|
||||
@@ -14,22 +15,6 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
|
||||
{
|
||||
const FFlist* tempsResult = ffDetectTemps();
|
||||
|
||||
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
|
||||
{
|
||||
// FIXME: this code doesn't take multiGPUs into count
|
||||
//The kernel exposes the device class multiplied by 256 for some reason
|
||||
if(tempValue->deviceClass == deviceClass * 256)
|
||||
{
|
||||
gpu->temperature = tempValue->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufAppendS(pciDir, "/driver");
|
||||
@@ -54,12 +39,95 @@ static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer
|
||||
}
|
||||
}
|
||||
|
||||
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
// https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#mem-info-vis-vram-total
|
||||
const uint32_t pciDirLen = pciDir->length;
|
||||
|
||||
ffStrbufAppendS(pciDir, "/hwmon/");
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
|
||||
if (!dirp) return;
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
break;
|
||||
}
|
||||
if (!entry) return;
|
||||
ffStrbufAppendS(pciDir, entry->d_name);
|
||||
ffStrbufAppendC(pciDir, '/');
|
||||
|
||||
const uint32_t hwmonLen = pciDir->length;
|
||||
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
|
||||
if (ffPathExists(pciDir->chars, FF_PATHTYPE_FILE))
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
else
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
|
||||
uint64_t value = 0;
|
||||
if (options->temp)
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, hwmonLen);
|
||||
ffStrbufAppendS(pciDir, "temp1_input"); // The on die GPU temperature in millidegrees Celsius
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
gpu->temperature = (double) value / 1000;
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(pciDir, hwmonLen);
|
||||
ffStrbufAppendS(pciDir, "freq1_input"); // The gfx/compute clock in hertz
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
gpu->frequency = (double) value / (1000 * 1000 * 1000);
|
||||
|
||||
if (options->driverSpecific)
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
||||
gpu->dedicated.used = value;
|
||||
else
|
||||
gpu->shared.used = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
if (!ffStrbufEndsWithS(pciDir, "/device")) // Must be in `/sys/class/drm/cardN/device`
|
||||
return;
|
||||
|
||||
// Works for Intel GPUs
|
||||
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
|
||||
ffStrbufSetNS(buffer, pciDir->length - (uint32_t) strlen("device"), pciDir->chars);
|
||||
ffStrbufAppendS(buffer, "gt_max_freq_mhz");
|
||||
char str[16];
|
||||
ssize_t len = ffReadFileData(buffer->chars, sizeof(str) - 1, str);
|
||||
if (len > 1)
|
||||
{
|
||||
str[len] = '\0';
|
||||
gpu->frequency = (double) strtoul(str, NULL, 10) / 1000.0;
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(&gpu->name, "Intel "))
|
||||
ffStrbufSubstrAfter(&gpu->name, (uint32_t) strlen("Intel "));
|
||||
gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
{
|
||||
#ifdef FF_CUSTOM_PCI_IDS_PATH
|
||||
|
||||
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
@@ -70,95 +138,98 @@ static bool loadPciIds(FFstrbuf* pciids)
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir)
|
||||
{
|
||||
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
|
||||
const char* pciDirPath = "/sys/bus/pci/devices/";
|
||||
const uint32_t drmDirPathLength = drmDir->length;
|
||||
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
|
||||
uint8_t classId, subclassId;
|
||||
if (sscanf(buffer->chars + strlen("pci:"), "v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6)
|
||||
return "Invalid modalias string";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDirPath);
|
||||
if(dirp == NULL)
|
||||
return "Failed to open `/sys/bus/pci/devices/`";
|
||||
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
||||
return "Not a GPU device";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&pciDir, pciDirPath);
|
||||
char pciPath[PATH_MAX];
|
||||
ssize_t pathLength = readlink(drmDir->chars, pciPath, sizeof(pciPath) - 1);
|
||||
if (pathLength <= 0)
|
||||
return "Unable to get PCI device path";
|
||||
pciPath[pathLength] = '\0';
|
||||
const char* pPciPath = strrchr(pciPath, '/');
|
||||
if (pPciPath)
|
||||
pPciPath++;
|
||||
else
|
||||
pPciPath = pciPath;
|
||||
|
||||
const uint32_t pciBaseDirLength = pciDir.length;
|
||||
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
|
||||
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
||||
return "Invalid PCI device path";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_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 = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
||||
ffStrbufAppendS(&pciDir, entry->d_name);
|
||||
|
||||
const uint32_t pciDevDirLength = pciDir.length;
|
||||
|
||||
ffStrbufAppendS(&pciDir, "/modalias");
|
||||
if (!ffReadFileBuffer(pciDir.chars, &buffer))
|
||||
continue;
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
|
||||
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
|
||||
uint8_t classId, subclassId;
|
||||
if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6)
|
||||
continue;
|
||||
|
||||
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
||||
continue;
|
||||
|
||||
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
|
||||
if (sscanf(entry->d_name, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_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 = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffStrbufAppendS(drmDir, "/revision");
|
||||
if (ffReadFileBuffer(drmDir->chars, buffer))
|
||||
{
|
||||
ffStrbufAppendS(&pciDir, "/revision");
|
||||
if (ffReadFileBuffer(pciDir.chars, &buffer))
|
||||
char* pend;
|
||||
uint64_t revision = strtoul(buffer->chars, &pend, 16);
|
||||
if (pend != buffer->chars)
|
||||
{
|
||||
char* pend;
|
||||
uint64_t revision = strtoul(buffer.chars, &pend, 16);
|
||||
if (pend != buffer.chars)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
}
|
||||
char query[32];
|
||||
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
||||
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
|
||||
ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name);
|
||||
#else
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
#endif
|
||||
}
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
}
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
static FFstrbuf pciids;
|
||||
if (pciids.chars == NULL)
|
||||
{
|
||||
if (!pciids.length)
|
||||
loadPciIds(&pciids);
|
||||
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
ffStrbufInit(&pciids);
|
||||
loadPciIds(&pciids);
|
||||
}
|
||||
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
}
|
||||
|
||||
pciDetectDriver(gpu, &pciDir, &buffer);
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
pciDetectDriver(gpu, drmDir, buffer);
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
pciDetectAmdSpecific(options, gpu, drmDir, buffer);
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
pciDetectIntelSpecific(gpu, drmDir, buffer);
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
{
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
if (options->temp || options->driverSpecific)
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
@@ -175,16 +246,118 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
.type = &gpu->type,
|
||||
.frequency = &gpu->frequency,
|
||||
}, "libnvidia-ml.so");
|
||||
|
||||
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
|
||||
#ifdef __linux__
|
||||
if(options->temp && gpu->temperature != gpu->temperature)
|
||||
pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir)
|
||||
{
|
||||
uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t");
|
||||
if (index == buffer->length) return "display-subsystem?";
|
||||
index += (uint32_t) strlen("apple,agx-t");
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
gpu->deviceId = strtoul(buffer->chars + index, NULL, 10);
|
||||
ffStrbufInitStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId));
|
||||
ffStrbufInitStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
pciDetectDriver(gpu, drmDir, buffer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&drmDir, "/sys/class/drm/");
|
||||
const uint32_t drmDirLength = drmDir.length;
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(drmDir.chars);
|
||||
if(dir == NULL)
|
||||
return "Failed to open `/sys/class/drm/`";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (!ffStrStartsWith(entry->d_name, "card") ||
|
||||
strchr(entry->d_name + 4, '-') != NULL)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
|
||||
ffStrbufAppendS(&drmDir, "/device/modalias");
|
||||
if (!ffReadFileBuffer(drmDir.chars, &buffer))
|
||||
continue;
|
||||
ffStrbufSubstrBefore(&drmDir, drmDir.length - (uint32_t) strlen("/modalias"));
|
||||
|
||||
if (ffStrbufStartsWithS(&buffer, "pci:"))
|
||||
detectPci(options, gpus, &buffer, &drmDir);
|
||||
#ifdef __aarch64__
|
||||
else if (ffStrbufStartsWithS(&buffer, "of:"))
|
||||
detectAsahi(gpus, &buffer, &drmDir);
|
||||
#endif
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
|
||||
const char* pciDirPath = "/sys/bus/pci/devices/";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDirPath);
|
||||
if(dirp == NULL)
|
||||
return "Failed to open `/sys/bus/pci/devices/`";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&pciDir, pciDirPath);
|
||||
|
||||
const uint32_t pciBaseDirLength = pciDir.length;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
||||
ffStrbufAppendS(&pciDir, entry->d_name);
|
||||
const uint32_t pciDevDirLength = pciDir.length;
|
||||
|
||||
ffStrbufAppendS(&pciDir, "/modalias");
|
||||
if (!ffReadFileBuffer(pciDir.chars, &buffer))
|
||||
continue;
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
assert(ffStrbufStartsWithS(&buffer, "pci:"));
|
||||
|
||||
detectPci(options, gpus, &buffer, &pciDir);
|
||||
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -194,9 +367,12 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
|
||||
if (!ffGPUDetectByDirectX(options, gpus))
|
||||
if (ffGPUDetectByDirectX(options, gpus) == NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0)
|
||||
return NULL;
|
||||
|
||||
return pciDetectGPUs(options, gpus);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ struct FFNvmlData {
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetClockInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
|
||||
|
||||
bool inited;
|
||||
@@ -32,7 +32,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetClockInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
|
||||
|
||||
if (ffnvmlInit_v2() != NVML_SUCCESS)
|
||||
@@ -122,7 +122,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
if (result.frequency)
|
||||
{
|
||||
uint32_t clockMHz;
|
||||
if (nvmlData.ffnvmlDeviceGetClockInfo(device, NVML_CLOCK_GRAPHICS, &clockMHz) == NVML_SUCCESS)
|
||||
if (nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, &clockMHz) == NVML_SUCCESS)
|
||||
*result.frequency = clockMHz / 1000.;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,20 +78,12 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
ffStrbufAppendF(&host->name, " - %s", wslDistroName);
|
||||
ffStrbufAppendS(&host->family, "WSL");
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY wslVer = ffStrbufCreate(); //Wide characters
|
||||
if(!ffProcessAppendStdOut(&wslVer, (char* const[]){
|
||||
"wsl.exe",
|
||||
"--version",
|
||||
NULL
|
||||
}) && wslVer.length > 0)
|
||||
{
|
||||
ffStrbufSubstrBeforeFirstC(&wslVer, '\r'); //CRLF
|
||||
ffStrbufSubstrAfterLastC(&wslVer, ' ');
|
||||
for(uint32_t i = 0; i < wslVer.length; ++i) {
|
||||
if(wslVer.chars[i]) //don't append \0
|
||||
ffStrbufAppendC(&host->version, wslVer.chars[i]);
|
||||
}
|
||||
}
|
||||
ffProcessAppendStdOut(&host->version, (char* const[]){
|
||||
"wslinfo",
|
||||
"--wsl-version",
|
||||
"-n",
|
||||
NULL,
|
||||
}); // supported in 2.2.3 and later
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+81
-21
@@ -2,11 +2,15 @@
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
static inline bool allRelevantValuesSet(const FFOSResult* result)
|
||||
{
|
||||
return result->id.length > 0
|
||||
@@ -15,18 +19,25 @@ static inline bool allRelevantValuesSet(const FFOSResult* result)
|
||||
;
|
||||
}
|
||||
|
||||
static bool parseFile(const char* fileName, FFOSResult* result)
|
||||
static bool parseLsbRelease(const char* fileName, FFOSResult* result)
|
||||
{
|
||||
return ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
|
||||
{"NAME =", &result->name},
|
||||
{"DISTRIB_DESCRIPTION =", &result->prettyName},
|
||||
{"PRETTY_NAME =", &result->prettyName},
|
||||
return ffParsePropFileValues(fileName, 4, (FFpropquery[]) {
|
||||
{"DISTRIB_ID =", &result->id},
|
||||
{"DISTRIB_DESCRIPTION =", &result->prettyName},
|
||||
{"DISTRIB_RELEASE =", &result->version},
|
||||
{"DISTRIB_CODENAME =", &result->codename},
|
||||
});
|
||||
}
|
||||
|
||||
static bool parseOsRelease(const char* fileName, FFOSResult* result)
|
||||
{
|
||||
return ffParsePropFileValues(fileName, 10, (FFpropquery[]) {
|
||||
{"PRETTY_NAME =", &result->prettyName},
|
||||
{"NAME =", &result->name},
|
||||
{"ID =", &result->id},
|
||||
{"ID_LIKE =", &result->idLike},
|
||||
{"VARIANT =", &result->variant},
|
||||
{"VARIANT_ID =", &result->variantID},
|
||||
{"DISTRIB_RELEASE =", &result->version},
|
||||
{"VERSION =", &result->version},
|
||||
{"VERSION_ID =", &result->versionID},
|
||||
{"VERSION_CODENAME =", &result->codename},
|
||||
@@ -132,15 +143,48 @@ static void getDebianVersion(FFOSResult* result)
|
||||
ffStrbufSet(&result->versionID, &debianVersion);
|
||||
}
|
||||
|
||||
static bool detectDebianDerived(FFOSResult* result)
|
||||
{
|
||||
if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Armbian 24.2.1 bookworm
|
||||
{
|
||||
ffStrbufSetS(&result->name, "Armbian");
|
||||
ffStrbufSetS(&result->id, "armbian");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufClear(&result->versionID);
|
||||
uint32_t versionStart = ffStrbufFirstIndexC(&result->prettyName, ' ') + 1;
|
||||
uint32_t versionEnd = ffStrbufNextIndexC(&result->prettyName, versionStart, ' ');
|
||||
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
|
||||
return true;
|
||||
}
|
||||
else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "pve");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "Proxmox VE");
|
||||
ffStrbufClear(&result->versionID);
|
||||
if (ffProcessAppendStdOut(&result->versionID, (char* const[]) {
|
||||
"/usr/bin/pveversion",
|
||||
NULL,
|
||||
}) == NULL) // pve-manager/8.2.2/9355359cd7afbae4 (running kernel: 6.8.4-2-pve)
|
||||
{
|
||||
ffStrbufSubstrBeforeLastC(&result->versionID, '/');
|
||||
ffStrbufSubstrAfterFirstC(&result->versionID, '/');
|
||||
}
|
||||
ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectOS(FFOSResult* os)
|
||||
{
|
||||
if(instance.config.general.osFile.length > 0)
|
||||
{
|
||||
parseFile(instance.config.general.osFile.chars, os);
|
||||
return;
|
||||
}
|
||||
#ifdef FF_CUSTOM_OS_RELEASE_PATH
|
||||
parseOsRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os);
|
||||
parseLsbRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os);
|
||||
return;
|
||||
#endif
|
||||
|
||||
if(instance.config.general.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
|
||||
if(instance.config.general.escapeBedrock && parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os))
|
||||
{
|
||||
if(os->id.length == 0)
|
||||
ffStrbufAppendS(&os->id, "bedrock");
|
||||
@@ -151,18 +195,31 @@ static void detectOS(FFOSResult* os)
|
||||
if(os->prettyName.length == 0)
|
||||
ffStrbufAppendS(&os->prettyName, "Bedrock Linux");
|
||||
|
||||
return;
|
||||
if(parseOsRelease("/bedrock" FASTFETCH_TARGET_DIR_ETC "/os-release", os) && allRelevantValuesSet(os))
|
||||
return;
|
||||
}
|
||||
|
||||
parseFile(FASTFETCH_TARGET_DIR_ETC"/os-release", os);
|
||||
if(allRelevantValuesSet(os))
|
||||
// Refer: https://gist.github.com/natefoo/814c5bf936922dad97ff
|
||||
|
||||
// Hack for MX Linux. See #847
|
||||
if(parseLsbRelease(FASTFETCH_TARGET_DIR_ETC "/lsb-release", os))
|
||||
{
|
||||
if (ffStrbufEqualS(&os->id, "MX"))
|
||||
{
|
||||
ffStrbufSetStatic(&os->name, "MX");
|
||||
ffStrbufSetStatic(&os->idLike, "debian");
|
||||
return;
|
||||
}
|
||||
|
||||
// For archlinux
|
||||
if (ffStrbufEqualS(&os->version, "rolling"))
|
||||
ffStrbufClear(&os->version);
|
||||
}
|
||||
|
||||
if(parseOsRelease(FASTFETCH_TARGET_DIR_ETC "/os-release", os) && allRelevantValuesSet(os))
|
||||
return;
|
||||
|
||||
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", os);
|
||||
if(allRelevantValuesSet(os))
|
||||
return;
|
||||
|
||||
parseFile(FASTFETCH_TARGET_DIR_ETC"/lsb-release", os);
|
||||
parseOsRelease(FASTFETCH_TARGET_DIR_USR "/lib/os-release", os);
|
||||
}
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os)
|
||||
@@ -172,5 +229,8 @@ void ffDetectOSImpl(FFOSResult* os)
|
||||
if(ffStrbufIgnCaseEqualS(&os->id, "ubuntu"))
|
||||
getUbuntuFlavour(os);
|
||||
else if(ffStrbufIgnCaseEqualS(&os->id, "debian"))
|
||||
getDebianVersion(os);
|
||||
{
|
||||
if (!detectDebianDerived(os))
|
||||
getDebianVersion(os);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ typedef struct FFPackagesResult
|
||||
uint32_t rpm;
|
||||
uint32_t scoop;
|
||||
uint32_t snap;
|
||||
uint32_t sorcery;
|
||||
uint32_t winget;
|
||||
uint32_t xbps;
|
||||
|
||||
|
||||
@@ -118,28 +118,146 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons
|
||||
return sum;
|
||||
}
|
||||
|
||||
static bool isValidNixPkg(FFstrbuf* pkg)
|
||||
{
|
||||
if (!ffPathExists(pkg->chars, FF_PATHTYPE_DIRECTORY))
|
||||
return false;
|
||||
|
||||
ffStrbufSubstrAfterLastC(pkg, '/');
|
||||
if (
|
||||
ffStrbufStartsWithS(pkg, "nixos-system-nixos-") ||
|
||||
ffStrbufEndsWithS(pkg, "-doc") ||
|
||||
ffStrbufEndsWithS(pkg, "-man") ||
|
||||
ffStrbufEndsWithS(pkg, "-info") ||
|
||||
ffStrbufEndsWithS(pkg, "-dev") ||
|
||||
ffStrbufEndsWithS(pkg, "-bin")
|
||||
) return false;
|
||||
|
||||
enum { START, DIGIT, DOT, MATCH } state = START;
|
||||
|
||||
for (uint32_t i = 0; i < pkg->length; i++)
|
||||
{
|
||||
char c = pkg->chars[i];
|
||||
switch (state)
|
||||
{
|
||||
case START:
|
||||
if (c >= '0' && c <= '9')
|
||||
state = DIGIT;
|
||||
break;
|
||||
case DIGIT:
|
||||
if (c >= '0' && c <= '9')
|
||||
continue;
|
||||
if (c == '.')
|
||||
state = DOT;
|
||||
else
|
||||
state = START;
|
||||
break;
|
||||
case DOT:
|
||||
if (c >= '0' && c <= '9')
|
||||
state = MATCH;
|
||||
else
|
||||
state = START;
|
||||
break;
|
||||
case MATCH:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return state == MATCH;
|
||||
}
|
||||
|
||||
static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count)
|
||||
{
|
||||
if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE))
|
||||
return false;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreate();
|
||||
if (!ffReadFileBuffer(cacheDir->chars, &cacheContent))
|
||||
return false;
|
||||
|
||||
// Format: <hash>\n<count>
|
||||
uint32_t split = ffStrbufFirstIndexC(&cacheContent, '\n');
|
||||
if (split == cacheContent.length)
|
||||
return false;
|
||||
|
||||
ffStrbufSetNS(hash, split, cacheContent.chars);
|
||||
*count = (uint32_t)atoi(cacheContent.chars + split + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool writeNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t count)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreateCopy(hash);
|
||||
ffStrbufAppendF(&cacheContent, "\n%u", count);
|
||||
return ffWriteFileBuffer(cacheDir->chars, &cacheContent);
|
||||
}
|
||||
|
||||
static uint32_t getNixPackagesImpl(char* path)
|
||||
{
|
||||
//Nix detection is kinda slow, so we only do it if the dir exists
|
||||
if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY))
|
||||
return 0;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(128);
|
||||
FF_STRBUF_AUTO_DESTROY cacheDir = ffStrbufCreateCopy(&instance.state.platform.cacheDir);
|
||||
ffStrbufEnsureEndsWithC(&cacheDir, '/');
|
||||
ffStrbufAppendS(&cacheDir, "fastfetch/packages/nix");
|
||||
ffStrbufAppendS(&cacheDir, path);
|
||||
|
||||
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(255);
|
||||
ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq | wc -l");
|
||||
//Check the hash first to determine if we need to recompute the count
|
||||
FF_STRBUF_AUTO_DESTROY hash = ffStrbufCreateA(64);
|
||||
FF_STRBUF_AUTO_DESTROY cacheHash = ffStrbufCreateA(64);
|
||||
uint32_t count = 0;
|
||||
|
||||
ffProcessAppendStdOut(&output, (char* const[]) {
|
||||
"sh",
|
||||
"-c",
|
||||
command.chars,
|
||||
ffProcessAppendStdOut(&hash, (char* const[]) {
|
||||
"nix-store",
|
||||
"--query",
|
||||
"--hash",
|
||||
path,
|
||||
NULL
|
||||
});
|
||||
|
||||
return (uint32_t) strtol(output.chars, NULL, 10);
|
||||
if (checkNixCache(&cacheDir, &cacheHash, &count) && ffStrbufEqual(&hash, &cacheHash))
|
||||
return count;
|
||||
|
||||
//Cache is invalid, recompute the count
|
||||
count = 0;
|
||||
|
||||
//Implementation based on bash script from here:
|
||||
//https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024);
|
||||
|
||||
ffProcessAppendStdOut(&output, (char* const[]) {
|
||||
"nix-store",
|
||||
"--query",
|
||||
"--requisites",
|
||||
path,
|
||||
NULL
|
||||
});
|
||||
|
||||
uint32_t lineLength = 0;
|
||||
for (uint32_t i = 0; i < output.length; i++)
|
||||
{
|
||||
if (output.chars[i] != '\n')
|
||||
{
|
||||
lineLength++;
|
||||
continue;
|
||||
}
|
||||
|
||||
output.chars[i] = '\0';
|
||||
FFstrbuf line = {
|
||||
.allocated = 0,
|
||||
.length = lineLength,
|
||||
.chars = output.chars + i - lineLength
|
||||
};
|
||||
if (isValidNixPkg(&line))
|
||||
count++;
|
||||
lineLength = 0;
|
||||
}
|
||||
|
||||
writeNixCache(&cacheDir, &hash, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
|
||||
@@ -315,6 +433,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PALUDIS_BIT)) packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_OPKG_BIT)) packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->am = getAM(baseDir);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_SORCERY_BIT)) packageCounts->sorcery += getNumStrings(baseDir, "/var/state/sorcery/packages", ":installed:");
|
||||
}
|
||||
|
||||
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
|
||||
@@ -383,7 +502,36 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
{
|
||||
// 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");
|
||||
}
|
||||
// check if $XDG_STATE_HOME/nix/profile exists
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY stateDir = ffStrbufCreate();
|
||||
const char* stateHome = getenv("XDG_STATE_HOME");
|
||||
if(ffStrSet(stateHome))
|
||||
{
|
||||
ffStrbufSetS(&stateDir, stateHome);
|
||||
ffStrbufEnsureEndsWithC(&stateDir, '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSet(&stateDir, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&stateDir, ".local/state/");
|
||||
}
|
||||
|
||||
ffStrbufSet(&profilePath, &stateDir);
|
||||
ffStrbufAppendS(&profilePath, "nix/profile");
|
||||
result->nixUser = getNixPackages(&stateDir, "nix/profile");
|
||||
}
|
||||
}
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
|
||||
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ void ffPreparePublicIp(FFPublicIpOptions* options)
|
||||
fputs("Error: only http: protocol is supported. Use `Command` module with `curl` if needed\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
ffStrbufSubstrAfter(&host, hostStartIndex + (strlen("://") - 1));
|
||||
ffStrbufSubstrAfter(&host, hostStartIndex + (uint32_t) (strlen("://") - 1));
|
||||
}
|
||||
uint32_t pathStartIndex = ffStrbufFirstIndexC(&host, '/');
|
||||
|
||||
|
||||
@@ -7,20 +7,11 @@
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
{
|
||||
ULONG size = sizeof(SYSTEM_PAGEFILE_INFORMATION);
|
||||
SYSTEM_PAGEFILE_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PAGEFILE_INFORMATION*)malloc(size);
|
||||
while(true)
|
||||
{
|
||||
NTSTATUS status = NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size);
|
||||
if(status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
if(!(pstart = (SYSTEM_PAGEFILE_INFORMATION*)realloc(pstart, size)))
|
||||
return "realloc(pstart, size) failed";
|
||||
}
|
||||
else if(!NT_SUCCESS(status))
|
||||
return "NtQuerySystemInformation(SystemPagefileInformation, size) failed";
|
||||
break;
|
||||
}
|
||||
uint8_t buffer[1024];
|
||||
ULONG size = sizeof(buffer);
|
||||
SYSTEM_PAGEFILE_INFORMATION* pstart = (SYSTEM_PAGEFILE_INFORMATION*) buffer;
|
||||
if(!NT_SUCCESS(NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size)))
|
||||
return "NtQuerySystemInformation(SystemPagefileInformation, size) failed";
|
||||
|
||||
uint32_t pageSize = instance.state.platform.pageSize;
|
||||
swap->bytesUsed = (uint64_t)pstart->TotalUsed * pageSize;
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <paths.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -223,7 +226,12 @@ static bool getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf*
|
||||
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
|
||||
{
|
||||
if(strcasecmp(exeName, "bash") == 0 || strcasecmp(exeName, "sh") == 0)
|
||||
if (!instance.config.display.tsVersion) return false;
|
||||
|
||||
if(ffStrEqualsIgnCase(exeName, "sh")) // #849
|
||||
return false;
|
||||
|
||||
if(strcasecmp(exeName, "bash") == 0)
|
||||
return getShellVersionBash(exe, version);
|
||||
if(strcasecmp(exeName, "zsh") == 0)
|
||||
return getExeVersionGeneral(exe, version); //zsh 5.9 (arm-apple-darwin21.3.0)
|
||||
@@ -469,6 +477,42 @@ static bool getTerminalVersionZellij(FFstrbuf* exe, FFstrbuf* version)
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
// kitty is written in python. `kitty --version` can be expensive
|
||||
char buffer[1024] = {};
|
||||
if (
|
||||
#ifdef __linux__
|
||||
ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) ||
|
||||
ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer)
|
||||
#else
|
||||
ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Starts from version 0.17.0
|
||||
// https://github.com/kovidgoyal/kitty/blob/master/kitty/constants.py#L25
|
||||
const char* p = memmem(buffer, sizeof(buffer) - 1, "version: Version = Version(", strlen("version: Version = Version("));
|
||||
if (p)
|
||||
{
|
||||
p += strlen("version: Version = Version(");
|
||||
int major, minor, patch;
|
||||
if (sscanf(p, "%d,%d,%d", &major, &minor, &patch) == 3)
|
||||
{
|
||||
ffStrbufSetF(version, "%d.%d.%d", major, minor, patch);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//kitty 0.21.2 created by Kovid Goyal
|
||||
return getExeVersionGeneral(exe, version);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
|
||||
@@ -500,6 +544,8 @@ static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
|
||||
|
||||
bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if (!instance.config.display.tsVersion) return false;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
if(ffStrbufEqualS(processName, "com.termux"))
|
||||
@@ -576,7 +622,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
#ifndef _WIN32
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "kitty"))
|
||||
return getExeVersionGeneral(exe, version); //kitty 0.21.2 created by Kovid Goyal
|
||||
return getTerminalVersionKitty(exe, version);
|
||||
|
||||
if (ffStrbufIgnCaseEqualS(processName, "Tabby") && getExeVersionRaw(exe, version))
|
||||
return true;
|
||||
|
||||
@@ -214,31 +214,44 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
|
||||
pid_t ppid = 0;
|
||||
int32_t tty = -1;
|
||||
|
||||
const char* userShellName = NULL;
|
||||
{
|
||||
uint32_t index = ffStrbufLastIndexC(&instance.state.platform.userShell, '/');
|
||||
if (index == instance.state.platform.userShell.length)
|
||||
userShellName = instance.state.platform.userShell.chars;
|
||||
else
|
||||
userShellName = instance.state.platform.userShell.chars + index + 1;
|
||||
}
|
||||
|
||||
while (getProcessNameAndPpid(pid, name, &ppid, &tty) == NULL)
|
||||
{
|
||||
//Common programs that are between terminal and own process, but are not the shell
|
||||
if(
|
||||
// tty < 0 || //A shell should connect to a tty
|
||||
ffStrEquals(name, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell
|
||||
ffStrEquals(name, "sudo") ||
|
||||
ffStrEquals(name, "su") ||
|
||||
ffStrEquals(name, "strace") ||
|
||||
ffStrEquals(name, "sshd") ||
|
||||
ffStrEquals(name, "gdb") ||
|
||||
ffStrEquals(name, "lldb") ||
|
||||
ffStrEquals(name, "lldb-mi") ||
|
||||
ffStrEquals(name, "login") ||
|
||||
ffStrEquals(name, "ltrace") ||
|
||||
ffStrEquals(name, "perf") ||
|
||||
ffStrEquals(name, "guake-wrapped") ||
|
||||
ffStrEquals(name, "time") ||
|
||||
ffStrContainsIgnCase(name, "debug") ||
|
||||
ffStrContainsIgnCase(name, "not-found") ||
|
||||
ffStrEndsWith(name, ".sh")
|
||||
)
|
||||
if (!ffStrEquals(userShellName, name))
|
||||
{
|
||||
pid = ppid;
|
||||
continue;
|
||||
//Common programs that are between terminal and own process, but are not the shell
|
||||
if(
|
||||
// tty < 0 || //A shell should connect to a tty
|
||||
ffStrEquals(name, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell
|
||||
ffStrEquals(name, "sudo") ||
|
||||
ffStrEquals(name, "su") ||
|
||||
ffStrEquals(name, "strace") ||
|
||||
ffStrEquals(name, "sshd") ||
|
||||
ffStrEquals(name, "gdb") ||
|
||||
ffStrEquals(name, "lldb") ||
|
||||
ffStrEquals(name, "lldb-mi") ||
|
||||
ffStrEquals(name, "login") ||
|
||||
ffStrEquals(name, "ltrace") ||
|
||||
ffStrEquals(name, "perf") ||
|
||||
ffStrEquals(name, "guake-wrapped") ||
|
||||
ffStrEquals(name, "time") ||
|
||||
ffStrEquals(name, "hyfetch") || //when hyfetch uses fastfetch as backend
|
||||
ffStrContainsIgnCase(name, "debug") ||
|
||||
ffStrContainsIgnCase(name, "not-found") ||
|
||||
ffStrEndsWith(name, ".sh")
|
||||
)
|
||||
{
|
||||
pid = ppid;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result->pid = (uint32_t) pid;
|
||||
@@ -470,14 +483,12 @@ static void setShellInfoDetails(FFShellResult* result)
|
||||
|
||||
static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
{
|
||||
if(result->exeName[0] == '.' && ffStrEndsWith(result->exeName, "-wrapped"))
|
||||
if(ffStrbufStartsWithC(&result->processName, '.') && ffStrbufEndsWithS(&result->processName, "-wrapped"))
|
||||
{
|
||||
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
|
||||
// We use processName when detecting version and font, overriding it for simplification
|
||||
ffStrbufSetNS(
|
||||
&result->processName,
|
||||
(uint32_t) (strlen(result->exeName) - strlen(".-wrapped")),
|
||||
result->exeName + 1);
|
||||
ffStrbufSubstrBefore(&result->processName, result->processName.length - (uint32_t) strlen("-wrapped"));
|
||||
ffStrbufSubstrAfter(&result->processName, 0);
|
||||
}
|
||||
|
||||
if(ffStrbufEqualS(&result->processName, "wezterm-gui"))
|
||||
@@ -508,6 +519,11 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
|
||||
else if(ffStrbufEqualS(&result->processName, "iTerm.app") || ffStrbufStartsWithS(&result->processName, "iTermServer-"))
|
||||
ffStrbufInitStatic(&result->prettyName, "iTerm");
|
||||
else if(ffStrbufEndsWithS(&result->exePath, "Terminal.app/Contents/MacOS/Terminal"))
|
||||
{
|
||||
ffStrbufSetStatic(&result->processName, "Apple_Terminal"); // for terminal font detection
|
||||
ffStrbufInitStatic(&result->prettyName, "Apple Terminal");
|
||||
}
|
||||
else if(ffStrbufEqualS(&result->processName, "Apple_Terminal"))
|
||||
ffStrbufInitStatic(&result->prettyName, "Apple Terminal");
|
||||
else if(ffStrbufEqualS(&result->processName, "WarpTerminal"))
|
||||
|
||||
@@ -104,6 +104,7 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || // scoop warps the real binaries with a "shim" exe
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") ||
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "hyfetch") || // uses fastfetch as backend
|
||||
ffStrbufContainIgnCaseS(&result->prettyName, "debug") ||
|
||||
ffStrbufContainIgnCaseS(&result->prettyName, "time") ||
|
||||
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014
|
||||
|
||||
@@ -337,7 +337,8 @@ static const char* detectWifiWithIoctls(FFlist* result)
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
#ifdef FF_HAVE_LIBNM
|
||||
if(!detectWifiWithLibnm(result))
|
||||
detectWifiWithLibnm(result);
|
||||
if(result->length) // NetworkManager not enabled? #811
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
|
||||
+32
-33
@@ -249,7 +249,7 @@ static void printCommandHelp(const char* command)
|
||||
puts(FASTFETCH_DATATEXT_HELP_COLOR);
|
||||
else if(ffStrEqualsIgnCase(command, "format"))
|
||||
puts(FASTFETCH_DATATEXT_HELP_FORMAT);
|
||||
else if(isalpha(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // <module>-format
|
||||
else if(ffCharIsEnglishAlphabet(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // <module>-format
|
||||
printCommandFormatHelp(command);
|
||||
else if(!printSpecificCommandHelp(command))
|
||||
fprintf(stderr, "Error: No specific help for command '%s' provided\n", command);
|
||||
@@ -321,21 +321,42 @@ static void parseOption(FFdata* data, const char* key, const char* value);
|
||||
|
||||
static bool parseJsoncFile(const char* path)
|
||||
{
|
||||
yyjson_read_err error;
|
||||
yyjson_doc* doc = yyjson_read_file(path, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, &error);
|
||||
if (!doc)
|
||||
assert(!instance.state.configDoc);
|
||||
|
||||
{
|
||||
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
|
||||
yyjson_read_err error;
|
||||
instance.state.configDoc = yyjson_read_file(path, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, &error);
|
||||
if (!instance.state.configDoc)
|
||||
{
|
||||
fprintf(stderr, "Error: failed to parse JSON config file `%s` at pos %zu: %s\n", path, error.pos, error.msg);
|
||||
if (error.code != YYJSON_READ_ERROR_FILE_OPEN)
|
||||
{
|
||||
fprintf(stderr, "Error: failed to parse JSON config file `%s` at pos %zu: %s\n", path, error.pos, error.msg);
|
||||
exit(477);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
if (!yyjson_is_obj(root))
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
if (
|
||||
error ||
|
||||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
|
||||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
|
||||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
|
||||
(error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) ||
|
||||
false
|
||||
) {
|
||||
fprintf(stderr, "JsonConfig Error: %s\n", error);
|
||||
exit(477);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (instance.state.configDoc)
|
||||
yyjson_doc_free(instance.state.configDoc); // for `--load-config`
|
||||
|
||||
instance.state.configDoc = doc;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -779,27 +800,6 @@ static void parseArguments(FFdata* data, int argc, char** argv, void (*parser)(F
|
||||
|
||||
static void run(FFdata* data)
|
||||
{
|
||||
if (instance.state.configDoc)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
if (!yyjson_is_obj(root))
|
||||
error = "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
if (
|
||||
error ||
|
||||
(error = ffOptionsParseLogoJsonConfig(&instance.config.logo, root)) ||
|
||||
(error = ffOptionsParseGeneralJsonConfig(&instance.config.general, root)) ||
|
||||
(error = ffOptionsParseDisplayJsonConfig(&instance.config.display, root)) ||
|
||||
(error = ffOptionsParseLibraryJsonConfig(&instance.config.library, root)) ||
|
||||
false
|
||||
) {
|
||||
fprintf(stderr, "JsonConfig Error: %s\n", error);
|
||||
exit(477);
|
||||
}
|
||||
}
|
||||
|
||||
const bool useJsonConfig = data->structure.length == 0 && instance.state.configDoc;
|
||||
|
||||
if (useJsonConfig)
|
||||
@@ -863,6 +863,7 @@ static void writeConfigFile(FFdata* data, const FFstrbuf* filename)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ffInitInstance();
|
||||
atexit(ffDestroyInstance);
|
||||
|
||||
//Data stores things only needed for the configuration of fastfetch
|
||||
FFdata data = {
|
||||
@@ -888,6 +889,4 @@ int main(int argc, char** argv)
|
||||
ffStrbufDestroy(&customValue->value);
|
||||
}
|
||||
ffListDestroy(&data.customValues);
|
||||
|
||||
ffDestroyInstance();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
..
|
||||
`:]x**j-,'
|
||||
.,+t***********z\<"
|
||||
?******************;
|
||||
'*n` .'`^,;;,^`'. ,cc.
|
||||
-<. .[l
|
||||
// ^^ ^^ \\
|
||||
!^ $2^^$1 ":
|
||||
'tt}` $2!~]rj_$1 ")t/.
|
||||
Itttt?' $2~~]rr]$1 `{tttt,
|
||||
\tttttt!""I$2_]r($1"""~tttttt1
|
||||
'_tttttttttttt$2)f$1tttttttttttti.
|
||||
\*ztttttttttttttttttttttttttf**[
|
||||
l**c)tttttttttttttttttttttttt(z**,
|
||||
.z*x.`tttttttttttttttttttttttt.`u*n
|
||||
>` (tttttttttttttttttttttt] "I
|
||||
,tttttttttttttttttttttt`
|
||||
./ttttt$2f$1tttttttt$2f$1ttttt(
|
||||
'I)$2))(\()($1tt$2))|\()($1{;'
|
||||
$2.~~~~~~~|)~~~~~~~<$1
|
||||
'$2[)))))1$1|($2)))))))$1?
|
||||
$2",,," ",,,^
|
||||
@@ -0,0 +1,14 @@
|
||||
█ █ █ █ █ █ █ █ █ █ █
|
||||
███████████████████████
|
||||
▄▄██ ██▄▄
|
||||
▄▄██ ███████████ ██▄▄
|
||||
▄▄██ ██ ██ ██▄▄
|
||||
▄▄██ ██ ██ ██▄▄
|
||||
▄▄██ ██ ██ ██▄▄
|
||||
▄▄██ █████████████ ██▄▄
|
||||
▄▄██ ██ ██ ██▄▄
|
||||
▄▄██ ██ ██ ██▄▄
|
||||
▄▄██ ██ ██ ██▄▄
|
||||
▄▄██ ██▄▄
|
||||
███████████████████████
|
||||
█ █ █ █ █ █ █ █ █ █ █
|
||||
@@ -0,0 +1,19 @@
|
||||
.''''....''''.
|
||||
.''... ...''.
|
||||
''.. ..''
|
||||
'.. ..''
|
||||
.'. .,,'.. .',,,' ..'.
|
||||
.'. .,,,,' .,,,,,' .'.
|
||||
.'. .,,,,' .,,,,,. .'.
|
||||
'.. .,,,,'',,,,;. .''
|
||||
.'. .,,,,,,,;;. ..'
|
||||
.'. .,,,,;;;;;${c2}, ${c1}..'.
|
||||
'.. .,;;;,${c2}';;;;;, ${c1}..'
|
||||
.'. .;;${c2};;' .;;:::: ${c1}.,.
|
||||
'.. ${c2}.;;;;' .::::::. ${c1}.,'
|
||||
'.. ${c2}.;;;;' .::::::. ${c1}.,${c2}'${c1}
|
||||
.'.. ${c2}.',.
|
||||
${c1}',.. ${c2}.','
|
||||
${c1}.,,... ${c2}..',,.
|
||||
..,,''........',,,.
|
||||
......
|
||||
@@ -0,0 +1,18 @@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@@@@@@@@@@@%*+--:------=+*%@@@@@@@@@@@@
|
||||
@@@@@@@@@#=. .-+#%@@@@@%#*+--=#@@@@@@@@@
|
||||
@@@@@@@+. .=%@@@@@@@@@@@@@@@@*-:+@@@@@@@
|
||||
@@@@@*. *@@@@@@@@@@@@@@@@@@@@@%-.*@@@@@
|
||||
@@@@- -@@@@@@@@@@@@@@@@@@@@@@@#: -@@@@
|
||||
@@@: -@@@@@@@=.*@@@@@@@@@@@@%- = :@@@
|
||||
@@= .@@@@@@@@%- :%@@@@@@@@@+ -%@# =@@
|
||||
@% +@@@@@@@@@@#. =@@@@@@*. .*@@@@. %@
|
||||
@+ *@@@@@@*..*@@+ *@@%- =@@@@@@- +@
|
||||
@= *@@@@%- -%@@- := -%@@@@@@@: +@
|
||||
@+ :@@@= +@@= .#@@@@@@@@% *@
|
||||
@% +*. .: *@@#: +@@: @@
|
||||
@@+ :%@- :- :: +@@
|
||||
@@@- .=@@= -@@@
|
||||
@@+. . +@@
|
||||
%=..:.................::...........:..-%
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@ -18,4 +18,3 @@
|
||||
.:ooooooolc:. .ooooooooooo'
|
||||
.':loooooo; ,oooooooooc
|
||||
..';::c' .;loooo:'
|
||||
.
|
||||
+57
-11
@@ -209,6 +209,7 @@ static const FFlogo A[] = {
|
||||
// AoscOsRetro_small
|
||||
{
|
||||
.names = {"Aosc OS/Retro_small", "aoscosretro_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_AOSCOSRETRO_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
@@ -375,6 +376,24 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_CYAN,
|
||||
.colorTitle = FF_COLOR_FG_CYAN,
|
||||
},
|
||||
// Armbian
|
||||
{
|
||||
.names = {"Armbian"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ARMBIAN,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_RED,
|
||||
},
|
||||
},
|
||||
// Armbian2
|
||||
{
|
||||
.names = {"Armbian2"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ARMBIAN2,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
},
|
||||
},
|
||||
// Artix
|
||||
{
|
||||
.names = {"artix", "artixlinux", "artix-linux"},
|
||||
@@ -764,6 +783,7 @@ static const FFlogo C[] = {
|
||||
// CalinixOSSmall
|
||||
{
|
||||
.names = {"Calinix_small", "calinixos_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_CALINIXOS_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
@@ -875,7 +895,7 @@ static const FFlogo C[] = {
|
||||
// Chimera Linux
|
||||
{
|
||||
.names = {"Chimera Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_CHIMERALINUX,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_CHIMERA_LINUX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
@@ -1241,9 +1261,9 @@ static const FFlogo D[] = {
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Drauger
|
||||
// DraugerOS
|
||||
{
|
||||
.names = {"Drauger"},
|
||||
.names = {"DraugerOS", "Drauger"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_DRAUGER,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
@@ -1336,8 +1356,8 @@ static const FFlogo E[] = {
|
||||
// EndeavourSmall
|
||||
{
|
||||
.names = {"Endeavour_small", "endeavour-linux_small", "endeavouros_small", "endeavouros-linux_small"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL,
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
@@ -1823,6 +1843,7 @@ static const FFlogo G[] = {
|
||||
// GuixSmall
|
||||
{
|
||||
.names = {"Guix_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_GUIX_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
@@ -2089,6 +2110,15 @@ static const FFlogo K[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// KernelOS
|
||||
{
|
||||
.names = {"KernelOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_KERNELOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
}
|
||||
},
|
||||
// KDENeon
|
||||
{
|
||||
.names = {"KDE", "kde-neon"},
|
||||
@@ -2462,6 +2492,7 @@ static const FFlogo M[] = {
|
||||
// MageiaSmall
|
||||
{
|
||||
.names = {"Mageia_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_MAGEIA_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_CYAN,
|
||||
@@ -2649,7 +2680,7 @@ static const FFlogo M[] = {
|
||||
},
|
||||
// MX
|
||||
{
|
||||
.names = {"MX"},
|
||||
.names = {"MX", "MX Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_MX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
@@ -2659,7 +2690,8 @@ static const FFlogo M[] = {
|
||||
},
|
||||
// MXSmall
|
||||
{
|
||||
.names = {"MX_small", "mx-small"},
|
||||
.names = {"MX_small", "mx linux_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_MX_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
@@ -2667,6 +2699,17 @@ static const FFlogo M[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_CYAN,
|
||||
},
|
||||
// MX2
|
||||
{
|
||||
.names = {"MX2"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_MX2,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_CYAN,
|
||||
},
|
||||
// LAST
|
||||
{},
|
||||
};
|
||||
@@ -2730,6 +2773,7 @@ static const FFlogo N[] = {
|
||||
// NixOSSmall
|
||||
{
|
||||
.names = {"NixOS_small", "nix_small", "nixos-linux-small", "nix-linux-small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_NIXOS_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
@@ -2962,7 +3006,7 @@ static const FFlogo O[] = {
|
||||
},
|
||||
// OpenMandriva
|
||||
{
|
||||
.names = {"openmandriva", "open-mandriva", "open_mandriva"},
|
||||
.names = {"openmandriva", "open-mandriva", "open_mandriva", "openmandriva lx"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OPENMANDRIVA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
@@ -3301,6 +3345,7 @@ static const FFlogo P[] = {
|
||||
// PostMarketOSSmall
|
||||
{
|
||||
.names = {"PostMarketOS_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_POSTMARKETOS_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
@@ -3309,7 +3354,7 @@ static const FFlogo P[] = {
|
||||
},
|
||||
// Proxmox
|
||||
{
|
||||
.names = {"proxmox"},
|
||||
.names = {"Proxmox", "pve"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_PROXMOX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
@@ -3560,6 +3605,7 @@ static const FFlogo R[] = {
|
||||
// RockyLinuxSmall
|
||||
{
|
||||
.names = {"rocky_small", "rocky-linux_small", "rockylinux_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ROCKY_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
@@ -3791,14 +3837,14 @@ static const FFlogo S[] = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// SourceMage
|
||||
// Source Mage
|
||||
{
|
||||
.names = {"Source Mage", "source_mage"},
|
||||
.names = {"Source Mage", "Source Mage GNU/Linux", "source_mage", "sourcemage"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_SOURCE_MAGE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Solaris
|
||||
|
||||
+32
-7
@@ -1,6 +1,7 @@
|
||||
#include "image.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/printing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
@@ -53,13 +54,14 @@ static FFstrbuf base64Encode(const FFstrbuf* in)
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool printImageIterm(void)
|
||||
static bool printImageIterm(bool printError)
|
||||
{
|
||||
const FFOptionsLogo* options = &instance.config.logo;
|
||||
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
|
||||
if(!ffAppendFileBuffer(options->source.chars, &buf))
|
||||
{
|
||||
fputs("Logo: Failed to load image file\n", stderr);
|
||||
if (printError)
|
||||
fputs("Logo (iterm): Failed to load image file\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -134,9 +136,17 @@ static bool printImageIterm(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool printImageKittyDirect(void)
|
||||
static bool printImageKittyDirect(bool printError)
|
||||
{
|
||||
const FFOptionsLogo* options = &instance.config.logo;
|
||||
|
||||
if (!ffPathExists(options->source.chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
if (printError)
|
||||
fputs("Logo (kitty-direct): Failed to load image file\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&options->source);
|
||||
|
||||
if (!options->width || !options->height)
|
||||
@@ -771,7 +781,7 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
|
||||
if(!getCharacterPixelDimensions(&requestData))
|
||||
{
|
||||
if(printError)
|
||||
fputs("Logo: getCharacterPixelDimensions() failed", stderr);
|
||||
fputs("Logo: getCharacterPixelDimensions() failed\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -788,7 +798,7 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
|
||||
//We can safely return here, because if realpath failed, we surely won't be able to read the file
|
||||
ffStrbufDestroy(&requestData.cacheDir);
|
||||
if(printError)
|
||||
fputs("Logo: Querying realpath of the image source failed", stderr);
|
||||
fputs("Logo: Querying realpath of the image source failed\n", stderr);
|
||||
return false;
|
||||
}
|
||||
ffStrbufRecalculateLength(&requestData.cacheDir);
|
||||
@@ -832,6 +842,13 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
|
||||
|
||||
bool ffLogoPrintImageIfExists(FFLogoType type, bool printError)
|
||||
{
|
||||
if(instance.config.display.pipe)
|
||||
{
|
||||
if(printError)
|
||||
fputs("Logo: Image logo is not supported in pipe mode\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ffPathExists(instance.config.logo.source.chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
if(printError)
|
||||
@@ -839,11 +856,19 @@ bool ffLogoPrintImageIfExists(FFLogoType type, bool printError)
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* term = getenv("TERM");
|
||||
if((term && ffStrEquals(term, "screen")) || getenv("ZELLIJ"))
|
||||
{
|
||||
if(printError)
|
||||
fputs("Logo: Image logo is not supported in terminal multiplexers\n", stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(type == FF_LOGO_TYPE_IMAGE_ITERM)
|
||||
return printImageIterm();
|
||||
return printImageIterm(printError);
|
||||
|
||||
if(type == FF_LOGO_TYPE_IMAGE_KITTY_DIRECT)
|
||||
return printImageKittyDirect();
|
||||
return printImageKittyDirect(printError);
|
||||
|
||||
#if !defined(FF_HAVE_CHAFA)
|
||||
if(type == FF_LOGO_TYPE_IMAGE_CHAFA)
|
||||
|
||||
+26
-16
@@ -61,7 +61,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048);
|
||||
|
||||
if (instance.config.display.brightColor)
|
||||
if (!instance.config.display.pipe && instance.config.display.brightColor)
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT);
|
||||
|
||||
ffStrbufAppendNC(&result, options->paddingTop, '\n');
|
||||
@@ -70,7 +70,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
|
||||
instance.state.logoHeight = options->paddingTop;
|
||||
|
||||
//Use logoColor[0] as the default color
|
||||
if(doColorReplacement)
|
||||
if(doColorReplacement && !instance.config.display.pipe)
|
||||
ffStrbufAppendF(&result, "\e[%sm", options->colors[0].chars);
|
||||
|
||||
while(*data != '\0')
|
||||
@@ -143,19 +143,27 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
|
||||
continue;
|
||||
}
|
||||
|
||||
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
|
||||
int index = ((int) *data) - 49;
|
||||
|
||||
//If the index is valid, print the color. Otherwise continue as normal
|
||||
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
|
||||
if(!instance.config.display.pipe)
|
||||
{
|
||||
ffStrbufAppendC(&result, '$');
|
||||
++currentlineLength;
|
||||
//Don't continue here, we want to print the current char as unicode
|
||||
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
|
||||
int index = ((int) *data) - 49;
|
||||
|
||||
//If the index is valid, print the color. Otherwise continue as normal
|
||||
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
|
||||
{
|
||||
ffStrbufAppendC(&result, '$');
|
||||
++currentlineLength;
|
||||
//Don't continue here, we want to print the current char as unicode
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars);
|
||||
++data;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars);
|
||||
++data;
|
||||
continue;
|
||||
}
|
||||
@@ -188,7 +196,8 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement)
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
if(!instance.config.display.pipe)
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
|
||||
if(!options->separate)
|
||||
{
|
||||
@@ -393,7 +402,8 @@ static bool logoPrintFileIfExists(bool doColorReplacement, bool raw)
|
||||
: !ffAppendFileBuffer(options->source.chars, &content)
|
||||
)
|
||||
{
|
||||
fprintf(stderr, "Logo: Failed to load file content from logo source: %s \n", options->source.chars);
|
||||
if (instance.config.display.showErrors)
|
||||
fprintf(stderr, "Logo: Failed to load file content from logo source: %s \n", options->source.chars);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -448,7 +458,7 @@ static bool logoTryKnownType(void)
|
||||
if(options->type == FF_LOGO_TYPE_IMAGE_RAW)
|
||||
return logoPrintFileIfExists(false, true);
|
||||
|
||||
return logoPrintImageIfExists(options->type, true);
|
||||
return logoPrintImageIfExists(options->type, instance.config.display.showErrors);
|
||||
}
|
||||
|
||||
static void logoPrintKnownType(void)
|
||||
@@ -459,10 +469,10 @@ static void logoPrintKnownType(void)
|
||||
|
||||
void ffLogoPrint(void)
|
||||
{
|
||||
//In pipe mode, we don't have a logo or padding.
|
||||
//When generate JSON result, we don't have a logo or padding.
|
||||
//We also don't need to set main color, because it won't be printed anyway.
|
||||
//So we can return quickly here.
|
||||
if(instance.config.display.pipe || instance.state.resultDoc)
|
||||
if(instance.state.resultDoc)
|
||||
{
|
||||
instance.state.logoHeight = 0;
|
||||
instance.state.logoWidth = 0;
|
||||
|
||||
@@ -84,23 +84,28 @@ void ffPrintBattery(FFBatteryOptions* options)
|
||||
if (error)
|
||||
{
|
||||
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return;
|
||||
}
|
||||
else
|
||||
if(results.length == 0)
|
||||
{
|
||||
for(uint8_t i = 0; i < (uint8_t) results.length; i++)
|
||||
{
|
||||
FFBatteryResult* result = ffListGet(&results, i);
|
||||
printBattery(options, result, i);
|
||||
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found");
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result->manufacturer);
|
||||
ffStrbufDestroy(&result->modelName);
|
||||
ffStrbufDestroy(&result->technology);
|
||||
ffStrbufDestroy(&result->status);
|
||||
ffStrbufDestroy(&result->serial);
|
||||
ffStrbufDestroy(&result->manufactureDate);
|
||||
}
|
||||
if(results.length == 0)
|
||||
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No batteries found");
|
||||
for(uint32_t i = 0; i < results.length; i++)
|
||||
{
|
||||
FFBatteryResult* result = ffListGet(&results, i);
|
||||
printBattery(options, result, (uint8_t) i);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFBatteryResult, result, results)
|
||||
{
|
||||
ffStrbufDestroy(&result->manufacturer);
|
||||
ffStrbufDestroy(&result->modelName);
|
||||
ffStrbufDestroy(&result->technology);
|
||||
ffStrbufDestroy(&result->status);
|
||||
ffStrbufDestroy(&result->serial);
|
||||
ffStrbufDestroy(&result->manufactureDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,19 +150,17 @@ void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options,
|
||||
yyjson_mut_obj_add_str(doc, module, "error", error);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
|
||||
FF_LIST_FOR_EACH(FFBluetoothResult, item, results)
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "battery", item->battery);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "connected", item->connected);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "type", &item->type);
|
||||
}
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
|
||||
FF_LIST_FOR_EACH(FFBluetoothResult, item, results)
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "battery", item->battery);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "connected", item->connected);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "type", &item->type);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFBluetoothResult, device, results)
|
||||
|
||||
@@ -154,12 +154,6 @@ void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options
|
||||
return;
|
||||
}
|
||||
|
||||
if(result.length == 0)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "No result is detected.");
|
||||
return;
|
||||
}
|
||||
|
||||
yyjson_mut_val* arr = yyjson_mut_arr(doc);
|
||||
yyjson_mut_obj_add_val(doc, module, "result", arr);
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@ static inline uint8_t max(uint8_t a, uint8_t b)
|
||||
|
||||
void ffPrintColors(FFColorsOptions* options)
|
||||
{
|
||||
if(instance.config.display.pipe)
|
||||
return;
|
||||
|
||||
bool flag = false;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(128);
|
||||
@@ -28,7 +25,8 @@ void ffPrintColors(FFColorsOptions* options)
|
||||
// 3%d: Set the foreground color
|
||||
for(uint8_t i = options->block.range[0]; i <= min(options->block.range[1], 7); i++)
|
||||
{
|
||||
ffStrbufAppendF(&result, "\e[3%dm", i);
|
||||
if(!instance.config.display.pipe)
|
||||
ffStrbufAppendF(&result, "\e[3%dm", i);
|
||||
for (uint8_t j = 0; j < options->block.width; j++)
|
||||
ffStrbufAppendS(&result, "█");
|
||||
}
|
||||
@@ -40,7 +38,8 @@ void ffPrintColors(FFColorsOptions* options)
|
||||
if(options->paddingLeft > 0)
|
||||
ffPrintCharTimes(' ', options->paddingLeft);
|
||||
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
if(!instance.config.display.pipe)
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
ffStrbufClear(&result);
|
||||
}
|
||||
@@ -49,7 +48,8 @@ void ffPrintColors(FFColorsOptions* options)
|
||||
// 9%d: Set the foreground to the bright color
|
||||
for(uint8_t i = max(options->block.range[0], 8); i <= options->block.range[1]; i++)
|
||||
{
|
||||
ffStrbufAppendF(&result, "\e[1;9%dm", i - 8);
|
||||
if(!instance.config.display.pipe)
|
||||
ffStrbufAppendF(&result, "\e[1;9%dm", i - 8);
|
||||
for (uint8_t j = 0; j < options->block.width; j++)
|
||||
ffStrbufAppendS(&result, "█");
|
||||
}
|
||||
@@ -82,7 +82,8 @@ void ffPrintColors(FFColorsOptions* options)
|
||||
|
||||
if(options->paddingLeft > 0)
|
||||
ffPrintCharTimes(' ', options->paddingLeft);
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
if(!instance.config.display.pipe)
|
||||
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,10 @@
|
||||
|
||||
void ffPrintCustom(FFCustomOptions* options)
|
||||
{
|
||||
if (options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "output format must be set for custom module");
|
||||
return;
|
||||
}
|
||||
|
||||
ffPrintLogoAndKey(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufWriteTo(&options->moduleArgs.outputFormat, stdout);
|
||||
puts(FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
if(!instance.config.display.pipe)
|
||||
puts(FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
bool ffParseCustomCommandOptions(FFCustomOptions* options, const char* key, const char* value)
|
||||
|
||||
@@ -152,7 +152,7 @@ void ffGenerateDateTimeJsonConfig(FFDateTimeOptions* options, yyjson_mut_doc* do
|
||||
|
||||
void ffGenerateDateTimeJsonResult(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
yyjson_mut_obj_add_uint(doc, module, "result", ffTimeGetNow());
|
||||
yyjson_mut_obj_add_strcpy(doc, module, "result", ffTimeToFullStr(ffTimeGetNow()));
|
||||
}
|
||||
|
||||
void ffPrintDateTimeHelpFormat(void)
|
||||
|
||||
+9
-52
@@ -131,54 +131,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
|
||||
}
|
||||
}
|
||||
|
||||
static void printMountpoint(FFDiskOptions* options, const FFlist* disks, const char* mountpoint)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
|
||||
{
|
||||
if(ffStrbufEqualS(&disk->mountpoint, mountpoint))
|
||||
{
|
||||
printDisk(options, disk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disk found for mountpoint: %s", mountpoint);
|
||||
}
|
||||
|
||||
static void printMountpoints(FFDiskOptions* options, const FFlist* disks)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char separator = ';';
|
||||
#else
|
||||
const char separator = ':';
|
||||
#endif
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY mountpoints = ffStrbufCreateCopy(&options->folders);
|
||||
ffStrbufTrim(&mountpoints, separator);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < mountpoints.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&mountpoints, startIndex, separator);
|
||||
mountpoints.chars[colonIndex] = '\0';
|
||||
|
||||
printMountpoint(options, disks, mountpoints.chars + startIndex);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void printAutodetected(FFDiskOptions* options, const FFlist* disks)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
|
||||
{
|
||||
if(disk->type & ~options->showTypes)
|
||||
continue;
|
||||
|
||||
printDisk(options, disk);
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintDisk(FFDiskOptions* options)
|
||||
{
|
||||
FF_LIST_AUTO_DESTROY disks = ffListCreate(sizeof (FFDisk));
|
||||
@@ -190,10 +142,13 @@ void ffPrintDisk(FFDiskOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(options->folders.length == 0)
|
||||
printAutodetected(options, &disks);
|
||||
else
|
||||
printMountpoints(options, &disks);
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, disks)
|
||||
{
|
||||
if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes))
|
||||
continue;
|
||||
|
||||
printDisk(options, disk);
|
||||
}
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, disks)
|
||||
@@ -451,6 +406,8 @@ void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso
|
||||
yyjson_mut_arr_add_str(doc, typeArr, "Hidden");
|
||||
if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT)
|
||||
yyjson_mut_arr_add_str(doc, typeArr, "Read-only");
|
||||
if(item->type & FF_DISK_VOLUME_TYPE_UNKNOWN_BIT)
|
||||
yyjson_mut_arr_add_str(doc, typeArr, "Unknown");
|
||||
|
||||
const char* pstr = ffTimeToFullStr(item->createTime);
|
||||
if (*pstr)
|
||||
|
||||
@@ -279,6 +279,7 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect display");
|
||||
return;
|
||||
}
|
||||
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
FF_LIST_FOR_EACH(FFDisplayResult, item, dsResult->displays)
|
||||
{
|
||||
|
||||
@@ -118,12 +118,6 @@ void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
|
||||
return;
|
||||
}
|
||||
|
||||
if(!result.length)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "No devices detected");
|
||||
return;
|
||||
}
|
||||
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
|
||||
{
|
||||
|
||||
@@ -334,13 +334,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs
|
||||
if(error)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(results.length == 0)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Failed to detect any IPs");
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
@@ -354,7 +348,6 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name);
|
||||
}
|
||||
|
||||
exit:
|
||||
FF_LIST_FOR_EACH(FFLocalIpResult, ip, results)
|
||||
{
|
||||
ffStrbufDestroy(&ip->name);
|
||||
|
||||
+1
-9
@@ -22,7 +22,7 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
|
||||
ffStrbufAppend(result, &instance.state.platform.systemName);
|
||||
|
||||
//Append code name if it is missing
|
||||
if(os->codename.length > 0 && !ffStrbufContain(result, &os->versionID))
|
||||
if(os->codename.length > 0 && !ffStrbufContain(result, &os->codename))
|
||||
{
|
||||
ffStrbufAppendC(result, ' ');
|
||||
ffStrbufAppend(result, &os->codename);
|
||||
@@ -40,14 +40,6 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
|
||||
ffStrbufAppend(result, &os->version);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
if(os->buildID.length > 0)
|
||||
{
|
||||
ffStrbufAppendC(result, ' ');
|
||||
ffStrbufAppend(result, &os->buildID);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Append variant if it is missing
|
||||
if(os->variant.length > 0 && ffStrbufFirstIndex(result, &os->variant) == result->length)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef enum FFPackagesFlags
|
||||
FF_PACKAGES_FLAG_WINGET_BIT = 1 << 17,
|
||||
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
|
||||
FF_PACKAGES_FLAG_AM_BIT = 1 << 19,
|
||||
FF_PACKAGES_FLAG_SORCERY_BIT = 1 << 20,
|
||||
} FFPackagesFlags;
|
||||
|
||||
typedef struct FFPackagesOptions
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "modules/packages/packages.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 26
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 30
|
||||
|
||||
void ffPrintPackages(FFPackagesOptions* options)
|
||||
{
|
||||
@@ -65,11 +65,15 @@ void ffPrintPackages(FFPackagesOptions* options)
|
||||
FF_PRINT_PACKAGE(winget)
|
||||
FF_PRINT_PACKAGE(opkg)
|
||||
FF_PRINT_PACKAGE(am)
|
||||
FF_PRINT_PACKAGE(sorcery)
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t nixAll = counts.nixDefault + counts.nixSystem + counts.nixUser;
|
||||
uint32_t flatpakAll = counts.flatpakSystem + counts.flatpakUser;
|
||||
uint32_t brewAll = counts.brew + counts.brewCask;
|
||||
FF_PRINT_FORMAT_CHECKED(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_PACKAGES_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.all},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.pacman},
|
||||
@@ -97,6 +101,10 @@ void ffPrintPackages(FFPackagesOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.winget},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.opkg},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.am},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.sorcery},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &nixAll},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &flatpakAll},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &brewAll},
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -166,6 +174,7 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
|
||||
case 'S': if (false);
|
||||
FF_TEST_PACKAGE_NAME(SCOOP)
|
||||
FF_TEST_PACKAGE_NAME(SNAP)
|
||||
FF_TEST_PACKAGE_NAME(SORCERY)
|
||||
break;
|
||||
case 'W': if (false);
|
||||
FF_TEST_PACKAGE_NAME(WINGET)
|
||||
@@ -266,6 +275,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
|
||||
case 'S': if (false);
|
||||
FF_TEST_PACKAGE_NAME(SCOOP)
|
||||
FF_TEST_PACKAGE_NAME(SNAP)
|
||||
FF_TEST_PACKAGE_NAME(SORCERY)
|
||||
break;
|
||||
case 'W': if (false);
|
||||
FF_TEST_PACKAGE_NAME(WINGET)
|
||||
@@ -316,6 +326,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
|
||||
FF_TEST_PACKAGE_NAME(WINGET)
|
||||
FF_TEST_PACKAGE_NAME(XBPS)
|
||||
FF_TEST_PACKAGE_NAME(AM)
|
||||
FF_TEST_PACKAGE_NAME(SORCERY)
|
||||
#undef FF_TEST_PACKAGE_NAME
|
||||
}
|
||||
}
|
||||
@@ -362,12 +373,13 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
|
||||
FF_APPEND_PACKAGE_COUNT(xbps)
|
||||
FF_APPEND_PACKAGE_COUNT(opkg)
|
||||
FF_APPEND_PACKAGE_COUNT(am)
|
||||
FF_APPEND_PACKAGE_COUNT(sorcery)
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch);
|
||||
}
|
||||
|
||||
void ffPrintPackagesHelpFormat(void)
|
||||
{
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Number of all packages",
|
||||
"Number of pacman packages",
|
||||
"Pacman branch on manjaro",
|
||||
@@ -394,6 +406,10 @@ void ffPrintPackagesHelpFormat(void)
|
||||
"Number of winget packages",
|
||||
"Number of opkg packages",
|
||||
"Number of am packages",
|
||||
"Number of sorcery packages",
|
||||
"Total number of all nix packages",
|
||||
"Total number of all flatpak packages",
|
||||
"Total number of all brew packages",
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,6 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options)
|
||||
ffTempsAppendNum(dev->temperature, &tempStr, options->tempConfig);
|
||||
if (dev->type & FF_PHYSICALDISK_TYPE_READWRITE)
|
||||
readOnlyType = "Read-write";
|
||||
ffParseSize(dev->size, &buffer);
|
||||
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_PHYSICALDISK_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &buffer},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &dev->name},
|
||||
@@ -118,7 +117,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_STRING, removableType},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, readOnlyType},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &dev->revision},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &tempStr},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr},
|
||||
}));
|
||||
}
|
||||
++index;
|
||||
@@ -252,7 +251,7 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut
|
||||
|
||||
void ffPrintPhysicalDiskHelpFormat(void)
|
||||
{
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PHYSICALDISK_MODULE_NAME, "{1}", FF_PHYSICALDISK_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PHYSICALDISK_MODULE_NAME, "{1} [{6}, {7}, {8}]", FF_PHYSICALDISK_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Device size (formatted)",
|
||||
"Device name",
|
||||
"Device interconnect type",
|
||||
|
||||
@@ -101,24 +101,28 @@ void ffGeneratePowerAdapterJsonResult(FF_MAYBE_UNUSED FFPowerAdapterOptions* opt
|
||||
if (error)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", error);
|
||||
return;
|
||||
}
|
||||
else if(results.length == 0)
|
||||
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "No power adapters found");
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "description", &item->description);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &item->manufacturer);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &item->modelName);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &item->serial);
|
||||
yyjson_mut_obj_add_int(doc, obj, "watts", item->watts);
|
||||
}
|
||||
else
|
||||
|
||||
FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results)
|
||||
{
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results)
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "description", &item->description);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &item->manufacturer);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &item->modelName);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &item->serial);
|
||||
yyjson_mut_obj_add_int(doc, obj, "watts", item->watts);
|
||||
}
|
||||
ffStrbufDestroy(&item->manufacturer);
|
||||
ffStrbufDestroy(&item->description);
|
||||
ffStrbufDestroy(&item->modelName);
|
||||
ffStrbufDestroy(&item->name);
|
||||
ffStrbufDestroy(&item->serial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,20 @@ static inline uint32_t max(uint32_t a, uint32_t b)
|
||||
|
||||
static inline uint32_t getWcsWidth(const FFstrbuf* mbstr, wchar_t* wstr, mbstate_t* state)
|
||||
{
|
||||
int result = 1;
|
||||
for (uint32_t i = 0; i < mbstr->length; i++)
|
||||
{
|
||||
if (!isascii(mbstr->chars[i]))
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__builtin_expect(result, 1)) return mbstr->length;
|
||||
|
||||
const char* str = mbstr->chars;
|
||||
uint32_t wstrLength = (uint32_t) mbsrtowcs(wstr, &str, mbstr->length, state);
|
||||
int result = mk_wcswidth(wstr, wstrLength);
|
||||
result = mk_wcswidth(wstr, wstrLength);
|
||||
return result > 0 ? (uint32_t) result : mbstr->length;
|
||||
}
|
||||
|
||||
@@ -32,9 +43,9 @@ void ffPrintSeparator(FFSeparatorOptions* options)
|
||||
+ (fqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name
|
||||
ffLogoPrintLine();
|
||||
|
||||
if(options->string.length == 0)
|
||||
if(__builtin_expect(options->string.length == 1, 1))
|
||||
{
|
||||
ffPrintCharTimes('-', titleLength);
|
||||
ffPrintCharTimes(options->string.chars[0], titleLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -131,7 +142,7 @@ void ffInitSeparatorOptions(FFSeparatorOptions* options)
|
||||
NULL,
|
||||
ffGenerateSeparatorJsonConfig
|
||||
);
|
||||
ffStrbufInit(&options->string);
|
||||
ffStrbufInitStatic(&options->string, "-");
|
||||
}
|
||||
|
||||
void ffDestroySeparatorOptions(FFSeparatorOptions* options)
|
||||
|
||||
@@ -8,6 +8,4 @@ typedef struct FFShellOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
bool version;
|
||||
} FFShellOptions;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user