Compare commits

..

92 Commits

Author SHA1 Message Date
Carter Li ea162fd452 Merge pull request #734 from fastfetch-cli/dev
Release: v2.8.4
2024-02-23 16:09:51 +08:00
李通洲 b80391b183 Release: v2.8.4 2024-02-23 15:56:12 +08:00
李通洲 4c7a9e4394 Doc: update changelog 2024-02-23 10:01:05 +08:00
李通洲 4b747f70a4 Disk (Linux): ensure only physical devices are detected
Ref: https://github.com/fastfetch-cli/fastfetch/issues/731#issuecomment-1955814211
2024-02-23 09:29:39 +08:00
李通洲 5fb4b6dc04 Display: --display-compact-type support *-with-refresh-rate
Ref: https://github.com/fastfetch-cli/fastfetch/discussions/732
2024-02-22 18:45:57 +08:00
李通洲 5e7cfe2976 Display: add option --display-order 2024-02-22 10:47:13 +08:00
李通洲 77db2d84a3 FFstrbuf: remove ffStrbufCompAlphabetically 2024-02-22 10:38:33 +08:00
李通洲 15bb5bfb24 Packages: add ability to disable specified package manager
Fix #729
2024-02-22 10:03:38 +08:00
李通洲 4e9ee9aa03 Package: code cleanup 2024-02-21 15:40:04 +08:00
李通洲 6a0c7ca788 Disk (Linux): try fixing multidevice bcachefs filesystem compatibility
Ref: #731
2024-02-21 09:05:26 +08:00
李通洲 90e99bcf69 Doc: fix invalid commands 2024-02-21 09:05:26 +08:00
Lenny0939 5b20a86d53 Fix mistake in README.md (#730)
Sudo is not necessary to use nix-shell, and puts you in a shell as root which is not ideal
2024-02-20 18:42:59 -06:00
李通洲 6ad1262f4a NetIO: add option --netio-detect-total 2024-02-20 14:44:55 +08:00
李通洲 e0297e1dd1 DiskIO: add option --diskio-detect-total 2024-02-20 14:43:50 +08:00
李通洲 937611aa29 Colors: support JSON config generation 2024-02-15 22:05:34 +08:00
李通洲 eda38e16db Colors: don't print extra empty lines 2024-02-15 21:55:33 +08:00
李通洲 2731756c39 Platform (Windows): small optimization 2024-02-15 20:29:57 +08:00
李通洲 853ca0f608 Platform (Windows): don't assume x86 as i686 2024-02-15 20:29:34 +08:00
李通洲 17f4a6e055 Colors: support block related settings
Fix #721
2024-02-14 22:09:12 +08:00
李通洲 925dc6f681 TerminalFont (Windows): support portable Windows Terminal settings
Fix #720
2024-02-13 19:49:49 +08:00
李通洲 706527eab4 Github: update ISSUE_TEMPLATE 2024-02-13 19:19:29 +08:00
李通洲 3a96ade423 CPU (Linux): don't segfault if we fail to find Vendor ID in lscpu
Fix #718
2024-02-13 19:08:44 +08:00
李通洲 da9c928286 CMake: make artifact file names consistant
Fix #719
2024-02-13 19:02:03 +08:00
Carter Li 30d3d00900 Merge pull request #717 from fastfetch-cli/dev
Release v2.8.3
2024-02-12 10:59:30 +08:00
李通洲 99fce80d0d CI: fix windows artifacts generation 2024-02-12 10:46:57 +08:00
Herby Gillot a5a28e30a0 README: add MacPorts install info (#716)
Add info on installing `fastfetch` on macOS via MacPorts: https://ports.macports.org/port/fastfetch/
2024-02-12 10:43:23 +08:00
李通洲 7fe39353df Release: v2.8.3 2024-02-12 10:28:29 +08:00
李通洲 a3576b3154 CI: release file name without version
Fix #714
2024-02-12 10:28:29 +08:00
AlbydS c5d0d84001 Add installation instructions for even more Linux distributions (#715)
Added Alpine (now with the right command), ALT Linux and Arch AUR to the installation instructions.
2024-02-12 10:20:10 +08:00
李通洲 467ed54a3b GPU (Linux): lazy load pci.ids 2024-02-12 10:12:34 +08:00
Carter 7ea8882843 GPU (FreeBSD): detect correct AMD card names 2024-02-12 18:09:11 +08:00
李通洲 f4cb3bb33f GPU (Linux): use amdgpu.ids 2024-02-12 00:43:06 +08:00
李通洲 330eb9fa21 GPU: show sub-device if available
Try fixing #713
2024-02-11 23:01:14 +08:00
李通洲 1006f513f5 Release: v2.8.2 2024-02-10 14:38:47 +08:00
李通洲 652c4b2e82 CI: don't upload old artifacts 2024-02-10 14:37:27 +08:00
李通洲 3c618a8cd0 Merge remote-tracking branch 'upstream/master' into dev 2024-02-10 14:14:09 +08:00
李通洲 b5821de793 Release: v2.8.1 2024-02-10 14:02:22 +08:00
李通洲 dec604691c CMake: try fixing packaging name conflicting 2024-02-10 13:59:34 +08:00
Carter Li 72baa6cca9 Merge pull request #712 from fastfetch-cli/dev
Release v2.8.0
2024-02-10 12:02:58 +08:00
李通洲 34b023a74f Release: 2.8.0 (ci skip)
For Luna New Year!
2024-02-10 10:32:14 +08:00
李通洲 8249a8ed6a Doc: update changelog 2024-02-09 00:10:29 +08:00
李通洲 7e1ac5e24a Terminal (Windows): code cleanup 2024-02-08 23:15:58 +08:00
李通洲 55c72a8bb3 Camera (Windows): fix Windows Server Core compatibility 2024-02-08 19:14:09 +08:00
Carter Li b602bb20c2 Battery (Linux): print the same format of battery status as other platforms 2024-02-08 14:10:51 +08:00
Carter Li 46ed24275f Battery (FreeBSD): fix typos 2024-02-08 13:59:02 +08:00
Carter Li 71db83f806 PowerAdapter (Linux): don't print not connected either
To align result to macOS
2024-02-08 13:51:30 +08:00
李通洲 0746afa0c2 PowerAdapter (macOS): don't show not connected if no power adapter is detected 2024-02-08 10:53:58 +08:00
李通洲 805c384819 Battery (macOS): don't show an empty battery if no battery is detected 2024-02-08 10:37:06 +08:00
Carter Li 9e4c0e318c Chore: add dpkg related stuff 2024-02-07 14:39:19 +08:00
李通洲 51eaac2fd7 Doc: update changelog 2024-02-06 09:54:33 +08:00
李通洲 92c3df82e6 Logo (Builtin): add PikaOS
Ref: https://github.com/hykilpikonna/hyfetch/pull/231
2024-02-06 09:30:24 +08:00
李通洲 7f238a701e Logo (Builtin): add tatra
Ref: https://github.com/dylanaraps/neofetch/pull/2439
2024-02-06 09:25:44 +08:00
李通洲 72236f62ad Logo (Builtin): add z/OS
Ref: https://github.com/dylanaraps/neofetch/pull/2436
2024-02-06 09:03:01 +08:00
李通洲 51b0c43d76 Platform (Windows): use %USERNAME% if available 2024-02-05 20:01:19 +08:00
李通洲 79e2007d30 Revert "Platform (Linux): use $HOSTNAME if available"
$HOSTNAME doesn't seem to be a standard variable

This reverts commit 02eb604ceb.
2024-02-05 20:01:18 +08:00
李通洲 02eb604ceb Platform (Linux): use $HOSTNAME if available
Ref: #710
2024-02-05 18:23:21 +08:00
李通洲 ce6b2b85f7 Locale (Linux): use environment variable if available
In some machine `setlocale(LC_MESSAGES, NULL)` returns `C` for some reason.
2024-02-05 16:25:12 +08:00
李通洲 48d1980061 CI: build linux old 2024-02-05 14:32:17 +08:00
李通洲 40fae5c5f1 Camera (Android): add empty color space result 2024-02-04 19:07:47 +08:00
李通洲 e296ee1040 CI (Linux): bump version of linux runners
Drop support of Debian 11
2024-02-04 15:48:58 +08:00
李通洲 199e71553d CI: run camera module 2024-02-04 15:14:18 +08:00
李通洲 13fa218e5a Camera: adjust output format 2024-02-04 14:17:18 +08:00
李通洲 eed5efabea Camera (Windows): detect color space 2024-02-04 14:17:18 +08:00
李通洲 d2315e967e Camera (macOS): detect color space 2024-02-04 14:17:18 +08:00
Carter Li cbe3c70480 Camera (Linux): add property colorspace 2024-02-04 14:17:18 +08:00
李通洲 c918226909 Fastfetch: print videodev2 in --list-features 2024-02-04 09:56:22 +08:00
李通洲 18472660ae CI (FreeBSD): remove unused depenencies 2024-02-04 09:27:04 +08:00
李通洲 458c2ccd01 Camera (FreeBSD): enable support
Requires build dependency `v4l_compat`
2024-02-04 09:26:19 +08:00
李通洲 7bb9efcebb Camera (Android): init support 2024-02-02 23:22:40 +08:00
李通洲 8a42dfd68d Camera: tidy; add module to all.jsonc 2024-02-02 22:43:01 +08:00
李通洲 3edd8a6740 Camera (Linux): init support 2024-02-02 22:14:25 +08:00
李通洲 cba22b7155 Camera (Windows): init support 2024-02-02 20:36:22 +08:00
李通洲 246ad6d288 Sound (Windows): tidy 2024-02-02 20:36:22 +08:00
李通洲 295e119810 Camera (macOS): new module 2024-02-02 20:36:22 +08:00
李通洲 cfe22f9524 Terminal (Linux): try fixing #707 (v2) 2024-02-01 17:56:40 +08:00
李通洲 de2c1d7786 CI: unify artifacts name (v2) 2024-02-01 16:00:33 +08:00
李通洲 7d74339aa0 CI: build in parallel 2024-02-01 15:43:56 +08:00
李通洲 7589e962c2 CI: unify artifact names 2024-02-01 15:25:05 +08:00
李通洲 9a189694f9 CI: silence more warnings 2024-02-01 15:24:07 +08:00
李通洲 4069fbfe7b CI: upgrade codeql-action 2024-02-01 15:02:37 +08:00
李通洲 7ccd886909 CI: build aarch64 binaries 2024-02-01 14:29:28 +08:00
李通洲 42957356b2 GPU: remove libpci related stuff 2024-02-01 13:38:15 +08:00
李通洲 9038cd32b2 Terminal (Linux): don't assume blackbox is build for flatpak 2024-02-01 09:14:06 +08:00
李通洲 128c3bfea6 TerminalShell (Linux): try supporting blackbox
Fix #707
2024-02-01 09:02:49 +08:00
李通洲 60ed822f6a GPU (Linux): fix detection in some cases 2024-01-31 18:58:48 +08:00
Carter Li 527ec1bc61 Logo (Builtin): add asahi2; make asahi logo actually work 2024-01-31 16:47:22 +08:00
Carter Li cbf203901b CPU (Linux): code refactor 2024-01-31 14:36:00 +08:00
Carter Li cf6f3dbe0c CI (Windows): fix build 2024-01-31 13:35:57 +08:00
Carter Li ab625497ce CPU (Linux): code refactor 2024-01-31 13:28:18 +08:00
Yussef Dalton 83532b68dd CPU (Linux): use marketing name on Asahi Linux 2024-01-31 11:02:41 +08:00
Carter Li cd2a1495b8 GPU (FreeBSD): use ffGPUParsePciIds 2024-01-31 10:39:09 +08:00
Carter Li b01d2bdd8c GPU (Linux): rewrite; drop libpci dependency 2024-01-31 10:20:49 +08:00
79 changed files with 2072 additions and 667 deletions
+1 -3
View File
@@ -46,9 +46,7 @@ Output of `fastfetch --list-features`:
Paste the stacktrace here. You may get it with:
```
$ gdb /path/to/fastfetch
$ run
$ bt
$ 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
+156 -57
View File
@@ -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
@@ -156,7 +249,7 @@ jobs:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install 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 +257,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,11 +283,11 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-macos
name: fastfetch-macos-universal
path: ./fastfetch-*.*
freebsd:
name: FreeBSD
freebsd-amd64:
name: FreeBSD-amd64
runs-on: macos-12
permissions:
security-events: write
@@ -211,9 +304,9 @@ jobs:
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 +317,11 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-freebsd
name: fastfetch-freebsd-amd64
path: ./fastfetch-*.*
win64:
name: Win64
windows-amd64:
name: Windows-amd64
runs-on: windows-latest
permissions:
security-events: write
@@ -254,7 +347,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 +371,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
@@ -313,7 +406,7 @@ jobs:
run: uname -a
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: c, cpp
@@ -321,10 +414,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 +438,28 @@ 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
- windows-amd64
- windows-i686
permissions:
contents: write
steps:
@@ -376,29 +470,34 @@ 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
@@ -407,10 +506,10 @@ jobs:
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
+40
View File
@@ -1,3 +1,43 @@
# 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:
+20 -8
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.7.1
VERSION 2.8.4
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)
@@ -310,6 +308,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
@@ -402,6 +401,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
@@ -434,6 +434,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)
@@ -487,6 +488,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)
@@ -517,6 +519,7 @@ elseif(BSD)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_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
@@ -549,6 +552,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)
@@ -604,6 +608,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
@@ -659,6 +664,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
@@ -792,10 +798,6 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
endforeach()
endfunction()
ff_lib_enable(LIBPCI
"libpci"
"Pci"
)
ff_lib_enable(VULKAN
"vulkan"
"Vulkan"
@@ -918,9 +920,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"
@@ -1105,6 +1109,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")
@@ -1121,7 +1133,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)
+10 -2
View File
@@ -28,11 +28,13 @@ 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`
* 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 +42,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`
+18
View File
@@ -0,0 +1,18 @@
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
+1
View File
@@ -0,0 +1 @@
12
+13
View File
@@ -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.
+11
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
fastfetch_2.7.1ubuntu2_source.buildinfo universe/utils optional
Vendored Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
debuild -S -i -I
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
Vendored Executable
+7
View File
@@ -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
+4
View File
@@ -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@
+49 -5
View File
@@ -1007,6 +1007,29 @@
"type": "integer",
"minimum": 0,
"default": 0
},
"block": {
"description": "Set behavior of block printing",
"type": "object",
"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
}
}
}
}
},
@@ -1078,7 +1101,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"
@@ -1088,6 +1113,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"
},
@@ -1173,6 +1207,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"
},
@@ -1382,6 +1421,11 @@
"type": "boolean",
"default": true
},
"detectTotal": {
"description": "Detect total bytes instead of current rate",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
@@ -1436,10 +1480,10 @@
"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": "A colon separated list of package managers to be disabled when detecting",
"type": "string",
"default": "winget"
},
"key": {
"$ref": "#/$defs/key"
+1
View File
@@ -50,6 +50,7 @@
"users",
"bluetooth",
"sound",
"camera",
"gamepad",
"weather",
"netio",
+1
View File
@@ -56,6 +56,7 @@
"users",
"bluetooth",
"sound",
"camera",
"gamepad",
{
"type": "weather",
+3 -3
View File
@@ -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
+1
View File
@@ -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,
+102 -12
View File
@@ -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
@@ -963,6 +972,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 +1013,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 +1033,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 +1049,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 +1087,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 +1126,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 +1148,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,
@@ -1225,6 +1269,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 +1394,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": [
+8 -10
View File
@@ -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), &currentCapacity) != 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), &currentCapacity) != NULL || currentCapacity <= 0)
continue;
battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
+2 -2
View File
@@ -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
{
+22
View File
@@ -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))
+15
View File
@@ -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 */);
+61
View File
@@ -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;
}
+31
View File
@@ -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;
}
+61
View File
@@ -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
}
+129
View File
@@ -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;
}
+75
View File
@@ -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>
@@ -34,6 +35,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,12 +52,36 @@ 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;
}
@@ -121,6 +150,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;
@@ -167,6 +234,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 +266,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
return NULL;
}
}
else
{
pstart = buffer.chars;
}
}
while ((pstart = strstr(pstart, "Model name:")))
+3 -3
View File
@@ -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)
+4
View File
@@ -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
+11
View File
@@ -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));
+4
View File
@@ -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, uint16_t subVendor, uint16_t subDevice, FFGPUResult* gpu);
#endif
+10 -64
View File
@@ -1,9 +1,9 @@
#include "gpu_driver_specific.h"
#include "common/io/io.h"
#include "common/properties.h"
#include "3rdparty/nvml/nvml.h"
#include "util/mallocHelper.h"
#include "common/io/io.h"
#include <dev/pci/pcireg.h>
#include <sys/pciio.h>
@@ -46,7 +46,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
return "ioctl(fd, PCIOCGETCONF, &pc) returned error";
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
loadPciIds(&pciids);
for (uint32_t i = 0; i < pcio.num_matches; ++i)
{
@@ -61,74 +60,21 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
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_vendor << 16) + pc->pc_device;
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 (pciids.length)
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
{
char buffer[32];
uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", pc->pc_vendor);
char* start = (char*) memmem(pciids.chars, pciids.length, buffer, len);
char* end = pciids.chars + pciids.length;
if (start)
{
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
end = pciids.chars + pciids.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 = pciids.chars + pciids.length;
break;
}
else
end++;
}
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", pc->pc_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 = pciids.chars + pciids.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);
}
}
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)
if (gpu->name.length == 0)
{
const char* subclass;
switch (pc->pc_subclass)
{
case PCIS_DISPLAY_VGA: subclass = " (VGA compatible)"; break;
case PCIS_DISPLAY_XGA: subclass = " (XGA compatible)"; break;
case PCIS_DISPLAY_3D: subclass = " (3D)"; break;
default: subclass = ""; break;
}
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", pc->pc_device, subclass);
if (pciids.length == 0)
loadPciIds(&pciids);
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, pc->pc_subvendor, pc->pc_subdevice, gpu);
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
+140 -300
View File
@@ -1,154 +1,25 @@
#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>
#include <inttypes.h>
// 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
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,187 +27,161 @@ 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;
}
ffReadFileBuffer("/usr/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
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);
ffReadFileBuffer("/usr/share/misc/pci.ids", pciids); // debian?
if (pciids->length > 0) return true;
if (device->device_class >> 8 != PCI_BASE_CLASS_DISPLAY)
return;
ffReadFileBuffer("/usr/local/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
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;
#endif
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
#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");
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, 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);
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, (uint16_t) subVendorId, (uint16_t) subDeviceId, 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
@@ -345,10 +190,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);
}
+81
View File
@@ -0,0 +1,81 @@
#include "gpu.h"
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, uint16_t subVendor, uint16_t subDevice, 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;
// Search for subvendor and subdevice
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t\t%04x %04x ", subVendor, subDevice);
char* subStart = memmem(start, (size_t) (end - start), buffer, len);
if (subStart)
start = subStart + 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);
}
}
+8
View File
@@ -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));
+11
View File
@@ -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));
+11 -9
View File
@@ -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");
}
}
+2 -1
View File
@@ -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");
}
+44 -34
View File
@@ -253,44 +253,53 @@ static uint32_t getRpmFromLibrpm(void)
#endif //FF_HAVE_RPM
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
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
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
}
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts)
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
getPackageCounts(baseDir, packageCounts);
getPackageCounts(baseDir, packageCounts, options);
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);
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)
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 +318,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");
}
+4 -5
View File
@@ -107,9 +107,8 @@ static void detectWinget(FFPackagesResult* result)
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
{
detectScoop(result);
detectChoco(result);
detectPacman(result);
if (options->winget)
detectWinget(result);
if (!(options->disabled & FF_PACKAGES_FLAG_SCOOP_BIT)) detectScoop(result);
if (!(options->disabled & FF_PACKAGES_FLAG_CHOCO_BIT)) detectChoco(result);
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) detectPacman(result);
if (!(options->disabled & FF_PACKAGES_FLAG_WINGET_BIT)) detectWinget(result);
}
@@ -13,5 +13,3 @@ typedef struct FFPowerAdapterResult
} FFPowerAdapterResult;
const char* ffDetectPowerAdapter(FFlist* results);
#define FF_POWERADAPTER_NOT_CONNECTED -1
+10 -10
View File
@@ -7,18 +7,18 @@
const char* ffDetectPowerAdapter(FFlist* results)
{
FFPowerAdapterResult* adapter = ffListAdd(results);
ffStrbufInit(&adapter->name);
ffStrbufInit(&adapter->description);
ffStrbufInit(&adapter->manufacturer);
ffStrbufInit(&adapter->modelName);
ffStrbufInit(&adapter->serial);
adapter->watts = FF_POWERADAPTER_NOT_CONNECTED;
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
if (details)
if (details && CFDictionaryContainsKey(details, CFSTR(kIOPSPowerAdapterWattsKey)))
{
FFPowerAdapterResult* adapter = ffListAdd(results);
ffStrbufInit(&adapter->name);
ffStrbufInit(&adapter->description);
ffStrbufInit(&adapter->manufacturer);
ffStrbufInit(&adapter->modelName);
ffStrbufInit(&adapter->serial);
adapter->watts = 0;
ffCfDictGetString(details, CFSTR(kIOPSNameKey), &adapter->name);
if (ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName) != NULL)
{
+12 -19
View File
@@ -28,6 +28,14 @@ static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFl
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
return;
ffStrbufAppendS(dir, "/online");
char online = '1';
ffReadFileData(dir->chars, sizeof(online), &online);
ffStrbufSubstrBefore(dir, dirLength);
if (online == '0')
return;
//input_power_limit must exist and be not empty
ffStrbufAppendS(dir, "/input_power_limit");
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
@@ -35,24 +43,14 @@ static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFl
if (!available)
return;
FFPowerAdapterResult* result = ffListAdd(results);
ffStrbufInit(&result->name);
ffStrbufInit(&result->description);
ffStrbufAppendS(dir, "/online");
char online = '1';
ffReadFileData(dir->chars, sizeof(online), &online);
ffStrbufSubstrBefore(dir, dirLength);
if (online == '0')
result->watts = FF_POWERADAPTER_NOT_CONNECTED;
else
result->watts = (int) (ffStrbufToDouble(&tmpBuffer) / 1e6 + 0.5);
//At this point, we have a battery. Try to get as much values as possible.
result->watts = (int) (ffStrbufToDouble(&tmpBuffer) / 1e6 + 0.5);
ffStrbufInit(&result->manufacturer);
ffStrbufInit(&result->modelName);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/manufacturer");
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
ffStrbufTrimRightSpace(&result->manufacturer);
@@ -60,13 +58,11 @@ static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFl
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->modelName);
ffStrbufAppendS(dir, "/model_name");
if (ffReadFileBuffer(dir->chars, &result->modelName))
ffStrbufTrimRightSpace(&result->modelName);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/serial_number");
if (ffReadFileBuffer(dir->chars, &result->serial))
ffStrbufTrimRightSpace(&result->serial);
@@ -95,8 +91,5 @@ const char* ffDetectPowerAdapter(FFlist* results)
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
if(results->length == 0)
return "\"/sys/class/power_supply/\" doesn't contain any power adapter folder";
return NULL;
}
+2 -2
View File
@@ -17,8 +17,8 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
IMMDeviceEnumerator* FF_AUTO_RELEASE_COM_OBJECT pEnum = NULL;
if (FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&pEnum)))
return "CoCreateInstance(__uuidof(MMDeviceEnumerator)) failed";
if (FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&pEnum)))
return "CoCreateInstance(CLSID_MMDeviceEnumerator) failed";
LPWSTR mainDeviceId = NULL;
+11 -1
View File
@@ -170,7 +170,17 @@ static void detectFromWindowsTeriminal(const FFstrbuf* terminalExe, FFTerminalFo
if(terminalExe && terminalExe->length > 0 && !ffStrbufEqualS(terminalExe, "Windows Terminal"))
{
char jsonPath[MAX_PATH + 1];
if(SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, jsonPath)))
strncpy(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1);
char* pathEnd = jsonPath + strlen(jsonPath);
strncpy(pathEnd, ".portable", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
if(ffPathExists(jsonPath, FF_PATHTYPE_FILE))
{
strncpy(pathEnd, "settings\\settings.json", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
if(!ffAppendFileBuffer(jsonPath, &json))
error = "Error reading Windows Terminal portable settings JSON file";
}
else if(SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, jsonPath)))
{
size_t remaining = sizeof(jsonPath) - strlen(jsonPath) - 1;
if(ffStrbufContainIgnCaseS(terminalExe, "_8wekyb3d8bbwe\\"))
@@ -356,6 +356,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionXterm(FFstrbuf* exe, FFstrbuf* ver
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionBlackbox(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdOut(version, (char* const[]){
exe->chars,
"--version",
NULL
})) return false;
//BlackBox version 0.14.0 (flatpak)
ffStrbufSubstrAfterFirstS(version, "version ");
ffStrbufSubstrBeforeFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionUrxvt(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]){
@@ -482,6 +496,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
if(ffStrbufIgnCaseEqualS(processName, "xterm"))
return getTerminalVersionXterm(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "blackbox"))
return getTerminalVersionBlackbox(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "st"))
return getTerminalVersionSt(exe, version);
@@ -285,6 +285,9 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrEquals(name, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
ffStrEquals(name, "login") ||
ffStrEquals(name, "sshd") ||
#ifdef __linux__
ffStrStartsWith(name, "flatpak-") || // #707
#endif
ffStrEndsWith(name, ".sh")
)
{
@@ -298,10 +298,11 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
{
if(!hasGui)
{
//We are nested shell
//We are in nested shell
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
ffStrbufClear(&result->exePath);
result->exeName = "";
pid = ppid;
continue;
@@ -320,6 +321,7 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
ffStrbufClear(&result->exePath);
result->exeName = "";
return 0;
}
+16 -1
View File
@@ -222,7 +222,22 @@ static bool printSpecificCommandHelp(const char* command)
yyjson_val* remarkKey = yyjson_obj_get(flagObj, "remark");
if (remarkKey)
printf("%10s: %s\n", "Remark", yyjson_get_str(remarkKey));
{
if (yyjson_is_str(remarkKey))
printf("%10s: %s\n", "Remark", yyjson_get_str(remarkKey));
else if (yyjson_is_arr(remarkKey) && yyjson_arr_size(remarkKey) > 0)
{
yyjson_val* remarkStr;
size_t remarkIdx, remarkMax;
yyjson_arr_foreach(remarkKey, remarkIdx, remarkMax, remarkStr)
{
if (remarkIdx == 0)
printf("%10s: %s\n", "Remark", yyjson_get_str(remarkStr));
else
printf(" %s\n", yyjson_get_str(remarkStr));
}
}
}
return true;
}
+18
View File
@@ -0,0 +1,18 @@
$1_wwM $2_ww
$1MMM$2MMMM
$1MM
$3_ww##############yy_
$4wMMMMM$3###########$4MMMMm
$4,MMMMMMMMM$3######$4MMMMMMMM0_
$4wMMMMMMMMMMMMM$5MM$60MMMMMMMMMMm
$4,MMMMMMMMMMMMMMM$5MMMM$60MMMMMMMMM0,
$4wMMMMMMMMMMMMMMMM$5MMMMM0$6MMMMMMMMMMb
$4_MMMMMMMMMMMMMMMMMM$5MMMMMMM0$6MMMMMMMMM0,
$4_MMMMMMMMMMMMMMMMMMM$5MMMM$7M$5MMMW$6MMMMMMMMMM_
$4_MMMMMMMMMMMMMMMMMMMM$5MMMM$7M0$5MMMW$6MMMMMMMMMM_
$4~MMMMMMMMMMMMMMMMM$5MMMM$7M$5MMMW$6MMMMM00~
$4~MMMMMMMMMMMMM$5MMMWMMM$60MM$5MMM$6~
$4~MMMMMMMMMM$5MMMMM$60MMM~~
$4~MMMMMM$5MMM$60MM~
$4~MM$5M$6@~
$4M
+28
View File
@@ -0,0 +1,28 @@
'',,, ,,,d,
',, ,,'
', ,.
., '
. .
' .
.. oddddkdlc:;,.. ..
. ............lllc, .
. ....................: .
. . ....................
'. ..........'o........d0XX0.
....lllllllcOOOcllllll............cxlxc...;okkkx.
..................................';lc'...lo.
.'''''''''''''.....................,;,.......
',,,,,,,,,,,,,,,,''...............dkkkd......
',,,,,,,,,,,,,,,,,,,'............;okkkd;....
.,,,,,,,,,,,,,,,,,,,,,............;cll;.....
,,,,,,,,,,,,,,,,,,,,'....................:d,
,,,,,,,,,,,,,,,,,,,....................oxxx:
.,,,,,,,,,,,,,,,,,'..................oxxxxx. .
.,,,,,,,,,,,,,,'.......... ,oxxxxxxx .
.;,,,,,,,,,,,,'.. 'cxxxxxxxxx,
:dl:,'',,'.... .;lxxxxxxxxxd;
,codol:;'. ...,;cldxxxxxxxxxoc.
.:cxxxxxdlccccc:ccldxxxxxxxxxxxxxx::.
.'::dxxxxxxxxxxxxxxxxxxxxxxxd::'.
..,::cdxxxxxxxxxxxxxdc::,..
...,;:::::::;,...
+15
View File
@@ -0,0 +1,15 @@
. .:. . .:.
.^^.!.:::. .^!?J?^
.:^.^!!!~:~^. .7??77!~~^.
.~^.!??77?!.^~: ..:^^7JJJ7~~^.
.^~.^7???7~.~~. .7??????????!
.:^:^^~^^:!^ ^: .......^!:...
.!7~.::.!.::. ~BG~ :^ ^~:
:!!~ ~. ?BBBB! ^?J!. .!~.
:!. .JBY. .Y#BBBY?~!???J7. :^^.
.. :5#B#P~P#BBP?7?55J?J7:
^P#BBBBBBBB5?7J5555J!.....
!BBBBBBGBBGJ77::Y555J?77777^
?BBBBG5JJ5PJ?!: .?Y??????77?~.
.YBGPYJ??????Y?^^^^~7?????????7?!.
.^^:..::::::::.....:::::::::::..:.
+7
View File
@@ -0,0 +1,7 @@
// OOOOOOO SSSSSSS
// OO OO SS
zzzzzz // OO OO SS
zz // OO OO SSSS
zz // OO OO SS
zz // OO OO SS
zzzzzz // OOOOOOO SSSSSSS
+58
View File
@@ -468,6 +468,23 @@ static const FFlogo A[] = {
.colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_GREEN,
},
// Asahi2
{
.names = {"asahi2", "asahi-linux2"},
.lines = FASTFETCH_DATATEXT_LOGO_ASAHI2,
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
.colors = {
FF_COLOR_FG_LIGHT_YELLOW,
FF_COLOR_FG_CYAN,
FF_COLOR_FG_RED,
FF_COLOR_FG_LIGHT_RED,
FF_COLOR_FG_WHITE,
FF_COLOR_FG_BLACK,
FF_COLOR_FG_LIGHT_CYAN,
},
.colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_GREEN,
},
// Aster
{
.names = {"aster"},
@@ -1445,6 +1462,22 @@ static const FFlogo F[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// FedoraAsahiRemix
{
.names = {"fedora-asahi-remix"},
.lines = FASTFETCH_DATATEXT_LOGO_ASAHI,
.colors = {
FF_COLOR_FG_YELLOW,
FF_COLOR_FG_GREEN,
FF_COLOR_FG_RED,
"38", //cyan
FF_COLOR_FG_WHITE,
FF_COLOR_FG_CYAN,
FF_COLOR_FG_BLUE,
},
.colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_GREEN,
},
// FedoraSmall
{
.names = {"Fedora_small", "fedora-linux-small"},
@@ -3189,6 +3222,14 @@ static const FFlogo P[] = {
FF_COLOR_FG_WHITE,
},
},
// PikaOS
{
.names = {"PikaOS"},
.lines = FASTFETCH_DATATEXT_LOGO_PIKAOS,
.colors = {
FF_COLOR_FG_YELLOW,
},
},
// Pisi
{
.names = {"Pisi"},
@@ -3882,6 +3923,15 @@ static const FFlogo T[] = {
FF_COLOR_FG_WHITE,
},
},
// Tatra
{
.names = {"Tatra"},
.lines = FASTFETCH_DATATEXT_LOGO_TATRA,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_GREEN,
},
},
// TeArch
{
.names = {"TeArch"},
@@ -4389,6 +4439,14 @@ static const FFlogo Z[] = {
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// Z/OS
{
.names = {"z/OS", "zos"},
.lines = FASTFETCH_DATATEXT_LOGO_ZOS,
.colors = {
FF_COLOR_FG_BLUE,
},
},
// LAST
{},
};
+170
View File
@@ -0,0 +1,170 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/libc/libc.h"
#include "detection/camera/camera.h"
#include "modules/camera/camera.h"
#include "util/stringUtils.h"
#define FF_CAMERA_NUM_FORMAT_ARGS 5
static void printDevice(FFCameraOptions* options, const FFCameraResult* device, uint8_t index)
{
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&device->name, stdout);
if (device->colorspace.length > 0)
{
fputs(" - ", stdout);
ffStrbufWriteTo(&device->colorspace, stdout);
}
if (device->width > 0 && device->height > 0)
printf(" (%ux%u px)\n", (unsigned) device->width, (unsigned) device->height);
else
putchar('\n');
}
else
{
ffPrintFormat(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_CAMERA_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->colorspace},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->id},
{FF_FORMAT_ARG_TYPE_UINT, &device->width},
{FF_FORMAT_ARG_TYPE_UINT, &device->height},
});
}
}
void ffPrintCamera(FFCameraOptions* options)
{
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFCameraResult));
const char* error = ffDetectCamera(&result);
if (error)
{
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, "%s", error);
return;
}
if (result.length == 0)
{
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, "No camera found");
return;
}
for(uint32_t i = 0; i < result.length; i++)
{
uint8_t index = (uint8_t) (result.length == 1 ? 0 : i + 1);
printDevice(options, FF_LIST_GET(FFCameraResult, result, i), index);
}
FF_LIST_FOR_EACH(FFCameraResult, dev, result)
{
ffStrbufDestroy(&dev->name);
ffStrbufDestroy(&dev->id);
ffStrbufDestroy(&dev->colorspace);
}
}
bool ffParseCameraCommandOptions(FFCameraOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_CAMERA_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
return false;
}
void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module)
{
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
void ffGenerateCameraJsonConfig(FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
__attribute__((__cleanup__(ffDestroyCameraOptions))) FFCameraOptions defaultOptions;
ffInitCameraOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
}
void ffGenerateCameraJsonResult(FF_MAYBE_UNUSED FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFCameraResult));
const char* error = ffDetectCamera(&result);
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFCameraResult, dev, result)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &dev->vendor);
yyjson_mut_obj_add_strbuf(doc, obj, "colorSpace", &dev->colorspace);
yyjson_mut_obj_add_strbuf(doc, obj, "id", &dev->id);
yyjson_mut_obj_add_uint(doc, obj, "width", dev->width);
yyjson_mut_obj_add_uint(doc, obj, "height", dev->height);
}
FF_LIST_FOR_EACH(FFCameraResult, dev, result)
{
ffStrbufDestroy(&dev->name);
ffStrbufDestroy(&dev->id);
ffStrbufDestroy(&dev->colorspace);
}
}
void ffPrintCameraHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_CAMERA_MODULE_NAME, "{1} ({4}px x {5}px)", FF_CAMERA_NUM_FORMAT_ARGS, (const char* []) {
"Device name",
"Vendor",
"Color space",
"Identifier",
"Width (in px)",
"Height (in px)",
});
}
void ffInitCameraOptions(FFCameraOptions* options)
{
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_CAMERA_MODULE_NAME,
"Print available cameras",
ffParseCameraCommandOptions,
ffParseCameraJsonObject,
ffPrintCamera,
ffGenerateCameraJsonResult,
ffPrintCameraHelpFormat,
ffGenerateCameraJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs);
}
void ffDestroyCameraOptions(FFCameraOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fastfetch.h"
#define FF_CAMERA_MODULE_NAME "Camera"
void ffPrintCamera(FFCameraOptions* options);
void ffInitCameraOptions(FFCameraOptions* options);
void ffDestroyCameraOptions(FFCameraOptions* options);
+11
View File
@@ -0,0 +1,11 @@
#pragma once
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
typedef struct FFCameraOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
} FFCameraOptions;
+128 -18
View File
@@ -4,37 +4,55 @@
#include "modules/colors/colors.h"
#include "util/stringUtils.h"
static inline uint8_t min(uint8_t a, uint8_t b)
{
return a < b ? a : b;
}
static inline uint8_t max(uint8_t a, uint8_t b)
{
return a > b ? a : b;
}
void ffPrintColors(FFColorsOptions* options)
{
if(instance.config.display.pipe)
return;
ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
bool flag = false;
if(options->paddingLeft > 0)
ffPrintCharTimes(' ', options->paddingLeft);
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(128);
if (options->symbol == FF_COLORS_SYMBOL_BLOCK)
{
// 4%d: Set the background color
// 3%d: Set the foreground color
for(uint8_t i = 0; i < 8; i++)
printf("\033[3%dm███", i);
for(uint8_t i = options->block.range[0]; i <= min(options->block.range[1], 7); i++)
{
ffStrbufAppendF(&result, "\e[3%dm", i);
for (uint8_t j = 0; j < options->block.width; j++)
ffStrbufAppendS(&result, "");
}
if (result.length > 0)
{
ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
flag = true;
puts(FASTFETCH_TEXT_MODIFIER_RESET);
if(options->paddingLeft > 0)
ffPrintCharTimes(' ', options->paddingLeft);
ffLogoPrintLine();
if(options->paddingLeft > 0)
ffPrintCharTimes(' ', options->paddingLeft);
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
ffStrbufPutTo(&result, stdout);
ffStrbufClear(&result);
}
// 1: Set everything to bolt. This causes normal colors on some systems to be bright.
// 4%d: Set the background to the not bright color
// 3%d: Set the foreground to the not bright color
// 10%d: Set the background to the bright color
// 9%d: Set the foreground to the bright color
for(uint8_t i = 0; i < 8; i++)
printf("\033[1;3%d;9%dm███", i, i);
for(uint8_t i = max(options->block.range[0], 8); i <= options->block.range[1]; i++)
{
ffStrbufAppendF(&result, "\e[1;9%dm", i - 8);
for (uint8_t j = 0; j < options->block.width; j++)
ffStrbufAppendS(&result, "");
}
}
else
{
@@ -49,10 +67,29 @@ void ffPrintColors(FFColorsOptions* options)
default: symbol = "███"; break;
}
for (int i = 8; i >= 1; --i)
printf("\e[3%dm%s ", i, symbol);
ffStrbufAppendF(&result, "\e[3%dm%s ", i, symbol);
}
puts(FASTFETCH_TEXT_MODIFIER_RESET);
if (result.length > 0)
{
if (flag)
ffLogoPrintLine();
else
{
ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
flag = true;
}
if(options->paddingLeft > 0)
ffPrintCharTimes(' ', options->paddingLeft);
ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET);
ffStrbufPutTo(&result, stdout);
}
if (!flag)
{
ffPrintError(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, "%s", "Nothing to print");
}
}
bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, const char* value)
@@ -82,6 +119,24 @@ bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, cons
return true;
}
if (ffStrEqualsIgnCase(subKey, "block-width"))
{
options->block.width = (uint8_t) ffOptionParseUInt32(key, value);
return true;
}
if (ffStrEqualsIgnCase(subKey, "block-range-start"))
{
options->block.range[0] = min((uint8_t) ffOptionParseUInt32(key, value), 15);
return true;
}
if (ffStrEqualsIgnCase(subKey, "block-range-end"))
{
options->block.range[1] = min((uint8_t) ffOptionParseUInt32(key, value), 15);
return true;
}
return false;
}
@@ -123,6 +178,40 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module)
continue;
}
if (ffStrEqualsIgnCase(key, "block"))
{
if (!yyjson_is_obj(val))
ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", key);
else
{
yyjson_val* width = yyjson_obj_get(val, "width");
if (width)
options->block.width = (uint8_t) yyjson_get_uint(width);
yyjson_val* range = yyjson_obj_get(val, "range");
if (range)
{
if (!yyjson_is_arr(range) || yyjson_arr_size(range) != 2)
ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", key);
else
{
uint8_t start = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 0));
uint8_t end = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 1));
if (start > end)
ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", key);
else if (end > 15)
ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", key);
else
{
options->block.range[0] = start;
options->block.range[1] = end;
}
}
}
}
continue;
}
ffPrintErrorString(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key);
}
}
@@ -149,6 +238,23 @@ void ffGenerateColorsJsonConfig(FFColorsOptions* options, yyjson_mut_doc* doc, y
if (defaultOptions.paddingLeft != options->paddingLeft)
yyjson_mut_obj_add_uint(doc, module, "paddingLeft", options->paddingLeft);
{
yyjson_mut_val* block = yyjson_mut_obj(doc);
if (defaultOptions.block.width != options->block.width)
yyjson_mut_obj_add_uint(doc, block, "width", options->block.width);
if (memcmp(defaultOptions.block.range, options->block.range, sizeof(options->block.range)) != 0)
{
yyjson_mut_val* range = yyjson_mut_obj_add_arr(doc, block, "range");
for (uint8_t i = 0; i < 2; i++)
yyjson_mut_arr_add_uint(doc, range, options->block.range[i]);
}
if (yyjson_mut_obj_size(block) > 0)
yyjson_mut_obj_add_val(doc, module, "block", block);
}
}
void ffInitColorsOptions(FFColorsOptions* options)
@@ -168,6 +274,10 @@ void ffInitColorsOptions(FFColorsOptions* options)
ffStrbufSetStatic(&options->moduleArgs.key, " ");
options->symbol = FF_COLORS_SYMBOL_BLOCK;
options->paddingLeft = 0;
options->block = (FFBlockConfig) {
.width = 3,
.range = { 0, 15 },
};
}
void ffDestroyColorsOptions(FF_MAYBE_UNUSED FFColorsOptions* options)
+7
View File
@@ -14,6 +14,12 @@ typedef enum FFColorsSymbol
FF_COLORS_SYMBOL_STAR,
} FFColorsSymbol;
typedef struct FFBlockConfig
{
uint8_t width;
uint8_t range[2];
} FFBlockConfig;
typedef struct FFColorsOptions
{
FFModuleBaseInfo moduleInfo;
@@ -21,4 +27,5 @@ typedef struct FFColorsOptions
FFColorsSymbol symbol;
uint32_t paddingLeft;
FFBlockConfig block;
} FFColorsOptions;
+26 -8
View File
@@ -58,18 +58,21 @@ void ffPrintDiskIO(FFDiskIOOptions* options)
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffParseSize(dev->bytesRead, &buffer);
ffStrbufAppendS(&buffer, "/s (R) - ");
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (R) - ");
ffParseSize(dev->bytesWritten, &buffer);
ffStrbufAppendS(&buffer, "/s (W)");
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (W)");
ffStrbufPutTo(&buffer, stdout);
}
else
{
ffStrbufClear(&buffer2);
ffParseSize(dev->bytesRead, &buffer);
ffStrbufAppendS(&buffer, "/s");
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffParseSize(dev->bytesWritten, &buffer2);
ffStrbufAppendS(&buffer2, "/s");
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISKIO_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &buffer},
@@ -105,6 +108,12 @@ bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, cons
return true;
}
if (ffStrEqualsIgnCase(subKey, "detect-total"))
{
options->detectTotal = ffOptionParseBoolean(value);
return true;
}
return false;
}
@@ -127,6 +136,12 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module)
continue;
}
if (ffStrEqualsIgnCase(key, "detectTotal"))
{
options->detectTotal = yyjson_get_bool(val);
continue;
}
ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -140,6 +155,9 @@ void ffGenerateDiskIOJsonConfig(FFDiskIOOptions* options, yyjson_mut_doc* doc, y
if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix))
yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix);
if (defaultOptions.detectTotal != options->detectTotal)
yyjson_mut_obj_add_bool(doc, module, "detectTotal", options->detectTotal);
}
void ffGenerateDiskIOJsonResult(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -175,12 +193,12 @@ void ffGenerateDiskIOJsonResult(FFDiskIOOptions* options, yyjson_mut_doc* doc, y
void ffPrintDiskIOHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_DISKIO_MODULE_NAME, "{1} (R) - {2} (W)", FF_DISKIO_NUM_FORMAT_ARGS, (const char* []) {
"Size of data read per second (formatted)",
"Size of data written per second (formatted)",
"Size of data read [per second] (formatted)",
"Size of data written [per second] (formatted)",
"Device name",
"Device raw file path",
"Size of data read per second (in bytes)",
"Size of data written per second (in bytes)",
"Size of data read [per second] (in bytes)",
"Size of data written [per second] (in bytes)",
"Number of reads",
"Number of writes",
});
+1
View File
@@ -10,4 +10,5 @@ typedef struct FFDiskIOOptions
FFModuleArgs moduleArgs;
FFstrbuf namePrefix;
bool detectTotal;
} FFDiskIOOptions;
+76 -8
View File
@@ -6,6 +6,16 @@
#define FF_DISPLAY_NUM_FORMAT_ARGS 8
static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b)
{
return ffStrbufComp(&a->name, &b->name);
}
static int sortByNameDesc(FFDisplayResult* a, FFDisplayResult* b)
{
return -ffStrbufComp(&a->name, &b->name);
}
void ffPrintDisplay(FFDisplayOptions* options)
{
const FFDisplayServerResult* dsResult = ffConnectDisplayServer();
@@ -16,25 +26,46 @@ void ffPrintDisplay(FFDisplayOptions* options)
return;
}
if (options->order != FF_DISPLAY_ORDER_NONE)
{
ffListSort((FFlist*) &dsResult->displays, (void*) (options->order == FF_DISPLAY_ORDER_ASC ? sortByNameAsc : sortByNameDesc));
}
if (options->compactType != FF_DISPLAY_COMPACT_TYPE_NONE)
{
ffPrintLogoAndKey(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
int index = 0;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
FF_LIST_FOR_EACH(FFDisplayResult, result, dsResult->displays)
{
if (options->compactType & FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT)
{
if (index++) putchar(' ');
printf("%ix%i", result->width, result->height);
ffStrbufAppendF(&buffer, "%ix%i", result->width, result->height);
}
if (options->compactType & FF_DISPLAY_COMPACT_TYPE_SCALED_BIT)
else
{
if (index++) putchar(' ');
printf("%ix%i", result->scaledWidth, result->scaledHeight);
ffStrbufAppendF(&buffer, "%ix%i", result->scaledWidth, result->scaledHeight);
}
if (options->compactType & FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT)
{
if (result->refreshRate > 0)
{
if (options->preciseRefreshRate)
ffStrbufAppendF(&buffer, " @ %gHz", result->refreshRate);
else
ffStrbufAppendF(&buffer, " @ %iHz", (uint32_t) (result->refreshRate + 0.5));
}
ffStrbufAppendS(&buffer, ", ");
}
else
{
ffStrbufAppendC(&buffer, ' ');
}
}
putchar('\n');
ffStrbufTrimRight(&buffer, ' ');
ffStrbufTrimRight(&buffer, ',');
ffStrbufPutTo(&buffer, stdout);
return;
}
@@ -122,6 +153,8 @@ bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, co
{ "none", FF_DISPLAY_COMPACT_TYPE_NONE },
{ "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT },
{ "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT },
{ "original-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT },
{ "scaled-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT },
{},
});
return true;
@@ -133,6 +166,17 @@ bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, co
return true;
}
if (ffStrEqualsIgnCase(subKey, "order"))
{
options->order = (FFDisplayOrder) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "asc", FF_DISPLAY_ORDER_ASC },
{ "desc", FF_DISPLAY_ORDER_DESC },
{ "none", FF_DISPLAY_ORDER_NONE },
{},
});
return true;
}
return false;
}
@@ -156,6 +200,8 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module)
{ "none", FF_DISPLAY_COMPACT_TYPE_NONE },
{ "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT },
{ "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT },
{ "original-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT },
{ "scaled-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT },
{},
});
if (error)
@@ -171,6 +217,22 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module)
continue;
}
if (ffStrEqualsIgnCase(key, "order"))
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "asc", FF_DISPLAY_ORDER_ASC },
{ "desc", FF_DISPLAY_ORDER_DESC },
{ "none", FF_DISPLAY_ORDER_NONE },
{},
});
if (error)
ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, "Invalid %s value: %s", key, error);
else
options->order = (FFDisplayOrder) value;
continue;
}
ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -184,7 +246,7 @@ void ffGenerateDisplayJsonConfig(FFDisplayOptions* options, yyjson_mut_doc* doc,
if (options->compactType != defaultOptions.compactType)
{
switch (options->compactType)
switch ((int) options->compactType)
{
case FF_DISPLAY_COMPACT_TYPE_NONE:
yyjson_mut_obj_add_str(doc, module, "compactType", "none");
@@ -195,6 +257,12 @@ void ffGenerateDisplayJsonConfig(FFDisplayOptions* options, yyjson_mut_doc* doc,
case FF_DISPLAY_COMPACT_TYPE_SCALED_BIT:
yyjson_mut_obj_add_str(doc, module, "compactType", "scaled");
break;
case FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT:
yyjson_mut_obj_add_str(doc, module, "compactType", "original-with-refresh-rate");
break;
case FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT:
yyjson_mut_obj_add_str(doc, module, "compactType", "scaled-with-refresh-rate");
break;
}
}
+9
View File
@@ -9,8 +9,16 @@ typedef enum FFDisplayCompactType
FF_DISPLAY_COMPACT_TYPE_NONE = 0,
FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT = 1 << 0,
FF_DISPLAY_COMPACT_TYPE_SCALED_BIT = 1 << 1,
FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT = 1 << 2,
} FFDisplayCompactType;
typedef enum FFDisplayOrder
{
FF_DISPLAY_ORDER_NONE,
FF_DISPLAY_ORDER_ASC,
FF_DISPLAY_ORDER_DESC,
} FFDisplayOrder;
typedef struct FFDisplayOptions
{
FFModuleBaseInfo moduleInfo;
@@ -18,4 +26,5 @@ typedef struct FFDisplayOptions
FFDisplayCompactType compactType;
bool preciseRefreshRate;
FFDisplayOrder order;
} FFDisplayOptions;
+1
View File
@@ -8,6 +8,7 @@
#include "modules/brightness/brightness.h"
#include "modules/board/board.h"
#include "modules/break/break.h"
#include "modules/camera/camera.h"
#include "modules/chassis/chassis.h"
#include "modules/cpu/cpu.h"
#include "modules/cpuusage/cpuusage.h"
+34 -15
View File
@@ -60,10 +60,14 @@ void ffPrintNetIO(FFNetIOOptions* options)
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffParseSize(inf->rxBytes, &buffer);
ffStrbufAppendS(&buffer, "/s (IN) - ");
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (IN) - ");
ffParseSize(inf->txBytes, &buffer);
ffStrbufAppendS(&buffer, "/s (OUT)");
if (!options->defaultRouteOnly && inf->defaultRoute)
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffStrbufAppendS(&buffer, " (OUT)");
if (inf->defaultRoute)
ffStrbufAppendS(&buffer, " *");
ffStrbufPutTo(&buffer, stdout);
}
@@ -71,9 +75,9 @@ void ffPrintNetIO(FFNetIOOptions* options)
{
ffStrbufClear(&buffer2);
ffParseSize(inf->rxBytes, &buffer);
ffStrbufAppendS(&buffer, "/s");
if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s");
ffParseSize(inf->txBytes, &buffer2);
ffStrbufAppendS(&buffer2, "/s");
if (!options->detectTotal) ffStrbufAppendS(&buffer2, "/s");
ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETIO_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &buffer},
@@ -118,6 +122,12 @@ bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const
return true;
}
if (ffStrEqualsIgnCase(subKey, "detect-total"))
{
options->detectTotal = ffOptionParseBoolean(value);
return true;
}
return false;
}
@@ -146,6 +156,12 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module)
continue;
}
if (ffStrEqualsIgnCase(key, "detectTotal"))
{
options->detectTotal = yyjson_get_bool(val);
continue;
}
ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -162,6 +178,9 @@ void ffGenerateNetIOJsonConfig(FFNetIOOptions* options, yyjson_mut_doc* doc, yyj
if (options->defaultRouteOnly != defaultOptions.defaultRouteOnly)
yyjson_mut_obj_add_bool(doc, module, "defaultRouteOnly", options->defaultRouteOnly);
if (options->detectTotal != defaultOptions.detectTotal)
yyjson_mut_obj_add_bool(doc, module, "detectTotal", options->detectTotal);
}
void ffGenerateNetIOJsonResult(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -200,18 +219,18 @@ void ffGenerateNetIOJsonResult(FFNetIOOptions* options, yyjson_mut_doc* doc, yyj
void ffPrintNetIOHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_NETIO_MODULE_NAME, "{1} (IN) - {2} (OUT)", FF_NETIO_NUM_FORMAT_ARGS, (const char* []) {
"Size of data received per second (formatted)",
"Size of data sent per second (formatted)",
"Size of data received [per second] (formatted)",
"Size of data sent [per second] (formatted)",
"Interface name",
"Is default route",
"Size of data received per second (in bytes)",
"Size of data sent per second (in bytes)",
"Number of packets received per second",
"Number of packets sent per second",
"Number of errors received per second",
"Number of errors sent per second",
"Number of packets dropped when receiving per second",
"Number of packets dropped when sending per second",
"Size of data received [per second] (in bytes)",
"Size of data sent [per second] (in bytes)",
"Number of packets received [per second]",
"Number of packets sent [per second]",
"Number of errors received [per second]",
"Number of errors sent [per second]",
"Number of packets dropped when receiving [per second]",
"Number of packets dropped when sending [per second]",
});
}
+1
View File
@@ -11,4 +11,5 @@ typedef struct FFNetIOOptions
FFstrbuf namePrefix;
bool defaultRouteOnly;
bool detectTotal;
} FFNetIOOptions;
+1
View File
@@ -8,6 +8,7 @@
#include "modules/board/option.h"
#include "modules/break/option.h"
#include "modules/brightness/option.h"
#include "modules/camera/option.h"
#include "modules/chassis/option.h"
#include "modules/cpu/option.h"
#include "modules/cpuusage/option.h"
+25 -3
View File
@@ -4,12 +4,34 @@
#include "common/option.h"
typedef enum FFPackagesFlags
{
FF_PACKAGES_FLAG_NONE = 0,
FF_PACKAGES_FLAG_APK_BIT = 1 << 0,
FF_PACKAGES_FLAG_BREW_BIT = 1 << 1,
FF_PACKAGES_FLAG_CHOCO_BIT = 1 << 2,
FF_PACKAGES_FLAG_DPKG_BIT = 1 << 3,
FF_PACKAGES_FLAG_EMERGE_BIT = 1 << 4,
FF_PACKAGES_FLAG_EOPKG_BIT = 1 << 5,
FF_PACKAGES_FLAG_FLATPAK_BIT = 1 << 6,
FF_PACKAGES_FLAG_NIX_BIT = 1 << 7,
FF_PACKAGES_FLAG_OPKG_BIT = 1 << 8,
FF_PACKAGES_FLAG_PACMAN_BIT = 1 << 9,
FF_PACKAGES_FLAG_PALUDIS_BIT = 1 << 10,
FF_PACKAGES_FLAG_PKG_BIT = 1 << 11,
FF_PACKAGES_FLAG_PKGTOOL_BIT = 1 << 12,
FF_PACKAGES_FLAG_MACPORTS_BIT = 1 << 13,
FF_PACKAGES_FLAG_RPM_BIT = 1 << 14,
FF_PACKAGES_FLAG_SCOOP_BIT = 1 << 15,
FF_PACKAGES_FLAG_SNAP_BIT = 1 << 16,
FF_PACKAGES_FLAG_WINGET_BIT = 1 << 17,
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
} FFPackagesFlags;
typedef struct FFPackagesOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
#ifdef _WIN32
bool winget;
#endif
FFPackagesFlags disabled;
} FFPackagesOptions;
+113 -19
View File
@@ -28,7 +28,7 @@ void ffPrintPackages(FFPackagesOptions* options)
{ \
printf("%u (%s)", counts.var, (name)); \
if((all -= counts.var) > 0) \
printf(", "); \
fputs(", ", stdout); \
};
#define FF_PRINT_PACKAGE(name) FF_PRINT_PACKAGE_NAME(name, #name)
@@ -42,7 +42,6 @@ void ffPrintPackages(FFPackagesOptions* options)
if((all -= counts.pacman) > 0)
printf(", ");
};
FF_PRINT_PACKAGE(dpkg)
FF_PRINT_PACKAGE(rpm)
FF_PRINT_PACKAGE(emerge)
@@ -109,13 +108,52 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
#ifdef _WIN32
if(ffStrEqualsIgnCase(subKey, "winget"))
if (ffStrEqualsIgnCase(subKey, "disabled"))
{
options->winget = ffOptionParseBoolean(value);
options->disabled = FF_PACKAGES_FLAG_NONE;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
ffOptionParseString(key, value, &buffer);
char *start = buffer.chars, *end = strchr(start, ':');
while (true)
{
if (end)
*end = '\0';
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(start, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
#undef FF_TEST_PACKAGE_NAME
if (end)
{
start = end + 1;
end = strchr(end, ':');
}
else
break;
}
return true;
}
#endif
return false;
}
@@ -127,19 +165,55 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
if (ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
#ifdef _WIN32
if (ffStrEqualsIgnCase(key, "winget"))
if (ffStrEqualsIgnCase(key, "disabled"))
{
options->winget = yyjson_get_bool(val);
continue;
if (!yyjson_is_null(val) && !yyjson_is_arr(val))
{
ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, "Invalid JSON value for %s", key);
continue;
}
options->disabled = FF_PACKAGES_FLAG_NONE;
if (yyjson_is_arr(val))
{
yyjson_val* flagObj;
size_t flagIdx, flagMax;
yyjson_arr_foreach(val, flagIdx, flagMax, flagObj)
{
const char* flag = yyjson_get_str(flagObj);
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(flag, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
#undef FF_TEST_PACKAGE_NAME
}
}
}
#endif
ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
@@ -152,10 +226,32 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
#ifdef _WIN32
if (options->winget != defaultOptions.winget)
yyjson_mut_obj_add_bool(doc, module, "winget", options->winget);
#endif
if (options->disabled != defaultOptions.disabled)
{
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "disabled");
#define FF_TEST_PACKAGE_NAME(name) else if ((options->disabled & FF_PACKAGES_FLAG_ ## name ## _BIT) != (defaultOptions.disabled & FF_PACKAGES_FLAG_ ## name ## _BIT)) { yyjson_mut_arr_add_str(doc, arr, #name); }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
#undef FF_TEST_PACKAGE_NAME
}
}
void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -248,9 +344,7 @@ void ffInitPackagesOptions(FFPackagesOptions* options)
);
ffOptionInitModuleArg(&options->moduleArgs);
#ifdef _WIN32
options->winget = false;
#endif
options->disabled = FF_PACKAGES_FLAG_WINGET_BIT;
}
void ffDestroyPackagesOptions(FFPackagesOptions* options)
-2
View File
@@ -33,8 +33,6 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options)
if(result->name.length > 0)
puts(result->name.chars);
else if(result->watts == FF_POWERADAPTER_NOT_CONNECTED)
puts("not connected");
else
printf("%dW\n", result->watts);
}
-7
View File
@@ -29,8 +29,6 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va
ffStrbufSetS(&options->libZ, yyjson_get_str(val));
#if defined(__linux__) || defined(__FreeBSD__)
else if (ffStrEqualsIgnCase(key, "pci"))
ffStrbufSetS(&options->libPCI, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "freetype"))
ffStrbufSetS(&options->libfreetype, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "wayland"))
@@ -95,8 +93,6 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key
ffOptionParseString(key, value, &options->libZ);
#if defined(__linux__) || defined(__FreeBSD__)
else if(ffStrEqualsIgnCase(subkey, "PCI"))
ffOptionParseString(key, value, &options->libPCI);
else if(ffStrEqualsIgnCase(subkey, "freetype"))
ffOptionParseString(key, value, &options->libfreetype);
else if(ffStrEqualsIgnCase(subkey, "wayland"))
@@ -183,9 +179,6 @@ void ffOptionsGenerateLibraryJsonConfig(FFOptionsLibrary* options, yyjson_mut_do
yyjson_mut_obj_add_strbuf(doc, obj, "z", &options->libZ);
#if defined(__linux__) || defined(__FreeBSD__)
if (!ffStrbufEqual(&options->libPCI, &defaultOptions.libPCI))
yyjson_mut_obj_add_strbuf(doc, obj, "PCI", &options->libPCI);
if (!ffStrbufEqual(&options->libWayland, &defaultOptions.libWayland))
yyjson_mut_obj_add_strbuf(doc, obj, "wayland", &options->libWayland);
-1
View File
@@ -12,7 +12,6 @@ typedef struct FFOptionsLibrary
FFstrbuf libZ;
#if defined(__linux__) || defined(__FreeBSD__)
FFstrbuf libPCI;
FFstrbuf libWayland;
FFstrbuf libXcbRandr;
FFstrbuf libXcb;
+2
View File
@@ -9,6 +9,7 @@ void ffOptionsInitModules(FFOptionsModules* options)
ffInitBoardOptions(&options->board);
ffInitBreakOptions(&options->break_);
ffInitBrightnessOptions(&options->brightness);
ffInitCameraOptions(&options->camera);
ffInitCPUOptions(&options->cpu);
ffInitCPUUsageOptions(&options->cpuUsage);
ffInitChassisOptions(&options->chassis);
@@ -72,6 +73,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options)
ffDestroyBoardOptions(&options->board);
ffDestroyBreakOptions(&options->break_);
ffDestroyBrightnessOptions(&options->brightness);
ffDestroyCameraOptions(&options->camera);
ffDestroyCPUOptions(&options->cpu);
ffDestroyCPUUsageOptions(&options->cpuUsage);
ffDestroyChassisOptions(&options->chassis);
+1
View File
@@ -12,6 +12,7 @@ typedef struct FFOptionsModules
FFBrightnessOptions brightness;
FFCPUOptions cpu;
FFCPUUsageOptions cpuUsage;
FFCameraOptions camera;
FFChassisOptions chassis;
FFColorsOptions colors;
FFCommandOptions command;
-5
View File
@@ -300,11 +300,6 @@ static inline int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp)
return memcmp(strbuf->chars, comp->chars, length + 1);
}
static inline int ffStrbufCompAlphabetically(const FFstrbuf* strbuf, const FFstrbuf* comp)
{
return strcmp(strbuf->chars, comp->chars);
}
static inline FF_C_NODISCARD bool ffStrbufEqual(const FFstrbuf* strbuf, const FFstrbuf* comp)
{
return ffStrbufComp(strbuf, comp) == 0;
+4
View File
@@ -7,6 +7,7 @@
#include <pwd.h>
#include <limits.h>
#include <sys/utsname.h>
#include <paths.h>
#ifdef __APPLE__
#include <libproc.h>
@@ -135,6 +136,9 @@ static void getDataDirs(FFPlatform* platform)
ffPlatformPathAddHome(&platform->dataDirs, platform, "");
platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS");
#ifdef _PATH_LOCALBASE
ffPlatformPathAddAbsolute(&platform->dataDirs, _PATH_LOCALBASE "/share/");
#endif
ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/");
ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/");
}
+49 -17
View File
@@ -40,8 +40,14 @@ static void getHomeDir(FFPlatform* platform)
ffStrbufSetWS(&platform->homeDir, pPath);
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
CoTaskMemFree(pPath);
}
else
{
ffStrbufSetS(&platform->homeDir, getenv("USERPROFILE"));
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
CoTaskMemFree(pPath);
}
static void getCacheDir(FFPlatform* platform)
@@ -52,13 +58,13 @@ static void getCacheDir(FFPlatform* platform)
ffStrbufSetWS(&platform->cacheDir, pPath);
ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
CoTaskMemFree(pPath);
}
else
{
ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
}
CoTaskMemFree(pPath);
}
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
@@ -71,8 +77,8 @@ static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
ffStrbufEnsureEndsWithC(&buffer, '/');
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
CoTaskMemFree(pPath);
}
CoTaskMemFree(pPath);
}
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
@@ -130,10 +136,16 @@ static void getDataDirs(FFPlatform* platform)
static void getUserName(FFPlatform* platform)
{
wchar_t buffer[128];
DWORD len = sizeof(buffer) / sizeof(*buffer);
if(GetUserNameW(buffer, &len))
ffStrbufSetWS(&platform->userName, buffer);
const char* userName = getenv("USERNAME");
if (ffStrSet(userName))
ffStrbufSetS(&platform->userName, userName);
else
{
wchar_t buffer[128];
DWORD len = sizeof(buffer) / sizeof(*buffer);
if(GetUserNameW(buffer, &len))
ffStrbufSetWS(&platform->userName, buffer);
}
}
static void getHostName(FFPlatform* platform)
@@ -180,13 +192,13 @@ static void getSystemReleaseAndVersion(FFPlatform* platform)
switch (osVersion.dwPlatformId)
{
case VER_PLATFORM_WIN32s:
ffStrbufAppendS(&platform->systemName, "WIN32s");
ffStrbufSetStatic(&platform->systemName, "WIN32s");
break;
case VER_PLATFORM_WIN32_WINDOWS:
ffStrbufAppendS(&platform->systemName, "WIN32_WINDOWS");
ffStrbufSetStatic(&platform->systemName, "WIN32_WINDOWS");
break;
case VER_PLATFORM_WIN32_NT:
ffStrbufAppendS(&platform->systemName, "WIN32_NT");
ffStrbufSetStatic(&platform->systemName, "WIN32_NT");
break;
}
}
@@ -199,25 +211,45 @@ static void getSystemArchitectureAndPageSize(FFPlatform* platform)
switch(sysInfo.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_AMD64:
ffStrbufAppendS(&platform->systemArchitecture, "x86_64");
ffStrbufSetStatic(&platform->systemArchitecture, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA64:
ffStrbufAppendS(&platform->systemArchitecture, "ia64");
ffStrbufSetStatic(&platform->systemArchitecture, "ia64");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
ffStrbufAppendS(&platform->systemArchitecture, "i686");
switch (sysInfo.wProcessorLevel)
{
case 4:
ffStrbufSetStatic(&platform->systemArchitecture, "i486");
break;
case 5:
ffStrbufSetStatic(&platform->systemArchitecture, "i586");
break;
case 6:
ffStrbufSetStatic(&platform->systemArchitecture, "i686");
break;
default:
ffStrbufSetStatic(&platform->systemArchitecture, "i386");
break;
}
break;
case PROCESSOR_ARCHITECTURE_ARM64:
ffStrbufAppendS(&platform->systemArchitecture, "aarch64");
ffStrbufSetStatic(&platform->systemArchitecture, "aarch64");
break;
case PROCESSOR_ARCHITECTURE_ARM:
ffStrbufAppendS(&platform->systemArchitecture, "arm");
ffStrbufSetStatic(&platform->systemArchitecture, "arm");
break;
case PROCESSOR_ARCHITECTURE_PPC:
ffStrbufAppendS(&platform->systemArchitecture, "ppc");
ffStrbufSetStatic(&platform->systemArchitecture, "ppc");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
ffStrbufAppendS(&platform->systemArchitecture, "mips");
ffStrbufSetStatic(&platform->systemArchitecture, "mips");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
ffStrbufSetStatic(&platform->systemArchitecture, "alpha");
break;
case PROCESSOR_ARCHITECTURE_ALPHA64:
ffStrbufSetStatic(&platform->systemArchitecture, "alpha64");
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
+24 -10
View File
@@ -1,16 +1,12 @@
#include <oaidl.h>
#include <propidl.h>
#include <type_traits>
#include <utility>
#include <string_view>
struct FFWmiVariant: VARIANT
template <typename TVariant>
struct FFBaseVariant: TVariant
{
explicit FFWmiVariant() { VariantInit(this); }
~FFWmiVariant() { VariantClear(this); }
FFWmiVariant(const FFWmiVariant&) = delete;
FFWmiVariant(FFWmiVariant&&); // don't define it to enforce NRVO optimization
bool hasValue() {
return this->vt != VT_EMPTY;
}
@@ -33,11 +29,11 @@ struct FFWmiVariant: VARIANT
return this->cVal;
}
else if constexpr (std::is_same_v<T, int16_t>) {
assert(vt == VT_I2);
assert(this->vt == VT_I2);
return this->iVal;
}
else if constexpr (std::is_same_v<T, int32_t>) {
assert(this->vt == VT_I4 || vt == VT_INT);
assert(this->vt == VT_I4 || this->vt == VT_INT);
return this->intVal;
}
else if constexpr (std::is_same_v<T, int64_t>) {
@@ -55,7 +51,7 @@ struct FFWmiVariant: VARIANT
return this->uiVal;
}
else if constexpr (std::is_same_v<T, uint32_t>) {
assert(this->vt == VT_UI4 || vt == VT_UINT);
assert(this->vt == VT_UI4 || this->vt == VT_UINT);
return this->uintVal;
}
else if constexpr (std::is_same_v<T, uint64_t>) {
@@ -135,3 +131,21 @@ struct FFWmiVariant: VARIANT
}
}
};
struct FFWmiVariant: FFBaseVariant<VARIANT>
{
FFWmiVariant(const FFWmiVariant&) = delete;
FFWmiVariant(FFWmiVariant&&); // don't define it to enforce NRVO optimization
explicit FFWmiVariant() { VariantInit(this); }
~FFWmiVariant() { VariantClear(this); }
};
static_assert(sizeof(FFWmiVariant) == sizeof(VARIANT), "");
struct FFPropVariant: FFBaseVariant<PROPVARIANT>
{
FFPropVariant(const FFPropVariant&) = delete;
FFPropVariant(FFPropVariant&&); // don't define it to enforce NRVO optimization
explicit FFPropVariant() { PropVariantInit(this); }
~FFPropVariant() { PropVariantClear(this); }
};
static_assert(sizeof(FFPropVariant) == sizeof(PROPVARIANT), "");