mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
280 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6769410753 | |||
| 40b9af6c36 | |||
| e63dfdd8b1 | |||
| a6639d7211 | |||
| 3e251f602a | |||
| ec25ca9fc7 | |||
| 396d20f2da | |||
| 49181fd0bf | |||
| 5eb1dbe7bf | |||
| 690e988cab | |||
| fd41770d6e | |||
| fb26cb1394 | |||
| 4e4efa67e6 | |||
| 0dfb1b6bb1 | |||
| bcbca38b1e | |||
| 3f0ccf802c | |||
| 691cb4ac24 | |||
| 282939f548 | |||
| 6f35b2f382 | |||
| 6700f63091 | |||
| 5c37ebec70 | |||
| 28a419d252 | |||
| 95128ee95f | |||
| c94180b3d2 | |||
| 12ca1a0cf7 | |||
| 67564dfa2c | |||
| a1e79a9522 | |||
| e16f8ef349 | |||
| fd1a2072b3 | |||
| aa45e70910 | |||
| 5374feb24b | |||
| 12ac0ac7a9 | |||
| 3d78666ed3 | |||
| dd2cc116bd | |||
| ba2636dc1a | |||
| 69589f1ad5 | |||
| 39da11de8e | |||
| 8b7a4daeda | |||
| 82af7a5b52 | |||
| a2d99695fd | |||
| 3a2786a89f | |||
| a6cb30d6c8 | |||
| de6b1f9542 | |||
| 77431671bb | |||
| 4430b7145e | |||
| 898859cc7a | |||
| 43b96df112 | |||
| bb97893bd0 | |||
| 9b21ec6e1f | |||
| ffac354368 | |||
| a9aab51764 | |||
| 4d1fc9ceb1 | |||
| e897a98153 | |||
| 0a8056d835 | |||
| 9681e176b3 | |||
| 1f8be43881 | |||
| 30813551be | |||
| beb564f374 | |||
| 5c97c012a9 | |||
| 50da7cabd6 | |||
| a6528cdfd6 | |||
| 588201fe46 | |||
| 6184b5ee96 | |||
| 5e7baa9d0a | |||
| 79ae650c58 | |||
| 44107f289e | |||
| 75927a87b2 | |||
| 85da30ccf5 | |||
| f73c3b85c2 | |||
| 66bef2fc19 | |||
| 7c5eb021ee | |||
| f902e3b3d8 | |||
| 553124ab5b | |||
| 6c6d93370d | |||
| 55ae3a7dbd | |||
| 586874080f | |||
| d5b91a8983 | |||
| 72fee13112 | |||
| 20ae897f39 | |||
| 6f756d103f | |||
| c9dd858ce3 | |||
| 2e201eaaf7 | |||
| 7c54dcba69 | |||
| a107395707 | |||
| 8a9fe22855 | |||
| 7e04e23528 | |||
| 8d779f68f3 | |||
| 98ba08c1a0 | |||
| a1499b82f8 | |||
| c6c866d78a | |||
| 7a6999bd20 | |||
| 1084cf3523 | |||
| ed5f2a3968 | |||
| 17e1d4b72d | |||
| 912f6c4f3c | |||
| 77d71b5fef | |||
| 6938a73a8a | |||
| cee9df189d | |||
| 2a125e226b | |||
| 4a7e60ef57 | |||
| 0a6140346e | |||
| 01862ebc04 | |||
| 3185299214 | |||
| 5b6ebe4f11 | |||
| 6274ef591b | |||
| 7acdaebee4 | |||
| 6dcfb6b88f | |||
| 064972aecd | |||
| b9dbb66bd7 | |||
| a01792c06c | |||
| d707a67f89 | |||
| 5d8aa11d81 | |||
| a87463fc09 | |||
| d0a4a012c4 | |||
| 6a82d73fe9 | |||
| 7504484f21 | |||
| d497853af5 | |||
| c2f815f5ba | |||
| 4bd4ec2897 | |||
| fc685e9aa0 | |||
| 14d3bd89a7 | |||
| c3970154d6 | |||
| 66aee54401 | |||
| 979f7d19b1 | |||
| f238138711 | |||
| 6c88981b05 | |||
| c935527e6f | |||
| 04915945f5 | |||
| 153df44282 | |||
| 22012556f8 | |||
| d0b03c380b | |||
| de2cd79632 | |||
| cc40ef42f0 | |||
| ba45073e04 | |||
| a3c3f3829d | |||
| 79b7b15b46 | |||
| 111f7111b2 | |||
| 5147651bcb | |||
| ba60d9059f | |||
| 8f205b8c30 | |||
| e046787aec | |||
| 743eebaa6b | |||
| 609caad02f | |||
| a0c47204bb | |||
| 1c87693867 | |||
| 42b756e703 | |||
| d317997396 | |||
| 91dac1563b | |||
| 73cfae97d2 | |||
| 78a606c1e1 | |||
| f258e484d9 | |||
| ea162fd452 | |||
| b80391b183 | |||
| 4c7a9e4394 | |||
| 4b747f70a4 | |||
| 5fb4b6dc04 | |||
| 5e7cfe2976 | |||
| 77db2d84a3 | |||
| 15bb5bfb24 | |||
| 4e9ee9aa03 | |||
| 6a0c7ca788 | |||
| 90e99bcf69 | |||
| 5b20a86d53 | |||
| 6ad1262f4a | |||
| e0297e1dd1 | |||
| 937611aa29 | |||
| eda38e16db | |||
| 2731756c39 | |||
| 853ca0f608 | |||
| 17f4a6e055 | |||
| 925dc6f681 | |||
| 706527eab4 | |||
| 3a96ade423 | |||
| da9c928286 | |||
| 30d3d00900 | |||
| 99fce80d0d | |||
| a5a28e30a0 | |||
| 7fe39353df | |||
| a3576b3154 | |||
| c5d0d84001 | |||
| 467ed54a3b | |||
| 7ea8882843 | |||
| f4cb3bb33f | |||
| 330eb9fa21 | |||
| 1006f513f5 | |||
| 652c4b2e82 | |||
| 3c618a8cd0 | |||
| b5821de793 | |||
| dec604691c | |||
| 72baa6cca9 | |||
| 34b023a74f | |||
| 8249a8ed6a | |||
| 7e1ac5e24a | |||
| 55c72a8bb3 | |||
| b602bb20c2 | |||
| 46ed24275f | |||
| 71db83f806 | |||
| 0746afa0c2 | |||
| 805c384819 | |||
| 9e4c0e318c | |||
| 51eaac2fd7 | |||
| 92c3df82e6 | |||
| 7f238a701e | |||
| 72236f62ad | |||
| 51b0c43d76 | |||
| 79e2007d30 | |||
| 02eb604ceb | |||
| ce6b2b85f7 | |||
| 48d1980061 | |||
| 40fae5c5f1 | |||
| e296ee1040 | |||
| 199e71553d | |||
| 13fa218e5a | |||
| eed5efabea | |||
| d2315e967e | |||
| cbe3c70480 | |||
| c918226909 | |||
| 18472660ae | |||
| 458c2ccd01 | |||
| 7bb9efcebb | |||
| 8a42dfd68d | |||
| 3edd8a6740 | |||
| cba22b7155 | |||
| 246ad6d288 | |||
| 295e119810 | |||
| cfe22f9524 | |||
| de2c1d7786 | |||
| 7d74339aa0 | |||
| 7589e962c2 | |||
| 9a189694f9 | |||
| 4069fbfe7b | |||
| 7ccd886909 | |||
| 42957356b2 | |||
| 9038cd32b2 | |||
| 128c3bfea6 | |||
| 60ed822f6a | |||
| 527ec1bc61 | |||
| cbf203901b | |||
| cf6f3dbe0c | |||
| ab625497ce | |||
| 83532b68dd | |||
| cd2a1495b8 | |||
| b01d2bdd8c | |||
| 736d5316cc | |||
| efe42a2c7d | |||
| ee07755139 | |||
| 3d924eeadd | |||
| aaa091f23b | |||
| 53cd1e5378 | |||
| 3747683f0d | |||
| 59c1e3d8c5 | |||
| 1206f6d2ba | |||
| 9aad3e339a | |||
| ef9221f305 | |||
| 391a3a0430 | |||
| 6b0314f14b | |||
| 8e316eb080 | |||
| 999f2170fe | |||
| 0282b884cc | |||
| ef7e6d0a6a | |||
| 77253a8d81 | |||
| 2041272f5f | |||
| d2a41bdfe1 | |||
| 025a708ecb | |||
| 4e2c124442 | |||
| 79ba9d7a68 | |||
| ee60ec3530 | |||
| 9d7cbb0fe3 | |||
| 0b98a14977 | |||
| 8f51763374 | |||
| 28ea765f19 | |||
| 5378d05bfb | |||
| bbf04f0d40 | |||
| ec6195133b | |||
| fa8c99601c | |||
| a5d5de90f8 | |||
| 994fd359a5 | |||
| a9a5790cba | |||
| 31b3fe403a | |||
| 14b74fe51d |
@@ -13,13 +13,17 @@ assignees: ''
|
||||
|
||||
* What happened:
|
||||
* What should happen:
|
||||
* Fastfetch version used: <!-- please use the latest version, if possible -->
|
||||
* Did it work in an older version: <!-- if yes, which version -->
|
||||
* Where did you get the binary: <!-- Github Release / Github Actions / Installed with a package manager (What package manager) / Built from source yourself -->
|
||||
* Does this issue still occurs in [the latest dev build](https://github.com/fastfetch-cli/fastfetch/actions/)?
|
||||
|
||||
# Often helpful information:
|
||||
|
||||
The content of the configuration file you use (if any)
|
||||
Screenshot:
|
||||
<!-- Paste the screenshot here -->
|
||||
|
||||
The content of the configuration file you use (if any):
|
||||
```
|
||||
//paste here
|
||||
```
|
||||
@@ -38,20 +42,19 @@ Output of `fastfetch --list-features`:
|
||||
//paste here
|
||||
```
|
||||
|
||||
## If fastfatch crashed
|
||||
## If fastfatch crashed or freezed
|
||||
|
||||
Paste the stacktrace here. You may get it with:
|
||||
|
||||
```
|
||||
$ gdb /path/to/fastfetch
|
||||
$ run
|
||||
$ bt
|
||||
```shell
|
||||
# You may need Ctrl+C to stop the process if it freezes
|
||||
gdb -q -ex 'set confirm off' -ex run -ex 'bt full' -ex quit --args /path/to/fastfetch
|
||||
```
|
||||
|
||||
If you are able to identify which module crashed, the strace can be helpful too
|
||||
|
||||
```
|
||||
$ strace /path/to/fastfetch --multithreading false --structure {MODULE} --pipe
|
||||
```shell
|
||||
strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
|
||||
```
|
||||
|
||||
If you cannot do the instructions above, please upload the core dump file:
|
||||
|
||||
@@ -7,10 +7,28 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Before requesting a new feature, please try `fastfetch -c all.jsonc` to see if it has been supported -->
|
||||
## Before requesting a new feature
|
||||
|
||||
# Current state:
|
||||
* A lot of features are not enabled by default. Please try `fastfetch --list-modules` and `fastfetch -c all.jsonc` to see if it has been supported
|
||||
* Fastfetch supports `Command` module, which can be used to grab output from a custom shell script. Please check if it fits your needs
|
||||
|
||||
# Wanted state:
|
||||
```jsonc
|
||||
// ~/.config/fastfetch/fastfetch.jsonc
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"type": "command",
|
||||
"text": "/path/to/your/script",
|
||||
"key": "Feature Title"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
# Why the change is sensible:
|
||||
## Wanted features:
|
||||
|
||||
<!-- Your features here -->
|
||||
|
||||
## Motivation:
|
||||
|
||||
<!-- Your motivation here -->
|
||||
|
||||
@@ -7,6 +7,8 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Tip: A logo can be displayed by fastfetch without getting into fastfetch's official repo. For highly customized logo for personal use, it's recommended to keep it locally. Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
|
||||
|
||||
# OS
|
||||
```
|
||||
Paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
|
||||
|
||||
+204
-62
@@ -10,7 +10,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
@@ -26,7 +26,6 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
compiler: [
|
||||
{ cc: gcc, cxx: "g++" },
|
||||
{ cc: clang, cxx: "clang++" },
|
||||
@@ -37,7 +36,7 @@ jobs:
|
||||
# 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: ${{ matrix.os }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -46,16 +45,16 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev 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 directx-headers-dev libdrm-dev
|
||||
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_LIBPCI=${{ matrix.enableFeatures }} -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 }} .
|
||||
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 .
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
@@ -72,9 +71,68 @@ jobs:
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package
|
||||
Linux-old-amd64:
|
||||
name: Linux-old-amd64
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
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 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 .
|
||||
|
||||
- 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
|
||||
|
||||
- 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
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- 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)
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -88,15 +146,15 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev 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
|
||||
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
|
||||
|
||||
- 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 ddcutil --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
@@ -104,10 +162,10 @@ jobs:
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -134,11 +192,46 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux
|
||||
name: fastfetch-linux-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos:
|
||||
name: MacOS
|
||||
linux-aarch64:
|
||||
name: Linux-aarch64
|
||||
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: aarch64
|
||||
distro: ubuntu22.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake 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 libddcutil-dev libchafa-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-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -152,11 +245,10 @@ jobs:
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
brew update
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
@@ -164,10 +256,10 @@ jobs:
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -190,12 +282,12 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos
|
||||
name: fastfetch-macos-universal
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
freebsd:
|
||||
name: FreeBSD
|
||||
runs-on: macos-12
|
||||
freebsd-amd64:
|
||||
name: FreeBSD-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -207,13 +299,16 @@ jobs:
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: freebsd
|
||||
architecture: x86-64
|
||||
cpu_count: 3
|
||||
shell: bash
|
||||
version: '13.2'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package --verbose
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch
|
||||
time ./fastfetch --format json
|
||||
@@ -224,11 +319,48 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-freebsd
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
win64:
|
||||
name: Win64
|
||||
freebsd-aarch64:
|
||||
name: FreeBSD-aarch64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: freebsd
|
||||
architecture: arm64
|
||||
cpu_count: 3
|
||||
shell: bash
|
||||
version: '13.2'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch
|
||||
time ./fastfetch --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-freebsd-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -245,7 +377,7 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG64
|
||||
update: true
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
@@ -254,7 +386,7 @@ jobs:
|
||||
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
|
||||
@@ -278,19 +410,19 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-win64
|
||||
path: ./fastfetch-*-Win64.*
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
|
||||
win32:
|
||||
name: Win32
|
||||
windows-i686:
|
||||
name: Windows-i686
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -307,13 +439,13 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG32
|
||||
update: true
|
||||
install: git mingw-w64-clang-i686-7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd
|
||||
install: git mingw-w64-clang-i686-7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c, cpp
|
||||
|
||||
@@ -321,10 +453,10 @@ jobs:
|
||||
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
|
||||
@@ -345,27 +477,29 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-win32
|
||||
path: ./fastfetch-*-Win32.*
|
||||
name: fastfetch-windows-i686
|
||||
path: ./fastfetch-windows-i686.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linux
|
||||
- macos
|
||||
- freebsd
|
||||
- win64
|
||||
- win32
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
- freebsd-aarch64
|
||||
- windows-amd64
|
||||
- windows-i686
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -376,38 +510,46 @@ jobs:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: download artifacts
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
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.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-*/fastfetch-*
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
|
||||
- name: download source tarballs
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-amd64.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
ls fastfetch-*/*
|
||||
|
||||
- name: generate release notes
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
|
||||
- name: update release body
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
bodyFile: fastfetch-release-notes.md
|
||||
allowUpdates: true
|
||||
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
**/build/
|
||||
**/.vscode/
|
||||
**/.cache/
|
||||
**/.kdev4/
|
||||
**/.DS_Store
|
||||
/.vs
|
||||
build/
|
||||
.vs/
|
||||
.vscode/
|
||||
.cache/
|
||||
.kdev4/
|
||||
.DS_Store
|
||||
cscope.*
|
||||
tags
|
||||
fastfetch.kdev4
|
||||
|
||||
+188
@@ -1,3 +1,191 @@
|
||||
# 2.9.2
|
||||
|
||||
Changes:
|
||||
* To make use of the newly introduced `yyjson` flag `YYJSON_WRITE_NEWLINE_AT_END`, fastfetch now requires `yyjson` 0.9.0 or later
|
||||
|
||||
Features:
|
||||
* Always add a final new-line when generating JSON output
|
||||
* Detect partition create time, which can be used as OS installation time (Disk)
|
||||
* Print time string when generating JSON result instead of UNIX epoch time number, which is more human-readable
|
||||
|
||||
Bugfixes:
|
||||
* Fix a memory leak
|
||||
* Better portable mode detection of Windows Terminal (TerminalFont, Windows)
|
||||
* Fix parsing of option `--packages-disabled` (Packages)
|
||||
* Don't use command `time` as a shell (Shell)
|
||||
|
||||
Logos:
|
||||
* Add openSUSE MicroOS
|
||||
* Fix color of AOSC OS
|
||||
|
||||
# 2.9.1
|
||||
|
||||
Features:
|
||||
* Support weston-terminal (missed commit in v2.9.0) (TerminalFont, Linux)
|
||||
* Support hyprcursor detection (#776, Cursor, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fix `fastfetch --gen-config` raises SIGSEGV when `~/.config/fastfetch` doesn't exist. Regression of `2.9.0` (#778)
|
||||
|
||||
# 2.9.0
|
||||
|
||||
Features:
|
||||
* Support Lxterminal version detection (Terminal, Linux)
|
||||
* Support weston-terminal version detection (Terminal, Linux)
|
||||
* Support `am` package manager detection (#771, Packages, Linux)
|
||||
* Support network prefix length detection for IPv6 (LocalIP)
|
||||
* Display all IPs when multiple IPs are assigned to the same interface (LocalIP)
|
||||
* Add option `--localip-show-prefix-len` to show network prefix length for both IPv4 and IPv6. Defaults to `true` (LocalIP)
|
||||
|
||||
Bugfixes:
|
||||
* Fix network prefix length detection when the value is greater than 24 (#773, LocalIP, Linux)
|
||||
* For xfce4-terminal, use system mono font if no config file is found (TerminalFont, Linux)
|
||||
|
||||
# 2.8.10
|
||||
|
||||
Bugfixes:
|
||||
* Don't display 0.00 GHz (CPU, FreeBSD)
|
||||
* Don't detect manufactor of Qualcomm as ARM (CPU, Android)
|
||||
* Ignore `chezmoi` (Terminal, Linux)
|
||||
* Trim trailing possible whitespaces (PublicIP)
|
||||
* Fix detection compatibility for KDE 6 (Font, Linux)
|
||||
* Always use Metal API to detect vmem size (GPU, macOS)
|
||||
|
||||
Features:
|
||||
* Improve stability; print more useful error message; avoid misuse (PublicIP / Weather)
|
||||
* Use MS-DOS device name as mountFrom result, instead of useless GUID volume name (Windows, Disk)
|
||||
* Some adjustments to Terminal detection (Terminal, Windows)
|
||||
* Don't pretty print CMD
|
||||
* Print conhost as Windows Console
|
||||
* Don't detect `wininit` as Terminal
|
||||
|
||||
Logo:
|
||||
* Fix color of Arco Linux
|
||||
|
||||
# 2.8.9
|
||||
|
||||
Bugfixes:
|
||||
* Don't detect `SessionLeader` as terminal, actually (Terminal, Linux)
|
||||
* Fix blurry chafa result when specifying both width and height (#757, Logo)
|
||||
|
||||
Features:
|
||||
* Support new MacBook Air (Host, macOS)
|
||||
* Distinguish min frequency and base frequency (CPU)
|
||||
|
||||
Logo:
|
||||
* Fix proxmox
|
||||
|
||||
# 2.8.8
|
||||
|
||||
Bugfixes:
|
||||
* Fix old fish version compatibility (#744)
|
||||
* Fix truncated texts in `--help format` (#745)
|
||||
* Fix old vulkan-header and libdrm library compatibility (#748, Linux)
|
||||
* Fix possible segfaults in `--help *-format` (#749)
|
||||
* Fix invalid resolution detection when using libdrm (Linux, Display)
|
||||
* Fix segfault when `/sys/devices/system/cpu/cpufreq/` doesn't exist (#750, CPU, Linux)
|
||||
* Don't detect `SessionLeader` as terminal (Terminal, Linux)
|
||||
* Fix detection of client IP (Users, Linux)
|
||||
|
||||
# 2.8.7
|
||||
|
||||
Bugfixes:
|
||||
* Fix max CPU frequency detection for some cases (CPU, Linux)
|
||||
* Fix some memory leaks
|
||||
* Fix ddcutil 2.1 compatibility (Brightness, Linux)
|
||||
* Workaround `permission denied` error when reading `/proc/uptime` (Uptime, Android)
|
||||
|
||||
Features:
|
||||
* Support zellij version detection (Linux, Terminal)
|
||||
|
||||
Logo:
|
||||
* Fix PostMarketOS
|
||||
|
||||
# 2.8.6
|
||||
|
||||
Changes:
|
||||
* Due to newly introduced configs, JSONC option `{ "temperatureUnit": "C" }` has been changed to `{ "temp": { "unit": "C" } }`
|
||||
|
||||
Bugfixes:
|
||||
* Fix incorrect GPU name detection for Intel iGPU on Linux (#736, GPU, Linux)
|
||||
|
||||
Features:
|
||||
* Support additional temperature formatting options (#737)
|
||||
* `{ "temp": { "ndigits": 1 } }`
|
||||
* `{ "temp": { "color": { "green": "green", "yellow": "yellow", "red": "red" } } }`
|
||||
* Support specifying custom `pci.ids` path for Linux (GPU, Linux)
|
||||
* Support warp-linux terminal version & terminal font detection (Terminal, Linux)
|
||||
|
||||
# 2.8.5
|
||||
|
||||
Bugfixes:
|
||||
* Fix uninitialized variables
|
||||
|
||||
# 2.8.4
|
||||
|
||||
Bugfixes:
|
||||
* Fix segfault if we fail to find `Vendor ID` in `lscpu` (#718, CPU, Linux)
|
||||
* Fix multi-device bcachefs filesystem compatibility (#731, Disk, Linux)
|
||||
|
||||
Features:
|
||||
* Support portable Windows Terminal settings (#720, Terminal, Windows)
|
||||
* Support `--color-block-width` and `--color-block-range` (#721, Colors)
|
||||
* Support `--diskio-detect-total` to show total bytes read/written (DiskIO)
|
||||
* Support `--netio-detect-total` to show total bytes received/sent (NetIO)
|
||||
* Support `--packages-disabled` to disable specified package manager (#729, Packages)
|
||||
* Support `--display-order` to sort multiple displays in a specific order (Display)
|
||||
* Support `--display-compact-type original-with-refresh-rate` to show refresh rates in compact (oneline) mode (Display)
|
||||
|
||||
# 2.8.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix GPU name detection for AMD graphic cards (GPU, Linux / FreeBSD)
|
||||
|
||||
# 2.8.2
|
||||
|
||||
Changes:
|
||||
* The linux binaries are now built with glibc 2.35, which means they no longer support Debian 11 and Ubuntu 20.04. Users using these distros may download the artifacts `fastfetch-linux-old` from GitHub Actions.
|
||||
|
||||
Features:
|
||||
* Rewrite GPU module, drop libpci dependency (GPU, Linux)
|
||||
* Detect marketing name of Apple Silicon CPUs for asahi linux (CPU, Linux)
|
||||
* Add new module `Camera`, which prints the name and resolution of connected cameras
|
||||
|
||||
Bugfixes:
|
||||
* Fix compatibility with packages installed by flatpak (Terminal, Linux)
|
||||
* Don't show an empty battery if no battery is detected (macOS, Battery)
|
||||
* Don't show `not connected` if no power adapter is found (macOS / Linux, PowerAdapter)
|
||||
* Make format of battery status be consistent with other platforms (Linux, Battery)
|
||||
|
||||
Logo:
|
||||
* Print Asahi logo in asahi linux (Logo, Linux)
|
||||
* Add Asahi2, z/OS, Tatra, PikaOS
|
||||
|
||||
# 2.7.1
|
||||
|
||||
Features:
|
||||
* Config presets in app folder now work with symlinks
|
||||
|
||||
Bugfixes:
|
||||
* Fix a possible segfault when detecting terminal (Terminal, Linux)
|
||||
|
||||
# 2.7.0
|
||||
|
||||
Features:
|
||||
* Add new module `TerminalTheme`, which prints the foreground and background color of the current terminal window. Currently doesn't work on Windows.
|
||||
* Allow command substitution when expanding paths. For example, now it's possible to use `"source": "$(ls ~/path/to/images/*.png | shuf -n 1)"` in JSONC config file to randomly choose an image to display. (#698)
|
||||
* Use native methods instead of pciutils to detect GPUs in FreeBSD. (GPU, FreeBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fix text formatting (Wifi, Linux)
|
||||
* Fix terminal detection in some cases (Terminal)
|
||||
* Remove trailing `\0` in JSON results (FreeBSD)
|
||||
* Fix uninitialized variables (GPU, Linux)
|
||||
* Fix a possible segfault (OpenCL)
|
||||
|
||||
Logo:
|
||||
* Add ASCII logos for fedora immutable variants (#700)
|
||||
|
||||
# 2.6.3
|
||||
|
||||
Bugfixes:
|
||||
|
||||
+44
-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.6.3
|
||||
VERSION 2.9.2
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -42,7 +42,6 @@ include(CheckIncludeFile)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF)
|
||||
@@ -70,7 +69,6 @@ cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF)
|
||||
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
@@ -78,6 +76,10 @@ option(ENABLE_PROPRIETARY_GPU_DRIVER_API "Enable proprietary GPU driver API (NVM
|
||||
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
|
||||
|
||||
if (LINUX)
|
||||
set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
|
||||
endif()
|
||||
|
||||
####################
|
||||
# Compiler options #
|
||||
####################
|
||||
@@ -120,7 +122,7 @@ if(ENABLE_ASAN)
|
||||
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -fstack-protector-all -fno-delete-null-pointer-checks")
|
||||
if(NOT WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
|
||||
endif()
|
||||
@@ -231,10 +233,9 @@ endif()
|
||||
|
||||
fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)
|
||||
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
|
||||
fastfetch_load_text(src/data/help.txt DATATEXT_HELP)
|
||||
fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER)
|
||||
fastfetch_load_text(src/data/help_color.txt DATATEXT_HELP_COLOR)
|
||||
fastfetch_load_text(src/data/help_format.txt DATATEXT_HELP_FORMAT)
|
||||
fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG)
|
||||
|
||||
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
|
||||
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
|
||||
@@ -279,6 +280,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/printing.c
|
||||
src/common/properties.c
|
||||
src/common/settings.c
|
||||
src/common/temps.c
|
||||
src/detection/chassis/chassis.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
@@ -293,6 +295,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/os/os.c
|
||||
src/detection/packages/packages.c
|
||||
src/detection/publicip/publicip.c
|
||||
src/detection/terminaltheme/terminaltheme.c
|
||||
src/detection/terminalfont/terminalfont.c
|
||||
src/detection/terminalshell/terminalshell.c
|
||||
src/detection/version/version.c
|
||||
@@ -309,6 +312,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/board/board.c
|
||||
src/modules/brightness/brightness.c
|
||||
src/modules/break/break.c
|
||||
src/modules/camera/camera.c
|
||||
src/modules/chassis/chassis.c
|
||||
src/modules/colors/colors.c
|
||||
src/modules/cpu/cpu.c
|
||||
@@ -348,6 +352,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/swap/swap.c
|
||||
src/modules/media/media.c
|
||||
src/modules/terminal/terminal.c
|
||||
src/modules/terminaltheme/terminaltheme.c
|
||||
src/modules/terminalfont/terminalfont.c
|
||||
src/modules/terminalsize/terminalsize.c
|
||||
src/modules/theme/theme.c
|
||||
@@ -400,6 +405,7 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
@@ -432,6 +438,7 @@ if(LINUX)
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
@@ -485,6 +492,7 @@ elseif(ANDROID)
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(BSD)
|
||||
@@ -514,7 +522,8 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_bsd.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/lm/lm_linux.c
|
||||
@@ -547,6 +556,7 @@ elseif(BSD)
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(APPLE)
|
||||
@@ -602,6 +612,7 @@ elseif(APPLE)
|
||||
src/detection/wm/wm_apple.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
@@ -657,6 +668,7 @@ elseif(WIN32)
|
||||
src/detection/wm/wm_windows.cpp
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/camera/camera_windows.cpp
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
src/util/windows/registry.c
|
||||
@@ -687,6 +699,9 @@ check_function_exists(wcwidth HAVE_WCWIDTH)
|
||||
if(NOT HAVE_WCWIDTH)
|
||||
list(APPEND LIBFASTFETCH_SRC src/3rdparty/mk_wcwidch/wcwidth.c)
|
||||
endif()
|
||||
if(LINUX)
|
||||
check_function_exists(statx HAVE_STATX)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SYSTEM_YYJSON)
|
||||
find_package(yyjson)
|
||||
@@ -716,8 +731,8 @@ if(yyjson_FOUND)
|
||||
else()
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
|
||||
if(APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -750,10 +765,19 @@ elseif(APPLE)
|
||||
target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE)
|
||||
endif()
|
||||
|
||||
if(HAVE_STATX)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_STATX)
|
||||
endif()
|
||||
|
||||
if(HAVE_WCWIDTH)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WCWIDTH)
|
||||
endif()
|
||||
|
||||
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()
|
||||
|
||||
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
|
||||
if(NOT ENABLE_${VARNAME})
|
||||
return()
|
||||
@@ -790,10 +814,6 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
ff_lib_enable(LIBPCI
|
||||
"libpci"
|
||||
"Pci"
|
||||
)
|
||||
ff_lib_enable(VULKAN
|
||||
"vulkan"
|
||||
"Vulkan"
|
||||
@@ -916,9 +936,11 @@ if(LINUX)
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "-framework AVFoundation"
|
||||
PRIVATE "-framework Cocoa"
|
||||
PRIVATE "-framework CoreFoundation"
|
||||
PRIVATE "-framework CoreAudio"
|
||||
PRIVATE "-framework CoreMedia"
|
||||
PRIVATE "-framework CoreVideo"
|
||||
PRIVATE "-framework CoreWLAN"
|
||||
PRIVATE "-framework IOBluetooth"
|
||||
@@ -1103,6 +1125,14 @@ install(
|
||||
##################
|
||||
|
||||
set(CPACK_GENERATOR "TGZ;ZIP")
|
||||
if(APPLE)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-universal" CPACK_PACKAGE_FILE_NAME)
|
||||
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)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
|
||||
@@ -1119,7 +1149,7 @@ set(CPACK_SET_DESTDIR ON)
|
||||
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "\
|
||||
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
|
||||
It is written in c to achieve much better performance.\
|
||||
It is written mostly in C to achieve much better performance.\
|
||||
")
|
||||
|
||||
include(CPack)
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||
identity and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall
|
||||
community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||
any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official email address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
[INSERT CONTACT METHOD].
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series of
|
||||
actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or permanent
|
||||
ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||
community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.1, available at
|
||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||
[https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
@@ -27,12 +27,17 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
|
||||
|
||||
### Linux
|
||||
|
||||
* 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`
|
||||
* Arch Linux: `sudo pacman -S fastfetch`
|
||||
Some distros packaged a 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).
|
||||
* Fedora: `sudo dnf install fastfetch`
|
||||
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
|
||||
* NixOS: `sudo nix-shell -p fastfetch`
|
||||
* Alpine: `apk add --upgrade fastfetch`
|
||||
* NixOS: `nix-shell -p fastfetch`
|
||||
* openSUSE: `sudo zypper install fastfetch`
|
||||
* ALT Linux: `sudo apt-get install fastfetch`
|
||||
|
||||
Replace sudo with doas depending on what you use.
|
||||
|
||||
@@ -40,8 +45,14 @@ Replace sudo with doas depending on what you use.
|
||||
|
||||
### macOS
|
||||
|
||||
...via [HomeBrew](https://brew.sh):
|
||||
|
||||
`brew install fastfetch`
|
||||
|
||||
...via [MacPorts](https://www.macports.org):
|
||||
|
||||
`sudo port install fastfetch`
|
||||
|
||||
### Windows
|
||||
|
||||
`scoop install fastfetch`
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env fish
|
||||
|
||||
if not type -q fastfetch
|
||||
return
|
||||
exit
|
||||
end
|
||||
|
||||
complete -c fastfetch -f
|
||||
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
fastfetch (2.8.10) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.10
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 25 Mar 2024 15:01:53 +0800
|
||||
|
||||
fastfetch (2.8.9) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.9
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 15 Mar 2024 10:49:42 +0800
|
||||
|
||||
fastfetch (2.8.8) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.8
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 08 Mar 2024 09:59:41 +0800
|
||||
|
||||
fastfetch (2.8.6) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.6
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 28 Feb 2024 10:01:40 +0800
|
||||
|
||||
fastfetch (2.8.4) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.4
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 23 Feb 2024 16:14:57 +0800
|
||||
|
||||
fastfetch (2.7.1ubuntu2) jammy; urgency=medium
|
||||
|
||||
* Ignore .git
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 14:23:23 +0800
|
||||
|
||||
fastfetch (2.7.1ubuntu1) jammy; urgency=medium
|
||||
|
||||
* Update build scripts
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 13:53:37 +0800
|
||||
|
||||
fastfetch (2.7.1) jammy; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
12
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: 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, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
Package: fastfetch
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
|
||||
It is written mainly in C, with performance and customizability in mind.
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: fastfetch
|
||||
Source: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
Files: *
|
||||
Copyright: 2024 fastfetch-cli
|
||||
License: Expat
|
||||
|
||||
Files: src/3rdparty/yyjson/*
|
||||
Copyright: 2020 YaoYuan
|
||||
License: Expat
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
fastfetch_2.8.10_source.buildinfo universe/utils optional
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
debuild -S -i -I
|
||||
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=cmake+ninja
|
||||
|
||||
override_dh_ctest_configure:
|
||||
dh_ctest_configure -- -DSET_TWEAK=OFF -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
version=4
|
||||
opts="filenamemangle=s%.*/@ANY_VERSION@%@PACKAGE@-$1.tar.gz%,searchmode=plain" \
|
||||
https://api.github.com/repos/fastfetch-cli/fastfetch/releases?per_page=100 \
|
||||
https://api.github.com/repos/fastfetch-cli/fastfetch/tarball/@ANY_VERSION@
|
||||
+268
-91
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"$schema": "https://json-schema.org/draft-07/schema",
|
||||
"$defs": {
|
||||
"colors": {
|
||||
"type": "string",
|
||||
@@ -30,6 +30,7 @@
|
||||
"percent": {
|
||||
"description": "Threshold of percentage colors",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"green": {
|
||||
"type": "integer",
|
||||
@@ -44,9 +45,37 @@
|
||||
"description": "Value greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red"
|
||||
}
|
||||
}
|
||||
},
|
||||
"temperature": {
|
||||
"description": "Detect and display temperature if supported",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"green": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 100,
|
||||
"description": "Value (in celsius) less then green will be shown in green"
|
||||
},
|
||||
"yellow": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 100,
|
||||
"description": "Value (in celsius) greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"title": "JSON config",
|
||||
"description": "JSON config file for fastfetch. Usually be `~/.config/fastfetch.jsonc`",
|
||||
"properties": {
|
||||
@@ -69,6 +98,7 @@
|
||||
{
|
||||
"description": "Fastfetch logo configurations",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Set the type of the logo given",
|
||||
@@ -96,6 +126,7 @@
|
||||
},
|
||||
"color": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Overwrite a color in the logo",
|
||||
"properties": {
|
||||
"1": {
|
||||
@@ -134,8 +165,7 @@
|
||||
"description": "Color 9",
|
||||
"$ref": "#/$defs/colors"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"width": {
|
||||
"type": "integer",
|
||||
@@ -149,6 +179,7 @@
|
||||
},
|
||||
"padding": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set the padding of the logo",
|
||||
"properties": {
|
||||
"top": {
|
||||
@@ -166,8 +197,7 @@
|
||||
"description": "Set the right padding of the logo",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"printRemaining": {
|
||||
"type": "boolean",
|
||||
@@ -191,6 +221,7 @@
|
||||
},
|
||||
"chafa": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Chafa configuration. See chafa document for details",
|
||||
"properties": {
|
||||
"fgOnly": {
|
||||
@@ -233,17 +264,16 @@
|
||||
"DIFFUSION"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"description": "Fastfetch general configurations",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"multithreading": {
|
||||
"type": "boolean",
|
||||
@@ -272,7 +302,7 @@
|
||||
"description": "Force display detection to use DRM. Linux only",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "bool",
|
||||
"type": "boolean",
|
||||
"const": false,
|
||||
"description": "Try `wayland`, then `x11`, then `drm`"
|
||||
},
|
||||
@@ -282,7 +312,7 @@
|
||||
"const": "sysfs-only"
|
||||
},
|
||||
{
|
||||
"type": "bool",
|
||||
"type": "boolean",
|
||||
"const": true,
|
||||
"description": "Try `libdrm` first, then `sysfs` if libdrm failed"
|
||||
}
|
||||
@@ -299,12 +329,12 @@
|
||||
"description": "Set the timeout (ms) when waiting for child processes, `-1` for no timeout",
|
||||
"default": 1000
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"description": "Configure how things to be displayed",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"stat": {
|
||||
"type": "boolean",
|
||||
@@ -345,6 +375,7 @@
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"keys": {
|
||||
"description": "Set the color of the keys",
|
||||
@@ -354,8 +385,7 @@
|
||||
"description": "Set the color of the title",
|
||||
"$ref": "#/$defs/colors"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -390,6 +420,7 @@
|
||||
},
|
||||
"size": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set how a size value should be displayed",
|
||||
"properties": {
|
||||
"maxPrefix": {
|
||||
@@ -407,14 +438,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"temperatureUnit": {
|
||||
"type": "string",
|
||||
"description": "Set the unit of the temperature",
|
||||
"enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"],
|
||||
"default": "C"
|
||||
"temp": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set how temperature values should be displayed",
|
||||
"properties": {
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"description": "Set the unit of the temperature",
|
||||
"enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"],
|
||||
"default": "C"
|
||||
},
|
||||
"ndigits": {
|
||||
"type": "integer",
|
||||
"description": "Set the number of digits to keep after the decimal point when formatting temperature values",
|
||||
"minimum": 0,
|
||||
"maximum": 9,
|
||||
"default": 1
|
||||
},
|
||||
"color": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set color used in different states of temperature values",
|
||||
"properties": {
|
||||
"green": {
|
||||
"description": "Color used in green state",
|
||||
"$ref": "#/$defs/colors"
|
||||
},
|
||||
"yellow": {
|
||||
"description": "Color used in yellow state",
|
||||
"$ref": "#/$defs/colors"
|
||||
},
|
||||
"red": {
|
||||
"description": "Color used in red state",
|
||||
"$ref": "#/$defs/colors"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"bar": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set the bar configuration",
|
||||
"properties": {
|
||||
"charElapsed": {
|
||||
@@ -442,6 +507,7 @@
|
||||
},
|
||||
"percent": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set how a percentage value should be displayed",
|
||||
"properties": {
|
||||
"type": {
|
||||
@@ -460,6 +526,7 @@
|
||||
},
|
||||
"color": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "Set color used in different states of percentage bars and numbers",
|
||||
"properties": {
|
||||
"green": {
|
||||
@@ -483,12 +550,12 @@
|
||||
"description": "Whether to disable the stdout application buffer",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"library": {
|
||||
"description": "Set the path of a library to load",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"pci": {
|
||||
"type": "string",
|
||||
@@ -590,8 +657,7 @@
|
||||
"description": "Used for brightness detection of external displays (Linux)",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"description": "Fastfetch modules to run",
|
||||
@@ -648,6 +714,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"title",
|
||||
"theme",
|
||||
"uptime",
|
||||
@@ -675,16 +742,20 @@
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "Break",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "break",
|
||||
"description": "Print a empty line"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "module",
|
||||
"description": "No additional properties",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"anyOf": [
|
||||
@@ -772,6 +843,10 @@
|
||||
"const": "terminalsize",
|
||||
"description": "Print current terminal size"
|
||||
},
|
||||
{
|
||||
"const": "terminaltheme",
|
||||
"description": "Print current terminal theme (foreground and background colors)"
|
||||
},
|
||||
{
|
||||
"const": "theme",
|
||||
"description": "Print current theme of desktop environment"
|
||||
@@ -818,11 +893,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Battery",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "battery",
|
||||
@@ -834,9 +910,7 @@
|
||||
"default": false
|
||||
},
|
||||
"temp": {
|
||||
"description": "Detect and display Battery temperature if supported",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
@@ -853,11 +927,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Bluetooth",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "List bluetooth devices",
|
||||
@@ -883,11 +958,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Brightness",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "brightness",
|
||||
@@ -907,6 +983,8 @@
|
||||
},
|
||||
{
|
||||
"title": "Chassis",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "chassis",
|
||||
@@ -928,15 +1006,15 @@
|
||||
},
|
||||
{
|
||||
"title": "CPU",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print CPU name, frequency, etc",
|
||||
"const": "cpu"
|
||||
},
|
||||
"temp": {
|
||||
"description": "Detect and display CPU temperature if supported",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"freqNdigits": {
|
||||
"description": "Set the number of digits to keep after the decimal point when printing CPU frequency",
|
||||
@@ -957,11 +1035,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "CPU Usage",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "cpuusage",
|
||||
@@ -979,6 +1058,8 @@
|
||||
},
|
||||
{
|
||||
"title": "Colors",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print some colored blocks",
|
||||
@@ -1002,11 +1083,37 @@
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
},
|
||||
"block": {
|
||||
"description": "Set behavior of block printing",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"width": {
|
||||
"description": "Set the block width in spaces",
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"default": 3
|
||||
},
|
||||
"range": {
|
||||
"description": "Set the range of colors in the blocks to print",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 15
|
||||
},
|
||||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Command",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Running custom shell scripts",
|
||||
@@ -1032,11 +1139,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Custom",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print a custom string, with or without key",
|
||||
@@ -1059,11 +1167,12 @@
|
||||
},
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"additionalProperties": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Display",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print resolutions, refresh rates, etc",
|
||||
@@ -1073,7 +1182,9 @@
|
||||
"enum": [
|
||||
"none",
|
||||
"original",
|
||||
"scaled"
|
||||
"scaled",
|
||||
"original-with-refresh-rate",
|
||||
"scaled-with-refresh-rate"
|
||||
],
|
||||
"description": "Set if all displays should be printed in one line",
|
||||
"default": "none"
|
||||
@@ -1083,6 +1194,15 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"order": {
|
||||
"description": "Set the order should be used when printing",
|
||||
"enum": [
|
||||
"none",
|
||||
"asc",
|
||||
"desc"
|
||||
],
|
||||
"default": "none"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -1095,11 +1215,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Disk",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print partitions, space usage, disk type, etc",
|
||||
@@ -1154,11 +1275,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "DiskIO",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print physical disk I/O throughput",
|
||||
@@ -1168,6 +1290,11 @@
|
||||
"description": "Show disks with given name prefix only",
|
||||
"type": "string"
|
||||
},
|
||||
"detectTotal": {
|
||||
"description": "Detect total bytes instead of current rate",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -1180,11 +1307,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "DE",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "de",
|
||||
@@ -1211,6 +1339,8 @@
|
||||
},
|
||||
{
|
||||
"title": "Gamepad",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "gamepad",
|
||||
@@ -1231,20 +1361,19 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "GPU",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print GPU names, graphic memory size, type, etc",
|
||||
"const": "gpu"
|
||||
},
|
||||
"temp": {
|
||||
"description": "Detect and display GPU temperature if supported",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"driverSpecific": {
|
||||
"description": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)",
|
||||
@@ -1277,11 +1406,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Local IP",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "List local IP addresses (v4 or v6), MAC addresses, etc",
|
||||
@@ -1307,6 +1437,11 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"showPrefixLen": {
|
||||
"description": "Show network prefix length (/N)",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"compact": {
|
||||
"description": "Show all IPs in one line",
|
||||
"type": "boolean",
|
||||
@@ -1333,11 +1468,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Memory",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "memory",
|
||||
@@ -1358,11 +1494,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "NetIO",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print network I/O throughput",
|
||||
@@ -1377,6 +1514,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"detectTotal": {
|
||||
"description": "Detect total bytes instead of current rate",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -1389,11 +1531,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "OpenGL",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print highest OpenGL version supported by the GPU",
|
||||
@@ -1421,20 +1564,47 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Packages",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "packages",
|
||||
"description": "List installed package managers and count of installed packages"
|
||||
},
|
||||
"winget": {
|
||||
"description": "Set if winget package count should be detected.\nNote this is very slow operation. Please make sure `winget list` works before enable this option\nWindows only",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"disabled": {
|
||||
"description": "List of package managers to be disabled when detecting",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"am",
|
||||
"apk",
|
||||
"brew",
|
||||
"choco",
|
||||
"dpkg",
|
||||
"emerge",
|
||||
"eopkg",
|
||||
"flatpak",
|
||||
"macports",
|
||||
"nix",
|
||||
"opkg",
|
||||
"pacman",
|
||||
"paludis",
|
||||
"pkg",
|
||||
"pkgtool",
|
||||
"rpm",
|
||||
"scoop",
|
||||
"snap",
|
||||
"winget",
|
||||
"xbps"
|
||||
],
|
||||
"uniqueItems": true
|
||||
},
|
||||
"default": ["winget"]
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
@@ -1452,6 +1622,8 @@
|
||||
},
|
||||
{
|
||||
"title": "Physical Disk",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print physical disk information",
|
||||
@@ -1462,9 +1634,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"temp": {
|
||||
"description": "Detect and display SSD temperature if supported",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
@@ -1478,11 +1648,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Public IP",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print your public IP address, etc",
|
||||
@@ -1512,11 +1683,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Separator",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print a separator line",
|
||||
@@ -1527,11 +1699,12 @@
|
||||
"type": "string",
|
||||
"default": "-"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Sound",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print sound devices, volume, etc",
|
||||
@@ -1562,11 +1735,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Swap",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "swap",
|
||||
@@ -1587,11 +1761,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Title",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print title, which contains your user name, hostname",
|
||||
@@ -1604,6 +1779,8 @@
|
||||
},
|
||||
"color": {
|
||||
"description": "Set colors of the different part of title",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"user": {
|
||||
"description": "Set color of the user name (left part)",
|
||||
@@ -1617,8 +1794,7 @@
|
||||
"description": "Set color of the host name (right part)",
|
||||
"$ref": "#/$defs/colors"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
@@ -1632,11 +1808,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Weather",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print weather information",
|
||||
@@ -1669,11 +1846,12 @@
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "WM",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "wm",
|
||||
@@ -1703,6 +1881,5 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
"gpu",
|
||||
@@ -49,6 +50,7 @@
|
||||
"users",
|
||||
"bluetooth",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"weather",
|
||||
"netio",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
"gpu",
|
||||
@@ -55,6 +56,7 @@
|
||||
"users",
|
||||
"bluetooth",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
{
|
||||
"type": "weather",
|
||||
|
||||
@@ -84,17 +84,17 @@
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"key": " PC",
|
||||
"key": " PC",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│ ├",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "none"
|
||||
},
|
||||
"display": {
|
||||
"separator": "-> "
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "title",
|
||||
"format": " {6}{7}{8}"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "┌───────────────────────────── \u001b[1mSystem Information\u001b[0m ─────────────────────────────┐" // `\u001b` is `\033`, or `\e`
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"key": " OS ",
|
||||
"keyColor": "red",
|
||||
"type": "os"
|
||||
},
|
||||
{
|
||||
"key": " Machine ",
|
||||
"keyColor": "green",
|
||||
"type": "host"
|
||||
},
|
||||
{
|
||||
"key": " Kernel ",
|
||||
"keyColor": "magenta",
|
||||
"type": "kernel"
|
||||
},
|
||||
{
|
||||
"key": " Uptime ",
|
||||
"keyColor": "red",
|
||||
"type": "uptime"
|
||||
},
|
||||
{
|
||||
"key": " Resolution ",
|
||||
"keyColor": "yellow",
|
||||
"type": "display",
|
||||
"compactType": "original-with-refresh-rate"
|
||||
},
|
||||
{
|
||||
"key": " WM ",
|
||||
"keyColor": "blue",
|
||||
"type": "wm"
|
||||
},
|
||||
{
|
||||
"key": " DE ",
|
||||
"keyColor": "green",
|
||||
"type": "de"
|
||||
},
|
||||
{
|
||||
"key": " Shell ",
|
||||
"keyColor": "cyan",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"key": " Terminal ",
|
||||
"keyColor": "red",
|
||||
"type": "terminal"
|
||||
},
|
||||
{
|
||||
"key": " CPU ",
|
||||
"keyColor": "yellow",
|
||||
"type": "cpu"
|
||||
},
|
||||
{
|
||||
"key": " GPU ",
|
||||
"keyColor": "blue",
|
||||
"type": "gpu"
|
||||
},
|
||||
{
|
||||
"key": " Memory ",
|
||||
"keyColor": "magenta",
|
||||
"type": "memory"
|
||||
},
|
||||
{
|
||||
"key": " Local IP ",
|
||||
"keyColor": "red",
|
||||
"type": "localip",
|
||||
"compact": true
|
||||
},
|
||||
{
|
||||
"key": " Public IP ",
|
||||
"keyColor": "cyan",
|
||||
"type": "publicip"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "└──────────────────────────────────────────────────────────────────────────────┘" // `\u001b` is `\033`, or `\e`
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "colors",
|
||||
"paddingLeft": 34,
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -19,15 +19,15 @@
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"key": " "
|
||||
"key": " "
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": " "
|
||||
"key": " "
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": " "
|
||||
"key": " "
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
},
|
||||
{
|
||||
"type": "icons",
|
||||
"key": "I",
|
||||
"format": "{5}"
|
||||
"key": "I"
|
||||
},
|
||||
{
|
||||
"type": "font",
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
"modules": [
|
||||
{
|
||||
"type": "host",
|
||||
"key": "╭─",
|
||||
"key": "╭─",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "├─",
|
||||
"key": "├─",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "├─",
|
||||
"key": "├─",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -77,17 +77,17 @@
|
||||
"break",
|
||||
{
|
||||
"type": "host",
|
||||
"key": " PC",
|
||||
"key": " PC",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "├",
|
||||
"key": "├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "├",
|
||||
"key": "├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": ""
|
||||
"key": ""
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"uptime",
|
||||
{
|
||||
"type": "battery",
|
||||
"format": "{/4}{-}{/}{4}%{?5} [{5}]{?}"
|
||||
"format": "{/4}{-}{/}{4}{?5} [{5}]{?}"
|
||||
},
|
||||
"break",
|
||||
"packages",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 341 KiB |
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ibireme/yyjson",
|
||||
"license": "MIT ( embed in source )",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.0",
|
||||
"author": "ibireme"
|
||||
}
|
||||
|
||||
Vendored
+31
-5
@@ -1407,6 +1407,7 @@ bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) {
|
||||
void yyjson_mut_doc_free(yyjson_mut_doc *doc) {
|
||||
if (doc) {
|
||||
yyjson_alc alc = doc->alc;
|
||||
memset(&doc->alc, 0, sizeof(alc));
|
||||
unsafe_yyjson_str_pool_release(&doc->str_pool, &alc);
|
||||
unsafe_yyjson_val_pool_release(&doc->val_pool, &alc);
|
||||
alc.free(alc.ctx, doc);
|
||||
@@ -8309,13 +8310,15 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
|
||||
bool cpy = (enc_table == enc_table_cpy);
|
||||
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
|
||||
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
|
||||
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
|
||||
const usize end_len = 2; /* '\n' and '\0' */
|
||||
|
||||
switch (unsafe_yyjson_get_type(val)) {
|
||||
case YYJSON_TYPE_RAW:
|
||||
str_len = unsafe_yyjson_get_len(val);
|
||||
str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
|
||||
check_str_len(str_len);
|
||||
incr_len(str_len + 1);
|
||||
incr_len(str_len + end_len);
|
||||
cur = write_raw(cur, str_ptr, str_len);
|
||||
break;
|
||||
|
||||
@@ -8323,7 +8326,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
|
||||
str_len = unsafe_yyjson_get_len(val);
|
||||
str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
|
||||
check_str_len(str_len);
|
||||
incr_len(str_len * 6 + 4);
|
||||
incr_len(str_len * 6 + 2 + end_len);
|
||||
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
|
||||
cur = write_string_noesc(cur, str_ptr, str_len);
|
||||
} else {
|
||||
@@ -8333,7 +8336,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
|
||||
break;
|
||||
|
||||
case YYJSON_TYPE_NUM:
|
||||
incr_len(32);
|
||||
incr_len(32 + end_len);
|
||||
cur = write_number(cur, val, flg);
|
||||
if (unlikely(!cur)) goto fail_num;
|
||||
break;
|
||||
@@ -8349,13 +8352,13 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
|
||||
break;
|
||||
|
||||
case YYJSON_TYPE_ARR:
|
||||
incr_len(4);
|
||||
incr_len(2 + end_len);
|
||||
byte_copy_2(cur, "[]");
|
||||
cur += 2;
|
||||
break;
|
||||
|
||||
case YYJSON_TYPE_OBJ:
|
||||
incr_len(4);
|
||||
incr_len(2 + end_len);
|
||||
byte_copy_2(cur, "{}");
|
||||
cur += 2;
|
||||
break;
|
||||
@@ -8364,6 +8367,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
|
||||
goto fail_type;
|
||||
}
|
||||
|
||||
if (newline) *cur++ = '\n';
|
||||
*cur = '\0';
|
||||
*dat_len = (usize)(cur - hdr);
|
||||
memset(err, 0, sizeof(yyjson_write_err));
|
||||
@@ -8436,6 +8440,7 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root,
|
||||
bool cpy = (enc_table == enc_table_cpy);
|
||||
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
|
||||
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
|
||||
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
|
||||
|
||||
alc_len = root->uni.ofs / sizeof(yyjson_val);
|
||||
alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64;
|
||||
@@ -8542,6 +8547,11 @@ ctn_end:
|
||||
}
|
||||
|
||||
doc_end:
|
||||
if (newline) {
|
||||
incr_len(2);
|
||||
*(cur - 1) = '\n';
|
||||
cur++;
|
||||
}
|
||||
*--cur = '\0';
|
||||
*dat_len = (usize)(cur - hdr);
|
||||
memset(err, 0, sizeof(yyjson_write_err));
|
||||
@@ -8615,6 +8625,7 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root,
|
||||
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
|
||||
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
|
||||
usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4;
|
||||
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
|
||||
|
||||
alc_len = root->uni.ofs / sizeof(yyjson_val);
|
||||
alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64;
|
||||
@@ -8745,6 +8756,10 @@ ctn_end:
|
||||
}
|
||||
|
||||
doc_end:
|
||||
if (newline) {
|
||||
incr_len(2);
|
||||
*cur++ = '\n';
|
||||
}
|
||||
*cur = '\0';
|
||||
*dat_len = (usize)(cur - hdr);
|
||||
memset(err, 0, sizeof(yyjson_write_err));
|
||||
@@ -8977,6 +8992,7 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root,
|
||||
bool cpy = (enc_table == enc_table_cpy);
|
||||
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
|
||||
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
|
||||
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
|
||||
|
||||
alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64;
|
||||
alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx));
|
||||
@@ -9087,6 +9103,11 @@ ctn_end:
|
||||
}
|
||||
|
||||
doc_end:
|
||||
if (newline) {
|
||||
incr_len(2);
|
||||
*(cur - 1) = '\n';
|
||||
cur++;
|
||||
}
|
||||
*--cur = '\0';
|
||||
*dat_len = (usize)(cur - hdr);
|
||||
err->code = YYJSON_WRITE_SUCCESS;
|
||||
@@ -9162,6 +9183,7 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root,
|
||||
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
|
||||
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
|
||||
usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4;
|
||||
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
|
||||
|
||||
alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64;
|
||||
alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx));
|
||||
@@ -9296,6 +9318,10 @@ ctn_end:
|
||||
}
|
||||
|
||||
doc_end:
|
||||
if (newline) {
|
||||
incr_len(2);
|
||||
*cur++ = '\n';
|
||||
}
|
||||
*cur = '\0';
|
||||
*dat_len = (usize)(cur - hdr);
|
||||
err->code = YYJSON_WRITE_SUCCESS;
|
||||
|
||||
Vendored
+35
-21
@@ -527,16 +527,16 @@ extern "C" {
|
||||
#define YYJSON_VERSION_MAJOR 0
|
||||
|
||||
/** The minor version of yyjson. */
|
||||
#define YYJSON_VERSION_MINOR 8
|
||||
#define YYJSON_VERSION_MINOR 9
|
||||
|
||||
/** The patch version of yyjson. */
|
||||
#define YYJSON_VERSION_PATCH 0
|
||||
|
||||
/** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
|
||||
#define YYJSON_VERSION_HEX 0x000800
|
||||
#define YYJSON_VERSION_HEX 0x000900
|
||||
|
||||
/** The version string of yyjson. */
|
||||
#define YYJSON_VERSION_STRING "0.8.0"
|
||||
#define YYJSON_VERSION_STRING "0.9.0"
|
||||
|
||||
/** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
|
||||
yyjson_api uint32_t yyjson_version(void);
|
||||
@@ -738,7 +738,7 @@ typedef uint32_t yyjson_read_flag;
|
||||
- Report error if double number is infinity.
|
||||
- Report error if string contains invalid UTF-8 character or BOM.
|
||||
- Report error on trailing commas, comments, inf and nan literals. */
|
||||
static const yyjson_read_flag YYJSON_READ_NOFLAG = 0 << 0;
|
||||
static const yyjson_read_flag YYJSON_READ_NOFLAG = 0;
|
||||
|
||||
/** Read the input data in-situ.
|
||||
This option allows the reader to modify and use input data to store string
|
||||
@@ -1067,7 +1067,7 @@ typedef uint32_t yyjson_write_flag;
|
||||
- Report error on inf or nan number.
|
||||
- Report error on invalid UTF-8 string.
|
||||
- Do not escape unicode or slash. */
|
||||
static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0 << 0;
|
||||
static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0;
|
||||
|
||||
/** Write JSON pretty with 4 space indent. */
|
||||
static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0;
|
||||
@@ -1096,6 +1096,10 @@ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5;
|
||||
This flag will override `YYJSON_WRITE_PRETTY` flag. */
|
||||
static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6;
|
||||
|
||||
/** Adds a newline character `\n` at the end of the JSON.
|
||||
This can be helpful for text editors or NDJSON. */
|
||||
static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7;
|
||||
|
||||
|
||||
|
||||
/** Result code for JSON writer */
|
||||
@@ -3695,7 +3699,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
|
||||
The `len` should be the length of the `val`, in bytes.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key/value strings are not copied, you should keep these strings
|
||||
@warning The key strings are not copied, you should keep these strings
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -4829,6 +4833,7 @@ yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) {
|
||||
yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) {
|
||||
if (doc) {
|
||||
yyjson_alc alc = doc->alc;
|
||||
memset(&doc->alc, 0, sizeof(alc));
|
||||
if (doc->str_pool) alc.free(alc.ctx, doc->str_pool);
|
||||
alc.free(alc.ctx, doc);
|
||||
}
|
||||
@@ -5668,6 +5673,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
|
||||
if (yyjson_likely(doc)) {
|
||||
yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
|
||||
if (yyjson_likely(val)) {
|
||||
_val = !!_val;
|
||||
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
|
||||
return val;
|
||||
}
|
||||
@@ -5920,7 +5926,8 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) {
|
||||
yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
|
||||
yyjson_mut_doc *doc, const bool *vals, size_t count) {
|
||||
yyjson_mut_arr_with_func({
|
||||
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)vals[i] << 3);
|
||||
bool _val = !!vals[i];
|
||||
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6872,6 +6879,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
|
||||
const char *_key,
|
||||
bool _val) {
|
||||
yyjson_mut_obj_add_func({
|
||||
_val = !!_val;
|
||||
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3);
|
||||
});
|
||||
}
|
||||
@@ -7730,33 +7738,39 @@ yyjson_api_inline bool yyjson_ptr_get_bool(
|
||||
}
|
||||
|
||||
/**
|
||||
Set provided `value` if the JSON Pointer (RFC 6901) exists and is type uint.
|
||||
Returns true if value at `ptr` exists and is the correct type, otherwise false.
|
||||
Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
|
||||
that fits in `uint64_t`. Returns true if successful, otherwise false.
|
||||
*/
|
||||
yyjson_api_inline bool yyjson_ptr_get_uint(
|
||||
yyjson_val *root, const char *ptr, uint64_t *value) {
|
||||
yyjson_val *val = yyjson_ptr_get(root, ptr);
|
||||
if (value && yyjson_is_uint(val)) {
|
||||
*value = unsafe_yyjson_get_uint(val);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
if (value && val) {
|
||||
uint64_t ret = val->uni.u64;
|
||||
if (unsafe_yyjson_is_uint(val) ||
|
||||
(unsafe_yyjson_is_sint(val) && !(ret >> 63))) {
|
||||
*value = ret;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint.
|
||||
Returns true if value at `ptr` exists and is the correct type, otherwise false.
|
||||
Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
|
||||
that fits in `int64_t`. Returns true if successful, otherwise false.
|
||||
*/
|
||||
yyjson_api_inline bool yyjson_ptr_get_sint(
|
||||
yyjson_val *root, const char *ptr, int64_t *value) {
|
||||
yyjson_val *val = yyjson_ptr_get(root, ptr);
|
||||
if (value && yyjson_is_sint(val)) {
|
||||
*value = unsafe_yyjson_get_sint(val);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
if (value && val) {
|
||||
int64_t ret = val->uni.i64;
|
||||
if (unsafe_yyjson_is_sint(val) ||
|
||||
(unsafe_yyjson_is_uint(val) && ret >= 0)) {
|
||||
*value = ret;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,7 @@ void ffPrepareCommandOption(FFdata* data)
|
||||
FFOptionsModules* const options = &instance.config.modules;
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
|
||||
ffPrepareCPUUsage();
|
||||
@@ -118,7 +118,7 @@ static void parseStructureCommand(
|
||||
}
|
||||
}
|
||||
|
||||
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
@@ -168,7 +168,7 @@ void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
|
||||
+20
-44
@@ -2,6 +2,7 @@
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void ffFontInit(FFfont* font)
|
||||
{
|
||||
@@ -66,59 +67,33 @@ void ffFontInitQt(FFfont* font, const char* data)
|
||||
//See https://doc.qt.io/qt-5/qfont.html#toString
|
||||
|
||||
//Family
|
||||
while(*data != ',' && *data != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&font->name, *data);
|
||||
++data;
|
||||
}
|
||||
if(*data != '\0')
|
||||
++data;
|
||||
data = ffStrbufAppendSUntilC(&font->name, data, ',');
|
||||
ffStrbufTrim(&font->name, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Size
|
||||
while(*data != ',' && *data != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&font->size, *data);
|
||||
++data;
|
||||
}
|
||||
if(*data != '\0')
|
||||
++data;
|
||||
data = ffStrbufAppendSUntilC(&font->size, data, ',');
|
||||
ffStrbufTrim(&font->size, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
#define FF_FONT_QT_SKIP_VALUE \
|
||||
while(*data != ',' && *data != '\0') \
|
||||
++data; \
|
||||
if(*data != '\0') \
|
||||
++data;
|
||||
|
||||
FF_FONT_QT_SKIP_VALUE //Pixel size
|
||||
FF_FONT_QT_SKIP_VALUE //Style hint
|
||||
FF_FONT_QT_SKIP_VALUE //Font weight
|
||||
FF_FONT_QT_SKIP_VALUE //Font style
|
||||
FF_FONT_QT_SKIP_VALUE //Underline
|
||||
FF_FONT_QT_SKIP_VALUE //Strike out
|
||||
FF_FONT_QT_SKIP_VALUE //Fixed pitch
|
||||
FF_FONT_QT_SKIP_VALUE //Always 0
|
||||
|
||||
#undef FF_FONT_QT_SKIP_VALUE
|
||||
|
||||
while(*data != '\0')
|
||||
//Style
|
||||
data = strrchr(data, ',');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
if (isalpha(*data))
|
||||
{
|
||||
while(*data == ' ')
|
||||
++data;
|
||||
|
||||
if(*data == '\0')
|
||||
break;
|
||||
|
||||
FFstrbuf* style = ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
while(*data != ' ' && *data != '\0')
|
||||
do
|
||||
{
|
||||
ffStrbufAppendC(style, *data);
|
||||
++data;
|
||||
}
|
||||
FFstrbuf* style = ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
data = ffStrbufAppendSUntilC(style, data, ' ');
|
||||
if (data) data++;
|
||||
} while (data);
|
||||
}
|
||||
|
||||
exit:
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
@@ -211,6 +186,7 @@ void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendS(&font->name, name);
|
||||
ffStrbufTrim(&font->name, '"');
|
||||
ffStrbufAppendS(&font->size, size);
|
||||
|
||||
fontInitPretty(font);
|
||||
|
||||
@@ -24,3 +24,7 @@ typedef struct FFformatarg
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, numArgs, arguments) do {\
|
||||
static_assert(sizeof(arguments) / sizeof(*(arguments)) == (numArgs), "Invalid number of format arguments");\
|
||||
ffParseFormatString((buffer), (formatstr), (numArgs), (arguments));\
|
||||
} while (0)
|
||||
|
||||
+3
-3
@@ -163,9 +163,6 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_THREADS
|
||||
"threads\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
@@ -241,6 +238,9 @@ 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
|
||||
|
||||
@@ -115,7 +115,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
#if __has_include(<wordexp.h>) // https://github.com/termux/termux-packages/pull/7056
|
||||
|
||||
wordexp_t exp;
|
||||
if(wordexp(in, &exp, WRDE_NOCMD) != 0)
|
||||
if(wordexp(in, &exp, 0) != 0)
|
||||
return false;
|
||||
|
||||
if (exp.we_wordc == 1)
|
||||
|
||||
@@ -235,6 +235,6 @@ void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
yyjson_mut_doc_set_root(jsonDoc, obj);
|
||||
}
|
||||
else
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
ffPrintError("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ static FFModuleBaseInfo* B[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* C[] = {
|
||||
(void*) &instance.config.modules.camera,
|
||||
(void*) &instance.config.modules.chassis,
|
||||
(void*) &instance.config.modules.command,
|
||||
(void*) &instance.config.modules.colors,
|
||||
@@ -124,6 +125,7 @@ static FFModuleBaseInfo* T[] = {
|
||||
(void*) &instance.config.modules.terminal,
|
||||
(void*) &instance.config.modules.terminalFont,
|
||||
(void*) &instance.config.modules.terminalSize,
|
||||
(void*) &instance.config.modules.terminalTheme,
|
||||
(void*) &instance.config.modules.title,
|
||||
(void*) &instance.config.modules.theme,
|
||||
NULL,
|
||||
|
||||
+4
-10
@@ -20,15 +20,9 @@ typedef struct FFNetworkingState {
|
||||
FFThreadType thread;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t timeout;
|
||||
} FFNetworkingState;
|
||||
|
||||
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout);
|
||||
|
||||
static inline bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer)
|
||||
{
|
||||
FFNetworkingState state;
|
||||
if(ffNetworkingSendHttpRequest(&state, host, path, headers))
|
||||
return ffNetworkingRecvHttpResponse(&state, buffer, timeout);
|
||||
return false;
|
||||
}
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer);
|
||||
|
||||
@@ -5,30 +5,50 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // For FreeBSD
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
static void connectAndSend(FFNetworkingState* state)
|
||||
static const char* connectAndSend(FFNetworkingState* state)
|
||||
{
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
|
||||
const char* ret = NULL;
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0)
|
||||
if(getaddrinfo(state->host.chars, "80", &(struct addrinfo) {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
{
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
ret = "socket() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (state->timeout > 0)
|
||||
{
|
||||
FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000;
|
||||
if (sec == 0) sec = 1;
|
||||
|
||||
#ifdef TCP_CONNECTIONTIMEOUT
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_KEEPINIT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_USER_TIMEOUT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
|
||||
{
|
||||
close(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
ret = "connect() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -37,6 +57,7 @@ static void connectAndSend(FFNetworkingState* state)
|
||||
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||
{
|
||||
close(state->sockfd);
|
||||
ret = "send() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -48,11 +69,13 @@ error:
|
||||
exit:
|
||||
ffStrbufDestroy(&state->host);
|
||||
ffStrbufDestroy(&state->command);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||
|
||||
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
ffStrbufInitS(&state->host, host);
|
||||
|
||||
@@ -66,22 +89,30 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
return !!state->thread;
|
||||
#else
|
||||
connectAndSend(state);
|
||||
return state->sockfd != -1;
|
||||
return state->thread ? NULL : "ffThreadCreate(connectAndSend) failed";
|
||||
}
|
||||
#endif
|
||||
|
||||
return connectAndSend(state);
|
||||
}
|
||||
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
if (!ffThreadJoin(state->thread, timeout))
|
||||
return false;
|
||||
return "ffThreadJoin() failed or timeout";
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state->sockfd == -1)
|
||||
return false;
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
@@ -91,14 +122,15 @@ bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, ui
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if(received > 0)
|
||||
{
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
close(state->sockfd);
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
|
||||
@@ -33,21 +33,20 @@ static const char* initWsaData(WSADATA* wsaData)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
static WSADATA wsaData;
|
||||
if (wsaData.wVersion == 0)
|
||||
{
|
||||
if (initWsaData(&wsaData) != NULL)
|
||||
const char* error = initWsaData(&wsaData);
|
||||
if (error != NULL)
|
||||
{
|
||||
wsaData.wVersion = (WORD) -1;
|
||||
return false;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (wsaData.wVersion == (WORD) -1)
|
||||
return false;
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
return "initWsaData() failed before";
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
@@ -55,26 +54,27 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
return false;
|
||||
return "getaddrinfo() failed";
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
return false;
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
{
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
struct sockaddr_in addr = {
|
||||
if(bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
.sin_port = 0,
|
||||
};
|
||||
if(bind(state->sockfd, (SOCKADDR *)&addr, sizeof(addr)) != 0)
|
||||
}, sizeof(struct sockaddr_in)) != 0)
|
||||
{
|
||||
printf("bind %d\n", WSAGetLastError());
|
||||
return false;
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,35 +93,52 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
return false;
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
|
||||
return true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
if (WaitForSingleObject((HANDLE) state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transfer, flags;
|
||||
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
return false;
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if(received > 0)
|
||||
{
|
||||
buffer->length += (uint32_t) received;
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int) ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length = recvStart + (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
closesocket(state->sockfd);
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
|
||||
+5
-21
@@ -96,39 +96,23 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result)
|
||||
}
|
||||
}
|
||||
|
||||
void ffParseTemperature(double celsius, FFstrbuf* buffer)
|
||||
{
|
||||
switch (instance.config.display.temperatureUnit)
|
||||
{
|
||||
case FF_TEMPERATURE_UNIT_CELSIUS:
|
||||
ffStrbufAppendF(buffer, "%.1f°C", celsius);
|
||||
break;
|
||||
case FF_TEMPERATURE_UNIT_FAHRENHEIT:
|
||||
ffStrbufAppendF(buffer, "%.1f°F", celsius * 1.8 + 32);
|
||||
break;
|
||||
case FF_TEMPERATURE_UNIT_KELVIN:
|
||||
ffStrbufAppendF(buffer, "%.1f K", celsius + 273.15);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
|
||||
{
|
||||
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
|
||||
{
|
||||
if((ffStrbufIgnCaseComp(gtk2, gtk3) == 0) && (ffStrbufIgnCaseComp(gtk2, gtk4) == 0))
|
||||
if((ffStrbufIgnCaseEqual(gtk2, gtk3)) && (ffStrbufIgnCaseEqual(gtk2, gtk4)))
|
||||
{
|
||||
ffStrbufAppend(buffer, gtk4);
|
||||
ffStrbufAppendS(buffer, " [GTK2/3/4]");
|
||||
}
|
||||
else if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
|
||||
else if(ffStrbufIgnCaseEqual(gtk2, gtk3))
|
||||
{
|
||||
ffStrbufAppend(buffer, gtk3);
|
||||
ffStrbufAppendS(buffer, " [GTK2/3], ");
|
||||
ffStrbufAppend(buffer, gtk4);
|
||||
ffStrbufAppendS(buffer, " [GTK4]");
|
||||
}
|
||||
else if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
|
||||
else if(ffStrbufIgnCaseEqual(gtk3, gtk4))
|
||||
{
|
||||
ffStrbufAppend(buffer, gtk2);
|
||||
ffStrbufAppendS(buffer, " [GTK2], ");
|
||||
@@ -147,7 +131,7 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
}
|
||||
else if(gtk2->length > 0 && gtk3->length > 0)
|
||||
{
|
||||
if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
|
||||
if(ffStrbufIgnCaseEqual(gtk2, gtk3))
|
||||
{
|
||||
ffStrbufAppend(buffer, gtk3);
|
||||
ffStrbufAppendS(buffer, " [GTK2/3]");
|
||||
@@ -162,7 +146,7 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
}
|
||||
else if(gtk3->length > 0 && gtk4->length > 0)
|
||||
{
|
||||
if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
|
||||
if(ffStrbufIgnCaseEqual(gtk3, gtk4))
|
||||
{
|
||||
ffStrbufAppend(buffer, gtk4);
|
||||
ffStrbufAppendS(buffer, " [GTK3/4]");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -11,6 +11,12 @@ typedef struct FFVersion
|
||||
uint32_t patch;
|
||||
} FFVersion;
|
||||
|
||||
typedef struct FFColorRangeConfig
|
||||
{
|
||||
uint8_t green;
|
||||
uint8_t yellow;
|
||||
} FFColorRangeConfig;
|
||||
|
||||
#define FF_VERSION_INIT ((FFVersion) {0})
|
||||
|
||||
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
|
||||
@@ -20,4 +26,3 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
|
||||
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFstrbuf* result);
|
||||
void ffParseTemperature(double celsius, FFstrbuf* buffer);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config)
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config)
|
||||
{
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
@@ -75,7 +75,7 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses)
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses)
|
||||
{
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
@@ -89,9 +89,9 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config
|
||||
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
const char* colorGreen = instance.config.display.percentColorGreen.chars;
|
||||
const char* colorYellow = instance.config.display.percentColorYellow.chars;
|
||||
const char* colorRed = instance.config.display.percentColorRed.chars;
|
||||
const char* colorGreen = options->percentColorGreen.chars;
|
||||
const char* colorYellow = options->percentColorYellow.chars;
|
||||
const char* colorRed = options->percentColorRed.chars;
|
||||
|
||||
if(percent != percent)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
|
||||
@@ -126,7 +126,7 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config
|
||||
ffStrbufAppendC(buffer, ')');
|
||||
}
|
||||
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config)
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config)
|
||||
{
|
||||
if (!ffStrStartsWithIgnCase(subkey, "percent-"))
|
||||
return false;
|
||||
@@ -160,7 +160,7 @@ bool ffPercentParseCommandOptions(const char* key, const char* subkey, const cha
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config)
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config)
|
||||
{
|
||||
if (!ffStrEqualsIgnCase(key, "percent"))
|
||||
return false;
|
||||
@@ -198,7 +198,7 @@ bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfi
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config)
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config)
|
||||
{
|
||||
if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow)
|
||||
return;
|
||||
|
||||
+6
-11
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -10,12 +11,6 @@ enum
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
};
|
||||
|
||||
typedef struct FFPercentConfig
|
||||
{
|
||||
uint8_t green;
|
||||
uint8_t yellow;
|
||||
} FFPercentConfig;
|
||||
|
||||
// if (green <= yellow)
|
||||
// [0, green]: print green
|
||||
// (green, yellow]: print yellow
|
||||
@@ -26,12 +21,12 @@ typedef struct FFPercentConfig
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): print red
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config);
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses);
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config);
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses);
|
||||
|
||||
typedef struct yyjson_val yyjson_val;
|
||||
typedef struct yyjson_mut_doc yyjson_mut_doc;
|
||||
typedef struct yyjson_mut_val yyjson_mut_val;
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config);
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config);
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config);
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config);
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config);
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config);
|
||||
|
||||
+4
-12
@@ -37,9 +37,9 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
ffParseFormatString(&key, &moduleArgs->key, 1, (FFformatarg[]){
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &moduleArgs->key, 1, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||
});
|
||||
}));
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments)
|
||||
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (moduleArgs)
|
||||
@@ -93,7 +93,7 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
@@ -101,14 +101,6 @@ void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFMod
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
printError(moduleName, moduleIndex, moduleArgs, FF_PRINT_TYPE_DEFAULT, message, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
void ffPrintColor(const FFstrbuf* colorValue)
|
||||
{
|
||||
//If the color is not set, this would reset in \033[m, which resets everything.
|
||||
|
||||
+10
-7
@@ -12,14 +12,17 @@ typedef enum FFPrintType {
|
||||
} FFPrintType;
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType);
|
||||
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments);
|
||||
static inline void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
ffPrintFormatString(moduleName, moduleIndex, moduleArgs, FF_PRINT_TYPE_DEFAULT, numArgs, arguments);
|
||||
}
|
||||
FF_C_PRINTF(5, 6) void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...);
|
||||
FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
|
||||
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PRINT_FORMAT_CHECKED(moduleName, moduleIndex, moduleArgs, printType, numArgs, arguments) do {\
|
||||
static_assert(sizeof(arguments) / sizeof(*(arguments)) == (numArgs), "Invalid number of format arguments");\
|
||||
ffPrintFormat((moduleName), (moduleIndex), (moduleArgs), (printType), (numArgs), (arguments));\
|
||||
} while (0)
|
||||
FF_C_PRINTF(5, 6) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...);
|
||||
void ffPrintColor(const FFstrbuf* colorValue);
|
||||
void ffPrintCharTimes(char c, uint32_t times);
|
||||
|
||||
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]);
|
||||
#define FF_PRINT_MODULE_FORMAT_HELP_CHECKED(moduleName, def, numArgs, args) do {\
|
||||
static_assert(sizeof(args) / sizeof(*(args)) == (numArgs), "Invalid number of format arguments");\
|
||||
ffPrintModuleFormatHelp((moduleName), (def), (numArgs), (args));\
|
||||
} while (0)
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/temps.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config)
|
||||
{
|
||||
if (celsius != celsius) // ignores NaN
|
||||
return;
|
||||
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
const char* colorGreen = options->tempColorGreen.chars;
|
||||
const char* colorYellow = options->tempColorYellow.chars;
|
||||
const char* colorRed = options->tempColorRed.chars;
|
||||
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
|
||||
if (!options->pipe)
|
||||
{
|
||||
if(green <= yellow)
|
||||
{
|
||||
if (celsius > yellow)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
|
||||
else if (celsius > green)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (celsius < yellow)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
|
||||
else if (celsius < green)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
|
||||
}
|
||||
}
|
||||
|
||||
switch (options->temperatureUnit)
|
||||
{
|
||||
case FF_TEMPERATURE_UNIT_CELSIUS:
|
||||
ffStrbufAppendF(buffer, "%.*f°C", options->tempNdigits, celsius);
|
||||
break;
|
||||
case FF_TEMPERATURE_UNIT_FAHRENHEIT:
|
||||
ffStrbufAppendF(buffer, "%.*f°F", options->tempNdigits, celsius * 1.8 + 32);
|
||||
break;
|
||||
case FF_TEMPERATURE_UNIT_KELVIN:
|
||||
ffStrbufAppendF(buffer, "%.*f K", options->tempNdigits, celsius + 273.15);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!options->pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* value, bool* useTemp, FFColorRangeConfig* config)
|
||||
{
|
||||
if (!ffStrStartsWithIgnCase(subkey, "temp"))
|
||||
return false;
|
||||
|
||||
if (subkey[strlen("temp")] == '\0')
|
||||
{
|
||||
*useTemp = ffOptionParseBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (subkey[strlen("temp")] != '-')
|
||||
return false;
|
||||
|
||||
subkey += strlen("temp-");
|
||||
|
||||
if (ffStrEqualsIgnCase(subkey, "green"))
|
||||
{
|
||||
uint32_t num = ffOptionParseUInt32(key, value);
|
||||
if (num > 100)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
|
||||
exit(480);
|
||||
}
|
||||
config->green = (uint8_t) num;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(subkey, "yellow"))
|
||||
{
|
||||
uint32_t num = ffOptionParseUInt32(key, value);
|
||||
if (num > 100)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
|
||||
exit(480);
|
||||
}
|
||||
config->yellow = (uint8_t) num;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config)
|
||||
{
|
||||
if (!ffStrEqualsIgnCase(key, "temp"))
|
||||
return false;
|
||||
|
||||
if (yyjson_is_bool(value))
|
||||
{
|
||||
*useTemp = yyjson_get_bool(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (yyjson_is_null(value))
|
||||
{
|
||||
*useTemp = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!yyjson_is_obj(value))
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s must be an object or a boolean\n", key);
|
||||
exit(480);
|
||||
}
|
||||
|
||||
*useTemp = true;
|
||||
|
||||
yyjson_val* greenVal = yyjson_obj_get(value, "green");
|
||||
if (greenVal)
|
||||
{
|
||||
int num = yyjson_get_int(greenVal);
|
||||
if (num < 0 || num > 100)
|
||||
{
|
||||
fputs("Error: usage: temp.green must be between 0 and 100\n", stderr);
|
||||
exit(480);
|
||||
}
|
||||
config->green = (uint8_t) num;
|
||||
}
|
||||
|
||||
yyjson_val* yellowVal = yyjson_obj_get(value, "yellow");
|
||||
if (yellowVal)
|
||||
{
|
||||
int num = yyjson_get_int(yellowVal);
|
||||
if (num < 0 || num > 100)
|
||||
{
|
||||
fputs("Error: usage: temp.yellow must be between 0 and 100\n", stderr);
|
||||
exit(480);
|
||||
}
|
||||
config->yellow = (uint8_t) num;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF_MAYBE_UNUSED bool defaultTemp, FFColorRangeConfig defaultConfig, bool temp, FFColorRangeConfig config)
|
||||
{
|
||||
assert(defaultTemp == false); // assume defaultTemp is always false
|
||||
|
||||
if (!temp)
|
||||
return;
|
||||
|
||||
if (config.green != defaultConfig.green || config.yellow != defaultConfig.yellow)
|
||||
{
|
||||
yyjson_mut_val* temp = yyjson_mut_obj_add_obj(doc, module, "temp");
|
||||
if (config.green != defaultConfig.green)
|
||||
yyjson_mut_obj_add_uint(doc, temp, "green", config.green);
|
||||
if (config.yellow != defaultConfig.yellow)
|
||||
yyjson_mut_obj_add_uint(doc, temp, "yellow", config.yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
yyjson_mut_obj_add_bool(doc, module, "temp", true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/parsing.h"
|
||||
|
||||
void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config);
|
||||
bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* value, bool* useTemp, FFColorRangeConfig* config);
|
||||
bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config);
|
||||
void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF_MAYBE_UNUSED bool defaultTemp, FFColorRangeConfig defaultConfig, bool temp, FFColorRangeConfig config);
|
||||
+36
-2
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <synchapi.h>
|
||||
#include <profileapi.h>
|
||||
#include <sysinfoapi.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static inline uint64_t ffTimeGetTick() //In msec
|
||||
@@ -45,3 +45,37 @@ static inline void ffTimeSleep(uint32_t msec)
|
||||
nanosleep(&(struct timespec){ msec / 1000, (long) (msec % 1000) * 1000000 }, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
#endif
|
||||
|
||||
// Not thread-safe
|
||||
static inline const char* ffTimeToFullStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
const struct tm* tm = localtime(&tsec);
|
||||
|
||||
static char buf[32];
|
||||
strftime(buf, __builtin_strlen("0000-00-00T00:00:00") + 1, "%FT%T", tm);
|
||||
snprintf(buf + __builtin_strlen("0000-00-00T00:00:00"), __builtin_strlen(".000") + 1, ".%03u", (unsigned) (msec % 1000));
|
||||
strftime(buf + __builtin_strlen("0000-00-00T00:00:00.000"), __builtin_strlen("+0000") + 1, "%z", tm);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Not thread-safe
|
||||
static inline const char* ffTimeToShortStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
|
||||
static char buf[32];
|
||||
strftime(buf, sizeof(buf), "%F %T", localtime(&tsec));
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
+170
-13
@@ -122,7 +122,10 @@
|
||||
{
|
||||
"long": "ds-force-drm",
|
||||
"desc": "Set if only DRM should be used to detect displays",
|
||||
"remark": "Use this option if you encountered problems with other detection method. Linux only",
|
||||
"remark": [
|
||||
"Use this option if you encountered problems with other detection method.",
|
||||
"Linux only"
|
||||
],
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"optional": true,
|
||||
@@ -537,7 +540,13 @@
|
||||
{
|
||||
"long": "percent-type",
|
||||
"desc": "Set the percentage output type",
|
||||
"remark": "1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number",
|
||||
"remark": [
|
||||
"1 for percentage number",
|
||||
"2 for bar",
|
||||
"3 for both",
|
||||
"6 for bar only",
|
||||
"9 for colored number"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 9
|
||||
@@ -647,7 +656,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temperature-unit",
|
||||
"long": "temp-unit",
|
||||
"desc": "Set the unit of the temperature",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
@@ -658,6 +667,41 @@
|
||||
},
|
||||
"default": "C"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temp-ndigits",
|
||||
"desc": "Set the number of digits to keep after the decimal point when printing temperature",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temp-color-green",
|
||||
"desc": "Set color used in green state of temperature values",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "green"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temp-color-yellow",
|
||||
"desc": "Set color used in yellow state of temperature values",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "light_yellow"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temp-color-red",
|
||||
"desc": "Set color used in red state of temperature values",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "light_red"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Library path": [
|
||||
@@ -963,6 +1007,14 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "diskio-detect-total",
|
||||
"desc": "Detect total bytes instead of current rate",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "diskio-name-prefix",
|
||||
"desc": "Show disks with given name prefix only",
|
||||
@@ -996,13 +1048,16 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "packages-winget",
|
||||
"desc": "Set if winget package count should be detected",
|
||||
"remark": "This option is extremely slow. You may need to increase value of '--processing-timeout' to make it actually work",
|
||||
"long": "packages-disabled",
|
||||
"desc": "A colon separated list of package managers to be disabled when detecting",
|
||||
"remark": [
|
||||
"Some detection methods can be very slow.",
|
||||
"You may need to increase value of '--processing-timeout' to make it actually work.",
|
||||
"Use `--packages-disabled none` to enable all."
|
||||
],
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
"type": "string",
|
||||
"default": "winget"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1013,7 +1068,9 @@
|
||||
"enum": {
|
||||
"none": "Disable this compact mode",
|
||||
"original": "Print original resolutions",
|
||||
"scaled": "Print scaled resolutions"
|
||||
"scaled": "Print scaled resolutions",
|
||||
"original-with-refresh-rate": "Print original resolutions with refresh rate",
|
||||
"scaled-with-refresh-rate": "Print scaled resolutions with refresh rate"
|
||||
},
|
||||
"default": "none"
|
||||
}
|
||||
@@ -1027,6 +1084,19 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "display-order",
|
||||
"desc": "Set the order should be used when printing displays",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"none": "Use the detected order",
|
||||
"asc": "Sort by display name ascendingly",
|
||||
"desc": "Sort by display name descendingly"
|
||||
},
|
||||
"default": "none"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "brightness-ddcci-sleep",
|
||||
"desc": "Set the sleep times (in ms) when sending DDC/CI requests",
|
||||
@@ -1052,7 +1122,10 @@
|
||||
{
|
||||
"long": "battery-use-setup-api",
|
||||
"desc": "Set if \"SetupAPI\" should be used on Windows to detect battery info",
|
||||
"remark": "SetupAPI supports multi batteries, but slower. Windows only",
|
||||
"remark": [
|
||||
"SetupAPI supports multi batteries, but slower.",
|
||||
"Windows only"
|
||||
],
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -1088,7 +1161,10 @@
|
||||
{
|
||||
"long": "de-slow-version-detection",
|
||||
"desc": "Set if DE version should be detected with slow operations",
|
||||
"remark": "Usually is not necessary. Linux only",
|
||||
"remark": [
|
||||
"It's only used as a fallback method. Please file a bug report if you encounter any issues.",
|
||||
"Linux only"
|
||||
],
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -1107,7 +1183,10 @@
|
||||
{
|
||||
"long": "gpu-driver-specific",
|
||||
"desc": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)",
|
||||
"remark": "Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported. Both require the latest proprietary driver to be installed",
|
||||
"remark": [
|
||||
"Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported.",
|
||||
"Both require the latest proprietary driver to be installed."
|
||||
],
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
@@ -1182,6 +1261,15 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-show-prefix-len",
|
||||
"desc": "Show network prefix length (/N) in local ip module",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-name-prefix",
|
||||
"desc": "Show interfaces with given interface name prefix only",
|
||||
@@ -1225,6 +1313,14 @@
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "netio-detect-total",
|
||||
"desc": "Detect total bytes instead of current rate",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "publicip-timeout",
|
||||
"desc": "Time in milliseconds to wait for the public ip server to respond",
|
||||
@@ -1342,6 +1438,44 @@
|
||||
"type": "num",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "colors-block-width",
|
||||
"desc": "Set the block width in spaces",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "colors-block-range-start",
|
||||
"desc": "Set the start range of colors in the blocks to print",
|
||||
"remark": [
|
||||
"Display colors 0-15 in the blocks. (16 colors)",
|
||||
"Display colors 0-7 in the blocks. (8 colors)",
|
||||
"Only works for `--colors-symbol block`.",
|
||||
"Must be in range 0-15",
|
||||
"See also `--colors-range-end`"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "colors-block-range-end",
|
||||
"desc": "Set the end range of colors in the blocks to print",
|
||||
"remark": [
|
||||
"Display colors 0-15 in the blocks. (16 colors)",
|
||||
"Display colors 0-7 in the blocks. (8 colors)",
|
||||
"Only works for `--colors-symbol block`.",
|
||||
"Must be in range 0-15",
|
||||
"See also `--colors-range-start`"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 15
|
||||
}
|
||||
}
|
||||
],
|
||||
"General module": [
|
||||
@@ -1407,6 +1541,29 @@
|
||||
"type": "num"
|
||||
},
|
||||
"pseudo": true
|
||||
},
|
||||
{
|
||||
"long": "<module>-temp-green",
|
||||
"desc": [
|
||||
"Threshold of temperature colors",
|
||||
"Value less then temp-green will be shown in green"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num"
|
||||
},
|
||||
"pseudo": true
|
||||
},
|
||||
{
|
||||
"long": "<module>-temp-yellow",
|
||||
"desc": [
|
||||
"Threshold of temperature colors",
|
||||
"Value greater than temp-green and less then yellow will be shown in yellow",
|
||||
"Value greater than temp-yellow will be shown in red"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num"
|
||||
},
|
||||
"pseudo": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
Usage: fastfetch -c <file>
|
||||
|
||||
Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.
|
||||
If the file is relative it looks in the following order:
|
||||
- relative to the current working directory
|
||||
- relative to ~/.local/share/fastfetch/presets/
|
||||
- relative to /usr/share/fastfetch/presets/
|
||||
Fastfetch provides some default presets. List them with "fastfetch --list-presets".
|
||||
@@ -1,15 +1,15 @@
|
||||
A format string is a string that contains placeholders for values.
|
||||
These placeholders begin with a '{', containing the index of the value, and end with a '}'.
|
||||
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce
|
||||
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce "Values: First (My second val)".
|
||||
The format string can contain placeholders in any order and have multiple occurrences.
|
||||
To include spaces when setting from the command line, surround the whole string with double quotes (").
|
||||
|
||||
If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
|
||||
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
|
||||
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second v
|
||||
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again.
|
||||
|
||||
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not
|
||||
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces aro
|
||||
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not counted as the beginning of a placeholder.
|
||||
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces around it.
|
||||
If the last placeholder isn't closed, it will be treated like it was at the end of the format string.
|
||||
|
||||
To only print something if a variable is set, use "{?<index>} ... {?}".
|
||||
@@ -17,7 +17,7 @@ For example, to only print a second value if it is set, use "{?2} Second value:
|
||||
If a "{?}" is found without an opener, it is printed as is.
|
||||
|
||||
To only print something if a variable is not set, do the same as with if, just replace every '?' with a '!'.
|
||||
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}"
|
||||
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}".
|
||||
|
||||
To stop formatting at any point in the format string, use "{-}".
|
||||
|
||||
@@ -25,7 +25,7 @@ To print something with color, start a placeholder with a '#' and then the linux
|
||||
"\033[" at the start, and an 'm' at the end is automatically added, so don't do that.
|
||||
A "{#}" is equivalent to a "{#0}" and resets everything to normal.
|
||||
For example to print something pink and underline, use "{#4;35}...{#}".
|
||||
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Sele
|
||||
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||
Which escape codes are supported and how they look is defined by your terminal.
|
||||
|
||||
If a format string evaluates to an empty value, the whole line in the output will be discarded.
|
||||
|
||||
@@ -20,6 +20,14 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
continue;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
|
||||
continue;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), ¤tCapacity) != NULL || currentCapacity <= 0)
|
||||
continue;
|
||||
|
||||
bool boolValue;
|
||||
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
@@ -30,16 +38,6 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
battery->capacity = 0.0/0.0;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
|
||||
continue;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), ¤tCapacity) != NULL || currentCapacity <= 0)
|
||||
continue;
|
||||
|
||||
battery->capacity = currentCapacity * 100.0 / maxCapacity;
|
||||
|
||||
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
|
||||
|
||||
@@ -54,13 +54,13 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Ctritical, ");
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
}
|
||||
|
||||
int acadStatus;
|
||||
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus)
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "AC connected");
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
||||
|
||||
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
@@ -68,6 +70,26 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
|
||||
ffStrbufTrimRightSpace(&result->status);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
// Unknown, Charging, Discharging, Not charging, Full
|
||||
if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
|
||||
ffStrbufSetStatic(&result->status, "AC Connected");
|
||||
else if (ffStrbufEqualS(&result->status, "Unknown"))
|
||||
ffStrbufClear(&result->status);
|
||||
|
||||
ffStrbufAppendS(dir, "/capacity_level");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
|
||||
{
|
||||
if (result->status.length)
|
||||
ffStrbufAppendS(&result->status, ", Critical");
|
||||
else
|
||||
ffStrbufSetStatic(&result->status, "Critical");
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->serial);
|
||||
ffStrbufAppendS(dir, "/serial_number");
|
||||
if (ffReadFileBuffer(dir->chars, &result->serial))
|
||||
|
||||
@@ -114,7 +114,7 @@ static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
FF_SUPPRESS_IO();
|
||||
// Ref: https://github.com/rockowitz/ddcutil/issues/344
|
||||
if (ffddca_init("--disable-watch-displays", -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0)
|
||||
if (ffddca_init(NULL, -1 /*DDCA_SYSLOG_NOT_SET*/, 1 /*DDCA_INIT_OPTIONS_DISABLE_CONFIG_FILE*/) < 0)
|
||||
return "ddca_init() failed";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFCameraResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf id;
|
||||
FFstrbuf colorspace;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} FFCameraResult;
|
||||
|
||||
const char* ffDetectCamera(FFlist* result /* list of FFCameraResult */);
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "camera.h"
|
||||
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
|
||||
#define FF_TERMUX_API_PARAM "CameraInfo"
|
||||
|
||||
static inline void wrapYyjsonFree(yyjson_doc** doc)
|
||||
{
|
||||
assert(doc);
|
||||
if (*doc)
|
||||
yyjson_doc_free(*doc);
|
||||
}
|
||||
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
if(ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
FF_TERMUX_API_PATH,
|
||||
FF_TERMUX_API_PARAM,
|
||||
NULL
|
||||
}))
|
||||
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
|
||||
|
||||
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
|
||||
if (!doc)
|
||||
return "Failed to parse camera info";
|
||||
|
||||
yyjson_val* root = yyjson_doc_get_root(doc);
|
||||
if (!yyjson_is_arr(root))
|
||||
return "Camera info result is not a JSON array";
|
||||
|
||||
yyjson_val* device;
|
||||
size_t idx, max;
|
||||
yyjson_arr_foreach(root, idx, max, device)
|
||||
{
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
{
|
||||
const char* facing = yyjson_get_str(yyjson_obj_get(device, "facing"));
|
||||
if (facing)
|
||||
ffStrbufInitF(&camera->name, "builtin-%s", facing);
|
||||
else
|
||||
ffStrbufInitStatic(&camera->name, "Unknown");
|
||||
}
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id")));
|
||||
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
|
||||
if (yyjson_is_obj(sizes))
|
||||
{
|
||||
camera->width = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "width"));
|
||||
camera->height = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "height"));
|
||||
}
|
||||
else
|
||||
camera->width = camera->height = 0;
|
||||
ffStrbufInit(&camera->colorspace);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "camera.h"
|
||||
|
||||
#import <AVFoundation/AVCaptureDevice.h>
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
|
||||
if (!session)
|
||||
return "Failed to create AVCaptureDeviceDiscoverySession";
|
||||
|
||||
for (AVCaptureDevice* device in session.devices)
|
||||
{
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&camera->name, device.localizedName.UTF8String);
|
||||
ffStrbufInitS(&camera->vendor, device.manufacturer.UTF8String);
|
||||
ffStrbufInitS(&camera->id, device.uniqueID.UTF8String);
|
||||
switch (device.activeColorSpace)
|
||||
{
|
||||
case AVCaptureColorSpace_sRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case AVCaptureColorSpace_P3_D65: ffStrbufInitStatic(&camera->colorspace, "P3-D65"); break;
|
||||
case 2 /*AVCaptureColorSpace_HLG_BT2020*/: ffStrbufInitStatic(&camera->colorspace, "BT2020-HLG"); break;
|
||||
case 3 /*AVCaptureColorSpace_AppleLog*/: ffStrbufInitStatic(&camera->colorspace, "AppleLog"); break;
|
||||
}
|
||||
|
||||
CMVideoDimensions size = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription);
|
||||
camera->width = size.width < 0 ? 0 : (uint32_t) size.width;
|
||||
camera->height = size.height < 0 ? 0 : (uint32_t) size.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "camera.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
#include <linux/videodev2.h>
|
||||
#endif
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
char path[] = "/dev/videoN";
|
||||
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
path[sizeof(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
break;
|
||||
|
||||
struct v4l2_capability cap = {};
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
continue;
|
||||
|
||||
struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
|
||||
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&camera->name, (const char*) cap.card);
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInitS(&camera->id, (const char*) cap.bus_info);
|
||||
switch (fmt.fmt.pix.colorspace)
|
||||
{
|
||||
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
|
||||
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
|
||||
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.808"); break;
|
||||
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
|
||||
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
|
||||
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
|
||||
case V4L2_COLORSPACE_REC709:
|
||||
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case V4L2_COLORSPACE_OPRGB: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
|
||||
case V4L2_COLORSPACE_BT2020: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case V4L2_COLORSPACE_RAW: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
|
||||
case V4L2_COLORSPACE_DCI_P3: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
default: ffStrbufInit(&camera->colorspace); break;
|
||||
}
|
||||
camera->width = fmt.fmt.pix.width;
|
||||
camera->height = fmt.fmt.pix.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(result);
|
||||
return "Fastfetch was compiled without <linux/videodev2.h>";
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
extern "C" {
|
||||
#include "camera.h"
|
||||
#include "common/library.h"
|
||||
}
|
||||
#include "util/windows/com.hpp"
|
||||
#include "util/windows/unicode.hpp"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
|
||||
template <typename Fn>
|
||||
struct on_scope_exit {
|
||||
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
|
||||
~on_scope_exit() { this->_fn(); }
|
||||
|
||||
private:
|
||||
Fn _fn;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(mfplat, NULL, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
|
||||
FF_LIBRARY_LOAD(mf, NULL, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
|
||||
|
||||
const char* error = ffInitCom();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
IMFAttributes* FF_AUTO_RELEASE_COM_OBJECT attrs = nullptr;
|
||||
if (FAILED(ffMFCreateAttributes(&attrs, 1)))
|
||||
return "MFCreateAttributes() failed";
|
||||
|
||||
if (FAILED(attrs->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
)))
|
||||
return "SetGUID(MF_*) failed";
|
||||
|
||||
IMFActivate** devices = NULL;
|
||||
uint32_t count;
|
||||
|
||||
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count)))
|
||||
return "MFEnumDeviceSources() failed";
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
IMFActivate* device = devices[i];
|
||||
|
||||
wchar_t buffer[256];
|
||||
uint32_t length = 0;
|
||||
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitNWS(&camera->name, length, buffer);
|
||||
ffStrbufInit(&camera->colorspace);
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInit(&camera->id);
|
||||
camera->width = 0;
|
||||
camera->height = 0;
|
||||
|
||||
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0)
|
||||
ffStrbufSetNWS(&camera->id, length, buffer);
|
||||
|
||||
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
|
||||
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source))))
|
||||
continue;
|
||||
|
||||
on_scope_exit destroySource([&] { source->Shutdown(); });
|
||||
|
||||
IMFPresentationDescriptor* FF_AUTO_RELEASE_COM_OBJECT pd = nullptr;
|
||||
if (FAILED(source->CreatePresentationDescriptor(&pd)))
|
||||
continue;
|
||||
|
||||
IMFStreamDescriptor* FF_AUTO_RELEASE_COM_OBJECT sd = NULL;
|
||||
BOOL selected;
|
||||
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd)))
|
||||
continue;
|
||||
|
||||
IMFMediaTypeHandler* FF_AUTO_RELEASE_COM_OBJECT handler = NULL;
|
||||
if (FAILED(sd->GetMediaTypeHandler(&handler)))
|
||||
continue;
|
||||
|
||||
DWORD mediaTypeCount;
|
||||
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount)))
|
||||
continue;
|
||||
|
||||
// Assume first type is the maximum resolution
|
||||
IMFMediaType* FF_AUTO_RELEASE_COM_OBJECT type = NULL;
|
||||
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
|
||||
{
|
||||
GUID majorType;
|
||||
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
|
||||
continue;
|
||||
|
||||
MFVideoPrimaries primaries;
|
||||
static_assert(sizeof(primaries) == sizeof(uint32_t), "");
|
||||
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries)))
|
||||
{
|
||||
switch (primaries)
|
||||
{
|
||||
case MFVideoPrimaries_BT709: ffStrbufSetStatic(&camera->colorspace, "sRGB"); break;
|
||||
case MFVideoPrimaries_BT470_2_SysM:
|
||||
case MFVideoPrimaries_BT470_2_SysBG: ffStrbufSetStatic(&camera->colorspace, "NTSC"); break;
|
||||
case MFVideoPrimaries_SMPTE170M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M"); break;
|
||||
case MFVideoPrimaries_SMPTE240M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M"); break;
|
||||
case MFVideoPrimaries_EBU3213: ffStrbufSetStatic(&camera->colorspace, "EBU 3213"); break;
|
||||
case MFVideoPrimaries_SMPTE_C: ffStrbufSetStatic(&camera->colorspace, "SMPTE C"); break;
|
||||
case MFVideoPrimaries_BT2020: ffStrbufSetStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case MFVideoPrimaries_XYZ: ffStrbufSetStatic(&camera->colorspace, "XYZ"); break;
|
||||
case MFVideoPrimaries_DCI_P3: ffStrbufSetStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
case MFVideoPrimaries_ACES: ffStrbufSetStatic(&camera->colorspace, "ACES"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &camera->width, &camera->height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CoTaskMemFree(devices);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -13,10 +13,12 @@ typedef struct FFCPUResult
|
||||
uint16_t coresLogical;
|
||||
uint16_t coresOnline;
|
||||
|
||||
double frequencyMin; // GHz
|
||||
double frequencyBase; // GHz
|
||||
double frequencyMax; // GHz
|
||||
double frequencyMin; // GHz
|
||||
|
||||
double temperature;
|
||||
} FFCPUResult;
|
||||
|
||||
const char* ffCPUDetectByCpuid(FFCPUResult* cpu);
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
|
||||
@@ -60,14 +60,13 @@ static const char* detectFrequency(FFCPUResult* cpu)
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
|
||||
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
|
||||
}
|
||||
else
|
||||
cpu->frequencyMax = 0.0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
|
||||
if(cpu->frequencyMax > 0.0)
|
||||
|
||||
@@ -11,8 +11,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresLogical = cpu->coresPhysical;
|
||||
cpu->coresOnline = cpu->coresPhysical;
|
||||
|
||||
cpu->frequencyMin = ffSysctlGetInt("hw.clockrate", 0) / 1000.0;
|
||||
cpu->frequencyMax = cpu->frequencyMin;
|
||||
int clockRate = ffSysctlGetInt("hw.clockrate", 0);
|
||||
cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0;
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp)
|
||||
|
||||
+137
-27
@@ -4,6 +4,7 @@
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <stdlib.h>
|
||||
@@ -16,7 +17,10 @@
|
||||
static void detectAndroid(FFCPUResult* cpu)
|
||||
{
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
ffSettingsGetAndroidProperty("ro.soc.model", &cpu->name);
|
||||
ffStrbufClear(&cpu->vendor); // We usually detect the vendor of CPU core as ARM, but instead we want the vendor of SOC
|
||||
}
|
||||
if (cpu->vendor.length == 0)
|
||||
{
|
||||
if (!ffSettingsGetAndroidProperty("ro.soc.manufacturer", &cpu->vendor))
|
||||
@@ -34,6 +38,10 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
FF_AUTO_FREE char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
#ifdef __aarch64__
|
||||
FF_STRBUF_AUTO_DESTROY implementer = ffStrbufCreate();
|
||||
#endif
|
||||
|
||||
while(getline(&line, &len, cpuinfo) != -1)
|
||||
{
|
||||
//Stop after the first CPU
|
||||
@@ -47,39 +55,103 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
|
||||
ffParsePropLine(line, "isa :", cpuIsa) ||
|
||||
ffParsePropLine(line, "uarch :", cpuUarch) ||
|
||||
|
||||
#ifdef __aarch64__
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", &implementer)) ||
|
||||
#endif
|
||||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
// https://github.com/util-linux/util-linux/blob/2cd89de14549d2b2c079a4f8b73f75500d229fee/sys-utils/lscpu-arm.c#L286
|
||||
if (cpu->vendor.length == 0 && implementer.length > 2 /* 0xX */)
|
||||
{
|
||||
uint32_t implId = (uint32_t) strtoul(implementer.chars, NULL, 16);
|
||||
switch (implId)
|
||||
{
|
||||
case 0x41: ffStrbufSetStatic(&cpu->vendor, "ARM"); break;
|
||||
case 0x42: ffStrbufSetStatic(&cpu->vendor, "Broadcom"); break;
|
||||
case 0x48: ffStrbufSetStatic(&cpu->vendor, "HiSilicon"); break;
|
||||
case 0x4e: ffStrbufSetStatic(&cpu->vendor, "Nvidia"); break;
|
||||
case 0x51: ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); break;
|
||||
case 0x53: ffStrbufSetStatic(&cpu->vendor, "Samsung"); break;
|
||||
case 0x61: ffStrbufSetStatic(&cpu->vendor, "Apple"); break;
|
||||
case 0x69: ffStrbufSetStatic(&cpu->vendor, "Intel"); break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static double getGHz(const char* file)
|
||||
static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
|
||||
if(ffAppendFileBuffer(file, &content))
|
||||
uint32_t baseLen = basePath->length;
|
||||
ffStrbufAppendS(basePath, cpuinfoFileName);
|
||||
bool ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
|
||||
if (scalingFileName)
|
||||
{
|
||||
double herz = ffStrbufToDouble(&content);
|
||||
|
||||
//ffStrbufToDouble failed
|
||||
if(herz != herz)
|
||||
return 0;
|
||||
|
||||
herz /= 1000.0; //to MHz
|
||||
return herz / 1000.0; //to GHz
|
||||
ffStrbufAppendS(basePath, scalingFileName);
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return 0.0/0.0;
|
||||
}
|
||||
|
||||
static double getFrequency(const char* info, const char* scaling)
|
||||
static bool detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
double frequency = getGHz(info);
|
||||
if(frequency > 0.0)
|
||||
return frequency;
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/cpufreq/");
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(path.chars);
|
||||
if (!dir) return false;
|
||||
|
||||
return getGHz(scaling);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (ffStrStartsWith(entry->d_name, "policy") && isdigit(entry->d_name[strlen("policy")]))
|
||||
{
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
double fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
|
||||
if (fbase == fbase)
|
||||
{
|
||||
if (cpu->frequencyBase == cpu->frequencyBase)
|
||||
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
|
||||
else
|
||||
cpu->frequencyBase = fbase;
|
||||
}
|
||||
double fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
|
||||
if (fmax == fmax)
|
||||
{
|
||||
if (cpu->frequencyMax == cpu->frequencyMax)
|
||||
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
|
||||
else
|
||||
cpu->frequencyMax = fmax;
|
||||
}
|
||||
double fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
|
||||
if (fmin == fmin)
|
||||
{
|
||||
if (cpu->frequencyMin == cpu->frequencyMin)
|
||||
cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin;
|
||||
else
|
||||
cpu->frequencyMin = fmin;
|
||||
}
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static double detectCPUTemp(void)
|
||||
@@ -121,6 +193,44 @@ static void parseIsa(FFstrbuf* cpuIsa)
|
||||
}
|
||||
}
|
||||
|
||||
void detectAsahi(FFCPUResult* cpu)
|
||||
{
|
||||
// In Asahi Linux, reading /proc/device-tree/compatible gives
|
||||
// information on the device model. It consists of 3 NUL terminated
|
||||
// strings, the second of which gives the actual SoC model. But it
|
||||
// is not the marketing name, i.e. for M2 there is "apple,t8112" in
|
||||
// the compatible string.
|
||||
if (cpu->name.length == 0 && ffStrbufEqualS(&cpu->vendor, "Apple"))
|
||||
{
|
||||
char content[32];
|
||||
ssize_t length = ffReadFileData("/proc/device-tree/compatible", sizeof(content), content);
|
||||
if (length <= 0) return;
|
||||
|
||||
// get the second NUL terminated string
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
@@ -137,16 +247,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
|
||||
|
||||
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
|
||||
if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY))
|
||||
{
|
||||
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
|
||||
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000;
|
||||
}
|
||||
if (!detectFrequency(cpu) || cpu->frequencyBase != cpu->frequencyBase)
|
||||
cpu->frequencyBase = ffStrbufToDouble(&cpuMHz) / 1000;
|
||||
|
||||
if(cpuUarch.length > 0)
|
||||
{
|
||||
@@ -167,6 +269,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectAndroid(cpu);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__aarch64__)
|
||||
detectAsahi(cpu);
|
||||
#endif
|
||||
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
@@ -195,6 +301,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pstart = buffer.chars;
|
||||
}
|
||||
}
|
||||
|
||||
while ((pstart = strstr(pstart, "Model name:")))
|
||||
|
||||
@@ -64,50 +64,53 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
return "No active CPU is found in SMBIOS data";
|
||||
}
|
||||
|
||||
double speed;
|
||||
if (data->MaxSpeed > 0 && data->MaxSpeed < 30000) // VMware reports weird values
|
||||
speed = data->MaxSpeed / 1000.0;
|
||||
else
|
||||
speed = data->CurrentSpeed / 1000.0;
|
||||
{
|
||||
double speed = data->MaxSpeed / 1000.0;
|
||||
if (cpu->frequencyBase < speed)
|
||||
cpu->frequencyMax = speed;
|
||||
}
|
||||
|
||||
if (cpu->frequencyMax < speed)
|
||||
cpu->frequencyMax = speed;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByOS(FFCPUResult* cpu)
|
||||
static const char* detectNCores(FFCPUResult* cpu)
|
||||
{
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
|
||||
if (length == 0)
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
|
||||
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
|
||||
if (!pProcessorInfo || !GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
||||
|
||||
for(
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
{
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
|
||||
if (length == 0)
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
|
||||
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
|
||||
if (pProcessorInfo && GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
|
||||
if(ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if(ptr->Relationship == RelationGroup)
|
||||
{
|
||||
for(
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
|
||||
{
|
||||
if(ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if(ptr->Relationship == RelationGroup)
|
||||
{
|
||||
cpu->coresOnline += ptr->Group.GroupInfo->ActiveProcessorCount;
|
||||
cpu->coresLogical += ptr->Group.GroupInfo->MaximumProcessorCount;
|
||||
}
|
||||
cpu->coresOnline += ptr->Group.GroupInfo[index].ActiveProcessorCount;
|
||||
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
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";
|
||||
@@ -115,24 +118,34 @@ static const char* detectByOS(FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t mhz;
|
||||
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||
cpu->frequencyMin = cpu->frequencyMax = mhz / 1000.0;
|
||||
cpu->frequencyBase = mhz / 1000.0;
|
||||
}
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
|
||||
if (cpu->coresLogical == 0)
|
||||
{
|
||||
DWORD cores;
|
||||
if (RegQueryInfoKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", NULL, NULL, &cores, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* error = detectByOS(cpu);
|
||||
detectNCores(cpu);
|
||||
|
||||
const char* error = detectByRegistry(cpu);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
if(options->temp)
|
||||
ffDetectSmbiosTemp(&cpu->temperature, NULL);
|
||||
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -68,18 +68,33 @@ static bool detectCursorFromEnv(FFCursorResult* result)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool detectCursorHyprcursor(FFCursorResult* result)
|
||||
{
|
||||
const char* hyprcursor_theme = getenv("HYPRCURSOR_THEME");
|
||||
|
||||
if(!ffStrSet(hyprcursor_theme))
|
||||
return false;
|
||||
|
||||
ffStrbufAppendS(&result->theme, hyprcursor_theme);
|
||||
ffStrbufAppendS(&result->size, getenv("HYPRCURSOR_SIZE"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffDetectCursor(FFCursorResult* result)
|
||||
{
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
|
||||
|
||||
if(ffStrbufCompS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG) == 0)
|
||||
if(ffStrbufEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG))
|
||||
ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY))
|
||||
ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA))
|
||||
detectCursorFromConfigFile("kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
|
||||
detectCursorFromConfigFile("lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_HYPRLAND) && detectCursorHyprcursor(result))
|
||||
return;
|
||||
else if(
|
||||
!detectCursorGTK(result) &&
|
||||
!detectCursorFromEnv(result) &&
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
if(result->length == 0)
|
||||
@@ -21,7 +21,7 @@ static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks);
|
||||
|
||||
static int compareDisks(const void* disk1, const void* disk2)
|
||||
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
{
|
||||
return ffStrbufCompAlphabetically(&((const FFDisk*) disk1)->mountpoint, &((const FFDisk*) disk2)->mountpoint);
|
||||
return ffStrbufComp(&disk1->mountpoint, &disk2->mountpoint);
|
||||
}
|
||||
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
@@ -18,7 +18,7 @@ const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
|
||||
//Note that we sort alphabetically here for a better ordering when printing the list,
|
||||
// so the check must be done in reverse order
|
||||
ffListSort(disks, compareDisks);
|
||||
ffListSort(disks, (void*) compareDisks);
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
|
||||
{
|
||||
if(disk->bytesTotal == 0)
|
||||
|
||||
@@ -17,6 +17,8 @@ typedef struct FFDisk
|
||||
|
||||
uint32_t filesUsed;
|
||||
uint32_t filesTotal;
|
||||
|
||||
uint64_t createTime;
|
||||
} FFDisk;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <libgeom.h>
|
||||
@@ -130,6 +131,10 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
if(fs->f_flags & MNT_RDONLY)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
|
||||
struct stat st;
|
||||
if(stat(fs->f_mntonname, &st) == 0)
|
||||
disk->createTime = (uint64_t)((st.st_birthtimespec.tv_sec * 1000) + (st.st_birthtimespec.tv_nsec / 1000000));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifdef __USE_LARGEFILE64
|
||||
@@ -41,6 +41,10 @@ static bool isPhysicalDevice(const struct mntent* device)
|
||||
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
|
||||
return false;
|
||||
|
||||
//#731
|
||||
if(ffStrEquals(device->mnt_type, "bcachefs"))
|
||||
return true;
|
||||
|
||||
if(
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices
|
||||
@@ -237,6 +241,13 @@ static void detectStats(FFDisk* disk)
|
||||
|
||||
if(fs.f_flag & ST_RDONLY)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
|
||||
disk->createTime = 0;
|
||||
#ifdef FF_HAVE_STATX
|
||||
struct statx stx;
|
||||
if (statx(0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME))
|
||||
disk->createTime = (uint64_t)((stx.stx_btime.tv_sec * 1000) + (stx.stx_btime.tv_nsec / 1000000));
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
@@ -15,7 +15,7 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
const wchar_t* mountpoint = buf + i;
|
||||
wchar_t* mountpoint = buf + i;
|
||||
|
||||
UINT driveType = GetDriveTypeW(mountpoint);
|
||||
if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
@@ -25,13 +25,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
}
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
|
||||
wchar_t volumeName[64];
|
||||
if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
|
||||
ffStrbufInitWS(&disk->mountFrom, volumeName);
|
||||
else
|
||||
ffStrbufInit(&disk->mountFrom);
|
||||
|
||||
if(!GetDiskFreeSpaceExW(
|
||||
mountpoint,
|
||||
@@ -78,6 +71,23 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -9,6 +9,8 @@ static uint64_t time1;
|
||||
|
||||
void ffPrepareDiskIO(FFDiskIOOptions* options)
|
||||
{
|
||||
if (options->detectTotal) return;
|
||||
|
||||
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
|
||||
ffDiskIOGetIoCounters(&ioCounters1, options);
|
||||
time1 = ffTimeGetNow();
|
||||
@@ -17,6 +19,15 @@ void ffPrepareDiskIO(FFDiskIOOptions* options)
|
||||
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
if (options->detectTotal)
|
||||
{
|
||||
error = ffDiskIOGetIoCounters(result, options);
|
||||
if (error)
|
||||
return error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (time1 == 0)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define FF_WM_PRETTY_XFWM4 "Xfwm4"
|
||||
#define FF_WM_PRETTY_OPENBOX "Openbox"
|
||||
#define FF_WM_PRETTY_I3 "i3"
|
||||
#define FF_WM_PRETTY_HYPRLAND "Hyprland"
|
||||
#define FF_WM_PRETTY_WAYFIRE "Wayfire"
|
||||
#define FF_WM_PRETTY_SWAY "Sway"
|
||||
#define FF_WM_PRETTY_BSPWM "bspwm"
|
||||
|
||||
@@ -143,7 +143,7 @@ static inline const char* drmType2Name(uint32_t connector_type)
|
||||
return "DPI";
|
||||
case DRM_MODE_CONNECTOR_WRITEBACK:
|
||||
return "Writeback";
|
||||
case DRM_MODE_CONNECTOR_SPI:
|
||||
case 19 /*DRM_MODE_CONNECTOR_SPI*/:
|
||||
return "SPI";
|
||||
case 20 /*DRM_MODE_CONNECTOR_USB*/:
|
||||
return "USB";
|
||||
@@ -250,8 +250,8 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
drmModeCrtc* crtc = ffdrmModeGetCrtc(fd, encoder->crtc_id);
|
||||
if (crtc)
|
||||
{
|
||||
width = crtc->mode.vdisplay;
|
||||
height = crtc->mode.hdisplay;
|
||||
width = crtc->mode.hdisplay;
|
||||
height = crtc->mode.vdisplay;
|
||||
refreshRate = crtc->mode.vrefresh;
|
||||
if (refreshRate == 0)
|
||||
{
|
||||
|
||||
@@ -52,6 +52,9 @@ static const char* parseEnv(void)
|
||||
if(getenv("TDE_FULL_SESSION") != NULL)
|
||||
return "Trinity";
|
||||
|
||||
if(getenv("HYPRLAND_CMD") != NULL)
|
||||
return "Hyprland";
|
||||
|
||||
#ifdef __linux__
|
||||
if(
|
||||
getenv("WAYLAND_DISPLAY") != NULL &&
|
||||
@@ -116,6 +119,8 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name)
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_ICEWM);
|
||||
else if(ffStrEqualsIgnCase(name, "dtwm"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DTWM);
|
||||
else if(ffStrEqualsIgnCase(name, "hyprland"))
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_HYPRLAND);
|
||||
}
|
||||
|
||||
static void applyNameIfWM(FFDisplayServerResult* result, const char* processName)
|
||||
|
||||
@@ -6,6 +6,8 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
|
||||
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
|
||||
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
|
||||
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
|
||||
const char* FF_GPU_VENDOR_NAME_QUALCOMM = "Qualcomm";
|
||||
const char* FF_GPU_VENDOR_NAME_MTK = "MTK";
|
||||
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
|
||||
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
|
||||
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
|
||||
@@ -33,6 +35,10 @@ const char* ffGetGPUVendorString(unsigned vendorId)
|
||||
return FF_GPU_VENDOR_NAME_INTEL;
|
||||
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
|
||||
return FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
else if(arrayContains((const unsigned[]) {0x5143}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
else if(arrayContains((const unsigned[]) {0x14c3}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_MTK;
|
||||
else if(arrayContains((const unsigned[]) {0x15ad}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_VMWARE;
|
||||
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
|
||||
|
||||
@@ -42,3 +42,7 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
|
||||
|
||||
const char* ffGetGPUVendorString(unsigned vendorId);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
|
||||
#endif
|
||||
|
||||
@@ -63,10 +63,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel
|
||||
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
|
||||
|
||||
int vram; // Supported on Intel
|
||||
if(!ffCfDictGetInt(properties, CFSTR("VRAM,totalMB"), &vram))
|
||||
gpu->dedicated.total = (uint64_t) vram * 1024 * 1024;
|
||||
|
||||
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "3rdparty/nvml/nvml.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
{
|
||||
// https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h
|
||||
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
|
||||
struct pci_conf confs[128];
|
||||
struct pci_match_conf match = {
|
||||
.pc_class = PCIC_DISPLAY,
|
||||
.flags = PCI_GETCONF_MATCH_CLASS,
|
||||
};
|
||||
struct pci_conf_io pcio = {
|
||||
.pat_buf_len = sizeof(match),
|
||||
.num_patterns = 1,
|
||||
.patterns = &match,
|
||||
.match_buf_len = sizeof(confs),
|
||||
.matches = confs,
|
||||
};
|
||||
|
||||
if (ioctl(fd, PCIOCGETCONF, &pcio) < 0)
|
||||
return "ioctl(fd, PCIOCGETCONF, &pc) failed";
|
||||
|
||||
if (pcio.status == PCI_GETCONF_ERROR)
|
||||
return "ioctl(fd, PCIOCGETCONF, &pc) returned error";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
||||
|
||||
for (uint32_t i = 0; i < pcio.num_matches; ++i)
|
||||
{
|
||||
struct pci_conf* pc = &confs[i];
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(pc->pc_vendor));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInitS(&gpu->driver, pc->pd_name);
|
||||
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) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
if (pciids.length == 0)
|
||||
loadPciIds(&pciids);
|
||||
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
|
||||
}
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = (uint32_t) pc->pc_sel.pc_domain,
|
||||
.bus = pc->pc_sel.pc_bus,
|
||||
.device = pc->pc_sel.pc_dev,
|
||||
.func = pc->pc_sel.pc_func,
|
||||
},
|
||||
}, (FFGpuDriverResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.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
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+145
-305
@@ -1,154 +1,28 @@
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
#include <setjmp.h>
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
// Fix building on Ubuntu 20.04
|
||||
#ifndef PCI_IORESOURCE_MEM
|
||||
#define PCI_IORESOURCE_MEM 0x00000200
|
||||
#endif
|
||||
#ifndef PCI_IORESOURCE_PREFETCH
|
||||
#define PCI_IORESOURCE_PREFETCH 0x00002000
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct PCIData
|
||||
{
|
||||
struct pci_access* access;
|
||||
FF_LIBRARY_SYMBOL(pci_fill_info)
|
||||
FF_LIBRARY_SYMBOL(pci_read_byte)
|
||||
FF_LIBRARY_SYMBOL(pci_lookup_name)
|
||||
FF_LIBRARY_SYMBOL(pci_get_param)
|
||||
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
FF_LIBRARY_SYMBOL(pci_get_string_property)
|
||||
#endif
|
||||
} PCIData;
|
||||
|
||||
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(&gpu->vendor, 255);
|
||||
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id);
|
||||
ffStrbufRecalculateLength(&gpu->vendor);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "NVIDIA"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Apple"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
}
|
||||
|
||||
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
u8 revId = 0;
|
||||
bool revIdSet = false;
|
||||
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
revIdSet = pci->ffpci_fill_info(device, PCI_FILL_CLASS_EXT) & PCI_FILL_CLASS_EXT;
|
||||
if(revIdSet)
|
||||
revId = device->rev_id;
|
||||
#endif
|
||||
|
||||
if(!revIdSet)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
return;
|
||||
#else
|
||||
revId = pci->ffpci_read_byte(device, PCI_REVISION_ID);
|
||||
#endif
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY query = ffStrbufCreateF("%X, %X,", device->device_id, revId);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query.chars, &gpu->name);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"AMD ", "ATI ",
|
||||
" (TM)", "(TM)",
|
||||
" Graphics Adapter", " Graphics", " Series", " Edition"
|
||||
};
|
||||
ffStrbufRemoveStrings(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||
}
|
||||
|
||||
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
if(ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD))
|
||||
{
|
||||
drmDetectDeviceName(gpu, pci, device);
|
||||
if(gpu->name.length > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFree(&gpu->name, 255);
|
||||
pci->ffpci_lookup_name(pci->access, gpu->name.chars, (int) gpu->name.allocated, PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
|
||||
ffStrbufRecalculateLength(&gpu->name);
|
||||
|
||||
uint32_t openingBracket = ffStrbufFirstIndexC(&gpu->name, '[');
|
||||
uint32_t closingBracket = ffStrbufNextIndexC(&gpu->name, openingBracket, ']');
|
||||
if(closingBracket < gpu->name.length)
|
||||
{
|
||||
ffStrbufSubstrBefore(&gpu->name, closingBracket);
|
||||
ffStrbufSubstrAfter(&gpu->name, openingBracket);
|
||||
}
|
||||
}
|
||||
|
||||
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
pci->ffpci_fill_info(device, PCI_FILL_DRIVER);
|
||||
ffStrbufAppendS(&gpu->driver, pci->ffpci_get_string_property(device, PCI_FILL_DRIVER));
|
||||
#endif
|
||||
|
||||
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
|
||||
if (gpu->driver.length == 0)
|
||||
{
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppendS(&path, "/module/version");
|
||||
ffAppendFileBuffer(path.chars, &gpu->driver);
|
||||
ffStrbufTrimRightSpace(&gpu->driver);
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device)
|
||||
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 == device->device_class * 256)
|
||||
if(tempValue->deviceClass == deviceClass * 256)
|
||||
{
|
||||
gpu->temperature = tempValue->value;
|
||||
return;
|
||||
@@ -156,195 +30,166 @@ FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* devi
|
||||
}
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool pciDetectMemory(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* device)
|
||||
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
gpu->dedicated.used = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
|
||||
uint32_t flags = (uint32_t) pci->ffpci_fill_info(device, PCI_FILL_IO_FLAGS | PCI_FILL_SIZES);
|
||||
if (!(flags & PCI_FILL_IO_FLAGS) || !(flags & PCI_FILL_SIZES))
|
||||
ffStrbufAppendS(pciDir, "/driver");
|
||||
char pathBuf[PATH_MAX];
|
||||
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
return false;
|
||||
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
|
||||
if (slash)
|
||||
{
|
||||
slash++;
|
||||
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(pciDir, "/module/version");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppend(&gpu->driver, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
gpu->dedicated.total = gpu->shared.total = 0;
|
||||
for (uint32_t i = 0; i < sizeof(device->size) / sizeof(device->size[0]); i++)
|
||||
{
|
||||
if (!(device->flags[i] & PCI_IORESOURCE_MEM)) continue;
|
||||
|
||||
// Assume dedicated memories are prefetchable
|
||||
// At least it's true for my laptop
|
||||
if (device->flags[i] & PCI_IORESOURCE_PREFETCH)
|
||||
gpu->dedicated.total += device->size[i];
|
||||
else
|
||||
gpu->shared.total += device->size[i];
|
||||
}
|
||||
|
||||
if (gpu->dedicated.total == 0 && gpu->shared.total == 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void pciDetectType(FFGPUResult* gpu)
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
{
|
||||
//There is no straightforward way to detect the type of a GPU.
|
||||
//The approach taken here is to look at the memory sizes of the device.
|
||||
//Since integrated GPUs usually use the system ram, they don't have expansive ROMs
|
||||
//and their memory sizes are usually smaller than 1GB.
|
||||
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 // 1GB
|
||||
? FF_GPU_TYPE_DISCRETE
|
||||
: FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
else
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* results, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
pci->ffpci_fill_info(device, PCI_FILL_CLASS);
|
||||
|
||||
char class[1024];
|
||||
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
|
||||
|
||||
if(
|
||||
//https://pci-ids.ucw.cz/read/PD/03
|
||||
strcasecmp("VGA compatible controller", class) != 0 &&
|
||||
strcasecmp("XGA compatible controller", class) != 0 &&
|
||||
strcasecmp("3D controller", class) != 0 &&
|
||||
strcasecmp("Display controller", class) != 0
|
||||
) return;
|
||||
|
||||
pci->ffpci_fill_info(device, PCI_FILL_IDENT);
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
pciDetectVendorName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
pciDetectDeviceName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
pciDetectDriverName(gpu, pci, device);
|
||||
|
||||
#if FF_USE_PCI_MEMORY
|
||||
// Libpci reports at least 2 false results (#495, #497)
|
||||
pciDetectMemory(gpu, pci, device);
|
||||
pciDetectType(gpu);
|
||||
#else
|
||||
gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
#ifdef FF_CUSTOM_PCI_IDS_PATH
|
||||
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
#endif
|
||||
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = (uint32_t) device->domain,
|
||||
.bus = device->bus,
|
||||
.device = device->dev,
|
||||
.func = device->func,
|
||||
},
|
||||
}, (FFGpuDriverResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.type = &gpu->type,
|
||||
.frequency = &gpu->frequency,
|
||||
}, "libnvidia-ml.so");
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian?
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
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
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
#ifdef __linux__
|
||||
if(options->temp && gpu->temperature != gpu->temperature)
|
||||
pciDetectTemp(gpu, device);
|
||||
#endif
|
||||
}
|
||||
|
||||
jmp_buf pciInitJmpBuf;
|
||||
static void __attribute__((__noreturn__))
|
||||
handlePciInitError(FF_MAYBE_UNUSED char *msg, ...)
|
||||
{
|
||||
longjmp(pciInitJmpBuf, 1);
|
||||
}
|
||||
// https://github.com/pciutils/pciutils/blob/bca0412843fa650c749128ade03f35ab3e8fe2b9/lib/init.c#L186
|
||||
static void __attribute__((__noreturn__))
|
||||
handlePciGenericError(char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
fputs("pcilib: ", stderr);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
static void handlePciWarning(FF_MAYBE_UNUSED char *msg, ...)
|
||||
{
|
||||
// noop
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
PCIData pci;
|
||||
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
|
||||
const char* pciDirPath = "/sys/bus/pci/devices/";
|
||||
|
||||
FF_LIBRARY_LOAD(libpci, &instance.config.library.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_alloc);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_init);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_scan_bus);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_cleanup);
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDirPath);
|
||||
if(dirp == NULL)
|
||||
return "Failed to open `/sys/bus/pci/devices/`";
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_fill_info);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_lookup_name);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_read_byte);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_param);
|
||||
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&pciDir, pciDirPath);
|
||||
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_string_property);
|
||||
#endif
|
||||
const uint32_t pciBaseDirLength = pciDir.length;
|
||||
|
||||
pci.access = ffpci_alloc();
|
||||
pci.access->warning = handlePciWarning;
|
||||
pci.access->error = handlePciInitError;
|
||||
if(setjmp(pciInitJmpBuf) == 0) // https://github.com/pciutils/pciutils/issues/136
|
||||
ffpci_init(pci.access);
|
||||
else
|
||||
return "pcilib: Cannot find any working access method.";
|
||||
pci.access->error = handlePciGenericError; // set back to generic error so we don't mess up error handling in other places
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
||||
|
||||
ffpci_scan_bus(pci.access);
|
||||
|
||||
struct pci_dev* device = pci.access->devices;
|
||||
while(device != NULL)
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
pciHandleDevice(options, gpus, &pci, device);
|
||||
device = device->next;
|
||||
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(&pciDir, "/revision");
|
||||
if (ffReadFileBuffer(pciDir.chars, &buffer))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
if (!pciids.length)
|
||||
loadPciIds(&pciids);
|
||||
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
}
|
||||
|
||||
pciDetectDriver(gpu, &pciDir, &buffer);
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = pciDomain,
|
||||
.bus = pciBus,
|
||||
.device = pciDevice,
|
||||
.func = pciFunc,
|
||||
},
|
||||
}, (FFGpuDriverResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.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);
|
||||
#endif
|
||||
}
|
||||
|
||||
ffpci_cleanup(pci.access);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
@@ -353,10 +198,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
return pciDetectGPUs(options, gpus);
|
||||
#else
|
||||
FF_UNUSED(options, gpus);
|
||||
return "fastfetch is built without libpci support";
|
||||
#endif
|
||||
return pciDetectGPUs(options, gpus);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "gpu.h"
|
||||
|
||||
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
|
||||
{
|
||||
if (content->length)
|
||||
{
|
||||
char buffer[32];
|
||||
|
||||
// Search for vendor
|
||||
uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor);
|
||||
char* start = (char*) memmem(content->chars, content->length, buffer, len);
|
||||
char* end = content->chars + content->length;
|
||||
if (start)
|
||||
{
|
||||
start += len;
|
||||
end = memchr(start, '\n', (uint32_t) (end - start));
|
||||
if (!end)
|
||||
end = content->chars + content->length;
|
||||
if (!gpu->vendor.length)
|
||||
ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start);
|
||||
|
||||
start = end; // point to '\n' of vendor
|
||||
end = start + 1; // point to start of devices
|
||||
// find the start of next vendor
|
||||
while (end[0] == '\t' || end[0] == '#')
|
||||
{
|
||||
end = strchr(end, '\n');
|
||||
if (!end)
|
||||
{
|
||||
end = content->chars + content->length;
|
||||
break;
|
||||
}
|
||||
else
|
||||
end++;
|
||||
}
|
||||
|
||||
// Search for device
|
||||
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device);
|
||||
start = memmem(start, (size_t) (end - start), buffer, len);
|
||||
if (start)
|
||||
{
|
||||
start += len;
|
||||
end = memchr(start, '\n', (uint32_t) (end - start));
|
||||
if (!end)
|
||||
end = content->chars + content->length;
|
||||
|
||||
char* openingBracket = memchr(start, '[', (uint32_t) (end - start));
|
||||
if (openingBracket)
|
||||
{
|
||||
openingBracket++;
|
||||
char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket));
|
||||
if (closingBracket)
|
||||
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
|
||||
}
|
||||
if (!gpu->name.length)
|
||||
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpu->name.length)
|
||||
{
|
||||
const char* subclassStr;
|
||||
switch (subclass)
|
||||
{
|
||||
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
|
||||
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
|
||||
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
|
||||
default: subclassStr = ""; break;
|
||||
}
|
||||
|
||||
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
uint64_t value = 0;
|
||||
|
||||
@@ -151,9 +151,9 @@ const FFQtResult* ffDetectQt(void)
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
|
||||
if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA))
|
||||
detectPlasma(&result);
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT) == 0)
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
|
||||
detectLXQt(&result);
|
||||
|
||||
return &result;
|
||||
|
||||
@@ -111,6 +111,8 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Mac");
|
||||
if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,4")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,5")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
|
||||
@@ -63,7 +63,7 @@ static const char* getSddmVersion(FFstrbuf* version)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose)
|
||||
|
||||
gzFile file = ffgzopen("/usr/share/man/man1/sddm.1.gz", "rb");
|
||||
gzFile file = ffgzopen(FASTFETCH_TARGET_DIR_USR "/share/man/man1/sddm.1.gz", "rb");
|
||||
if (file == Z_NULL)
|
||||
return "ffgzopen(\"/usr/share/man/man1/sddm.1.gz\", \"rb\") failed";
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
|
||||
void ffDetectLocale(FFstrbuf* result)
|
||||
{
|
||||
ffStrbufAppendS(result, getenv("LC_MESSAGES"));
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(result, getenv("LANG"));
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
#ifdef LC_MESSAGES
|
||||
ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL));
|
||||
|
||||
|
||||
@@ -40,10 +40,12 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type,
|
||||
switch (type)
|
||||
{
|
||||
case AF_INET:
|
||||
ffStrbufSetS(&ip->ipv4, addr);
|
||||
if (ip->ipv4.length) ffStrbufAppendC(&ip->ipv4, ',');
|
||||
ffStrbufAppendS(&ip->ipv4, addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ffStrbufSetS(&ip->ipv6, addr);
|
||||
if (ip->ipv6.length) ffStrbufAppendC(&ip->ipv6, ',');
|
||||
ffStrbufAppendS(&ip->ipv6, addr);
|
||||
break;
|
||||
case -1:
|
||||
ffStrbufSetS(&ip->mac, addr);
|
||||
@@ -83,12 +85,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
char addressBuffer[INET_ADDRSTRLEN + 4];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
|
||||
struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;
|
||||
int cidr = __builtin_popcount(inet_netof(netmask->sin_addr));
|
||||
if (cidr != 0)
|
||||
if (options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%d", cidr);
|
||||
struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;
|
||||
int cidr = __builtin_popcount(netmask->sin_addr.s_addr);
|
||||
if (cidr != 0)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%d", cidr);
|
||||
}
|
||||
}
|
||||
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute);
|
||||
@@ -99,8 +104,23 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
continue;
|
||||
|
||||
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
char addressBuffer[INET6_ADDRSTRLEN + 4];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
|
||||
if (options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT)
|
||||
{
|
||||
struct sockaddr_in6* netmask = (struct sockaddr_in6*) ifa->ifa_netmask;
|
||||
int cidr = 0;
|
||||
static_assert(sizeof(netmask->sin6_addr) % sizeof(uint64_t) == 0, "");
|
||||
for (uint32_t i = 0; i < sizeof(netmask->sin6_addr) / sizeof(uint64_t); ++i)
|
||||
cidr += __builtin_popcountll(((uint64_t*) &netmask->sin6_addr)[i]);
|
||||
if (cidr != 0)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%d", cidr);
|
||||
}
|
||||
}
|
||||
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute);
|
||||
}
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "util/windows/unicode.h"
|
||||
#include "localip.h"
|
||||
|
||||
static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, bool defaultRoute)
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool newIp, bool defaultRoute)
|
||||
{
|
||||
FFLocalIpResult* ip = NULL;
|
||||
|
||||
@@ -27,13 +27,15 @@ static void addNewIp(FFlist* list, const char* name, const char* value, int type
|
||||
switch (type)
|
||||
{
|
||||
case AF_INET:
|
||||
ffStrbufSetS(&ip->ipv4, value);
|
||||
if (ip->ipv4.length) ffStrbufAppendC(&ip->ipv4, ',');
|
||||
ffStrbufAppendS(&ip->ipv4, addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ffStrbufSetS(&ip->ipv6, value);
|
||||
if (ip->ipv6.length) ffStrbufAppendC(&ip->ipv6, ',');
|
||||
ffStrbufAppendS(&ip->ipv6, addr);
|
||||
break;
|
||||
case -1:
|
||||
ffStrbufSetS(&ip->mac, value);
|
||||
ffStrbufSetS(&ip->mac, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +110,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
char addressBuffer[INET_ADDRSTRLEN + 4];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
|
||||
if (ifa->OnLinkPrefixLength)
|
||||
if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength);
|
||||
@@ -120,8 +122,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
|
||||
{
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
char addressBuffer[INET6_ADDRSTRLEN + 4];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
|
||||
if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength)
|
||||
{
|
||||
size_t len = strlen(addressBuffer);
|
||||
snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength);
|
||||
}
|
||||
|
||||
addNewIp(results, name, addressBuffer, AF_INET6, newIp, isDefaultRoute);
|
||||
newIp = false;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ static uint64_t time1;
|
||||
|
||||
void ffPrepareNetIO(FFNetIOOptions* options)
|
||||
{
|
||||
if (options->detectTotal) return;
|
||||
|
||||
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
|
||||
ffNetIOGetIoCounters(&ioCounters1, options);
|
||||
time1 = ffTimeGetNow();
|
||||
@@ -17,6 +19,15 @@ void ffPrepareNetIO(FFNetIOOptions* options)
|
||||
const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
if (options->detectTotal)
|
||||
{
|
||||
error = ffNetIOGetIoCounters(result, options);
|
||||
if (error)
|
||||
return error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (time1 == 0)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
|
||||
|
||||
@@ -23,15 +23,15 @@ typedef struct OpenCLData
|
||||
|
||||
static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
{
|
||||
cl_platform_id platformID;
|
||||
cl_uint numPlatforms;
|
||||
cl_platform_id platformID = NULL;
|
||||
cl_uint numPlatforms = 0;
|
||||
data->ffclGetPlatformIDs(1, &platformID, &numPlatforms);
|
||||
|
||||
if(numPlatforms == 0)
|
||||
return "clGetPlatformIDs returned 0 platforms";
|
||||
|
||||
cl_device_id deviceID;
|
||||
cl_uint numDevices;
|
||||
cl_device_id deviceID = NULL;
|
||||
cl_uint numDevices = 0;
|
||||
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices);
|
||||
|
||||
if(numDevices == 0)
|
||||
@@ -40,7 +40,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
if(numDevices == 0)
|
||||
return "clGetDeviceIDs returned 0 devices";
|
||||
|
||||
char version[64];
|
||||
char version[64] = "";
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL);
|
||||
if(!ffStrSet(version))
|
||||
return "clGetDeviceInfo returned NULL or empty string";
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
typedef struct FFPackagesResult
|
||||
{
|
||||
uint32_t am;
|
||||
uint32_t apk;
|
||||
uint32_t brew;
|
||||
uint32_t brewCask;
|
||||
|
||||
@@ -45,14 +45,14 @@ static void getBrewPackages(FFPackagesResult* result)
|
||||
if(ffStrSet(prefix))
|
||||
return countBrewPackages(prefix, result);
|
||||
|
||||
countBrewPackages(FASTFETCH_TARGET_DIR_ROOT"/opt/homebrew", result);
|
||||
countBrewPackages(FASTFETCH_TARGET_DIR_ROOT"/usr/local", result);
|
||||
countBrewPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/homebrew", result);
|
||||
countBrewPackages(FASTFETCH_TARGET_DIR_USR "/local", result);
|
||||
}
|
||||
|
||||
static uint32_t countMacPortsPackages(const char* dirname)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname);
|
||||
ffStrbufAppendS(&baseDir, "/var/macports/software");
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/var/macports/software");
|
||||
|
||||
return getNumElements(baseDir.chars, DT_DIR);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ static uint32_t getMacPortsPackages()
|
||||
if(ffStrSet(prefix))
|
||||
return countMacPortsPackages(prefix);
|
||||
|
||||
return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT"/opt/local");
|
||||
return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/local");
|
||||
}
|
||||
|
||||
static uint32_t getNixPackagesImpl(char* path)
|
||||
@@ -81,7 +81,7 @@ static uint32_t getNixPackagesImpl(char* 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");
|
||||
|
||||
ffProcessAppendStdOut(&output, (char* const[]) {
|
||||
"/bin/sh",
|
||||
FASTFETCH_TARGET_DIR_ROOT "/bin/sh",
|
||||
"-c",
|
||||
command.chars,
|
||||
NULL
|
||||
@@ -99,14 +99,16 @@ static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
|
||||
return num_elements;
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
getBrewPackages(result);
|
||||
result->macports = getMacPortsPackages();
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
|
||||
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
|
||||
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT)) getBrewPackages(result);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT)) result->macports = getMacPortsPackages();
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
|
||||
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
|
||||
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
{
|
||||
result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
|
||||
result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages");
|
||||
}
|
||||
|
||||
@@ -253,44 +253,91 @@ static uint32_t getRpmFromLibrpm(void)
|
||||
|
||||
#endif //FF_HAVE_RPM
|
||||
|
||||
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
|
||||
static uint32_t getAM(FFstrbuf* baseDir)
|
||||
{
|
||||
packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q");
|
||||
packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: install ok installed");
|
||||
packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE");
|
||||
packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR);
|
||||
packageCounts->flatpakSystem += getFlatpak(baseDir, "/var/lib/flatpak");
|
||||
packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default");
|
||||
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
|
||||
packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR);
|
||||
packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", DT_REG);
|
||||
packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages");
|
||||
packageCounts->snap += getSnap(baseDir);
|
||||
packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps");
|
||||
packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR);
|
||||
packageCounts->brew += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Cellar", DT_DIR);
|
||||
packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
|
||||
packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt
|
||||
}
|
||||
|
||||
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
|
||||
{
|
||||
getPackageCounts(baseDir, packageCounts);
|
||||
|
||||
// #771
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC "/pacman-mirrors.conf");
|
||||
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
|
||||
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
|
||||
|
||||
ffStrbufAppendS(baseDir, "/opt");
|
||||
uint32_t optDirLength = baseDir->length;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
ffStrbufAppendS(baseDir, "/am/APP-MANAGER");
|
||||
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
++result; // `am` itself is counted as a package too
|
||||
ffStrbufSubstrBefore(baseDir, optDirLength);
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
|
||||
if(dirp)
|
||||
{
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
if (entry->d_type == DT_DIR)
|
||||
{
|
||||
ffStrbufAppendF(baseDir, "/%s/AM-updater", entry->d_name);
|
||||
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
|
||||
++result;
|
||||
ffStrbufSubstrBefore(baseDir, optDirLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
|
||||
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
|
||||
{
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_DPKG_BIT)) packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: install ok installed");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_EMERGE_BIT)) packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_EOPKG_BIT)) packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpak(baseDir, "/var/lib/flatpak");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
{
|
||||
packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default");
|
||||
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
|
||||
}
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKGTOOL_BIT)) packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", DT_REG);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT)) packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_SNAP_BIT)) packageCounts->snap += getSnap(baseDir);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_XBPS_BIT)) packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT))
|
||||
{
|
||||
packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR);
|
||||
packageCounts->brew += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Cellar", DT_DIR);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
|
||||
{
|
||||
getPackageCounts(baseDir, packageCounts, options);
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT))
|
||||
{
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC "/pacman-mirrors.conf");
|
||||
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
|
||||
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
}
|
||||
|
||||
static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
|
||||
{
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
ffStrbufAppendS(baseDir, "/bedrock/strata");
|
||||
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
{
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
@@ -309,33 +356,34 @@ static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* package
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
getPackageCounts(baseDir, packageCounts);
|
||||
getPackageCounts(baseDir, packageCounts, options);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength2);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(512);
|
||||
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(&ffDetectOS()->id, "bedrock"))
|
||||
getPackageCountsBedrock(&baseDir, result);
|
||||
getPackageCountsBedrock(&baseDir, result, options);
|
||||
else
|
||||
getPackageCountsRegular(&baseDir, result);
|
||||
getPackageCountsRegular(&baseDir, result, options);
|
||||
|
||||
// If SQL failed, we can still try with librpm.
|
||||
// This is needed on openSUSE, which seems to use a proprietary database file
|
||||
// This method doesn't work on bedrock, so we do it here.
|
||||
#ifdef FF_HAVE_RPM
|
||||
if(result->rpm == 0)
|
||||
if(!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT) && result->rpm == 0)
|
||||
result->rpm = getRpmFromLibrpm();
|
||||
#endif
|
||||
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
|
||||
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user