mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d317997396 | |||
| 91dac1563b | |||
| 73cfae97d2 | |||
| 78a606c1e1 | |||
| f258e484d9 | |||
| ea162fd452 | |||
| b80391b183 | |||
| 4c7a9e4394 | |||
| 4b747f70a4 | |||
| 5fb4b6dc04 | |||
| 5e7cfe2976 | |||
| 77db2d84a3 | |||
| 15bb5bfb24 | |||
| 4e9ee9aa03 | |||
| 6a0c7ca788 | |||
| 90e99bcf69 | |||
| 5b20a86d53 | |||
| 6ad1262f4a | |||
| e0297e1dd1 | |||
| 937611aa29 | |||
| eda38e16db | |||
| 2731756c39 | |||
| 853ca0f608 | |||
| 17f4a6e055 | |||
| 925dc6f681 | |||
| 706527eab4 | |||
| 3a96ade423 | |||
| da9c928286 | |||
| 30d3d00900 | |||
| 99fce80d0d | |||
| a5a28e30a0 | |||
| 7fe39353df | |||
| a3576b3154 | |||
| c5d0d84001 | |||
| 467ed54a3b | |||
| 7ea8882843 | |||
| f4cb3bb33f | |||
| 330eb9fa21 | |||
| 1006f513f5 | |||
| 652c4b2e82 | |||
| 3c618a8cd0 | |||
| b5821de793 | |||
| dec604691c | |||
| 72baa6cca9 | |||
| 34b023a74f | |||
| 8249a8ed6a | |||
| 7e1ac5e24a | |||
| 55c72a8bb3 | |||
| b602bb20c2 | |||
| 46ed24275f | |||
| 71db83f806 | |||
| 0746afa0c2 | |||
| 805c384819 | |||
| 9e4c0e318c | |||
| 51eaac2fd7 | |||
| 92c3df82e6 | |||
| 7f238a701e | |||
| 72236f62ad | |||
| 51b0c43d76 | |||
| 79e2007d30 | |||
| 02eb604ceb | |||
| ce6b2b85f7 | |||
| 48d1980061 | |||
| 40fae5c5f1 | |||
| e296ee1040 | |||
| 199e71553d | |||
| 13fa218e5a | |||
| eed5efabea | |||
| d2315e967e | |||
| cbe3c70480 | |||
| c918226909 | |||
| 18472660ae | |||
| 458c2ccd01 | |||
| 7bb9efcebb | |||
| 8a42dfd68d | |||
| 3edd8a6740 | |||
| cba22b7155 | |||
| 246ad6d288 | |||
| 295e119810 | |||
| cfe22f9524 | |||
| de2c1d7786 | |||
| 7d74339aa0 | |||
| 7589e962c2 | |||
| 9a189694f9 | |||
| 4069fbfe7b | |||
| 7ccd886909 | |||
| 42957356b2 | |||
| 9038cd32b2 | |||
| 128c3bfea6 | |||
| 60ed822f6a | |||
| 527ec1bc61 | |||
| cbf203901b | |||
| cf6f3dbe0c | |||
| ab625497ce | |||
| 83532b68dd | |||
| cd2a1495b8 | |||
| b01d2bdd8c | |||
| 736d5316cc | |||
| efe42a2c7d | |||
| ee07755139 | |||
| 3d924eeadd | |||
| aaa091f23b | |||
| 53cd1e5378 | |||
| 3747683f0d | |||
| 59c1e3d8c5 | |||
| 1206f6d2ba | |||
| 9aad3e339a | |||
| ef9221f305 | |||
| 391a3a0430 | |||
| 6b0314f14b | |||
| 8e316eb080 | |||
| 999f2170fe | |||
| 0282b884cc | |||
| ef7e6d0a6a | |||
| 77253a8d81 | |||
| 2041272f5f | |||
| d2a41bdfe1 | |||
| 025a708ecb | |||
| 4e2c124442 | |||
| 79ba9d7a68 | |||
| ee60ec3530 | |||
| 9d7cbb0fe3 | |||
| 0b98a14977 | |||
| 8f51763374 | |||
| 28ea765f19 | |||
| 5378d05bfb | |||
| bbf04f0d40 | |||
| ec6195133b | |||
| fa8c99601c | |||
| a5d5de90f8 | |||
| 994fd359a5 | |||
| a9a5790cba | |||
| 31b3fe403a | |||
| 14b74fe51d | |||
| 35a5a03cd7 | |||
| f927b8ea87 | |||
| ebefcec3e2 | |||
| c151bf0b37 | |||
| a767104b96 | |||
| 18fced9b2e | |||
| 713ef0ce34 | |||
| 5b2db02bc1 |
@@ -19,7 +19,10 @@ assignees: ''
|
||||
|
||||
# Often helpful information:
|
||||
|
||||
The content of the configuration file you use (if any)
|
||||
Screenshot:
|
||||
<!-- Paste the screenshot here -->
|
||||
|
||||
The content of the configuration file you use (if any):
|
||||
```
|
||||
//paste here
|
||||
```
|
||||
@@ -43,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
|
||||
|
||||
+159
-57
@@ -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,38 +470,46 @@ jobs:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: download artifacts
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: rm old artifacts
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
rm -rf fastfetch-*-old-*
|
||||
|
||||
- name: create release
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-*/fastfetch-*
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
|
||||
- name: download source tarballs
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-amd64.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
ls fastfetch-*/*
|
||||
|
||||
- name: generate release notes
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
|
||||
- name: update release body
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
bodyFile: fastfetch-release-notes.md
|
||||
allowUpdates: true
|
||||
|
||||
@@ -1,3 +1,83 @@
|
||||
# 2.8.5
|
||||
|
||||
Bugfixes:
|
||||
* Fix uninitialized variables
|
||||
|
||||
# 2.8.4
|
||||
|
||||
Bugfixes:
|
||||
* Fix segfault if we fail to find `Vendor ID` in `lscpu` (#718, CPU, Linux)
|
||||
* Fix multi-device bcachefs filesystem compatibility (#731, Disk, Linux)
|
||||
|
||||
Features:
|
||||
* Support portable Windows Terminal settings (#720, Terminal, Windows)
|
||||
* Support `--color-block-width` and `--color-block-range` (#721, Colors)
|
||||
* Support `--diskio-detect-total` to show total bytes read/written (DiskIO)
|
||||
* Support `--netio-detect-total` to show total bytes received/sent (NetIO)
|
||||
* Support `--packages-disabled` to disable specified package manager (#729, Packages)
|
||||
* Support `--display-order` to sort multiple displays in a specific order (Display)
|
||||
* Support `--display-compact-type original-with-refresh-rate` to show refresh rates in compact (oneline) mode (Display)
|
||||
|
||||
# 2.8.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix GPU name detection for AMD graphic cards (GPU, Linux / FreeBSD)
|
||||
|
||||
# 2.8.2
|
||||
|
||||
Changes:
|
||||
* The linux binaries are now built with glibc 2.35, which means they no longer support Debian 11 and Ubuntu 20.04. Users using these distros may download the artifacts `fastfetch-linux-old` from GitHub Actions.
|
||||
|
||||
Features:
|
||||
* Rewrite GPU module, drop libpci dependency (GPU, Linux)
|
||||
* Detect marketing name of Apple Silicon CPUs for asahi linux (CPU, Linux)
|
||||
* Add new module `Camera`, which prints the name and resolution of connected cameras
|
||||
|
||||
Bugfixes:
|
||||
* Fix compatibility with packages installed by flatpak (Terminal, Linux)
|
||||
* Don't show an empty battery if no battery is detected (macOS, Battery)
|
||||
* Don't show `not connected` if no power adapter is found (macOS / Linux, PowerAdapter)
|
||||
* Make format of battery status be consistent with other platforms (Linux, Battery)
|
||||
|
||||
Logo:
|
||||
* Print Asahi logo in asahi linux (Logo, Linux)
|
||||
* Add Asahi2, z/OS, Tatra, PikaOS
|
||||
|
||||
# 2.7.1
|
||||
|
||||
Features:
|
||||
* Config presets in app folder now work with symlinks
|
||||
|
||||
Bugfixes:
|
||||
* Fix a possible segfault when detecting terminal (Terminal, Linux)
|
||||
|
||||
# 2.7.0
|
||||
|
||||
Features:
|
||||
* Add new module `TerminalTheme`, which prints the foreground and background color of the current terminal window. Currently doesn't work on Windows.
|
||||
* Allow command substitution when expanding paths. For example, now it's possible to use `"source": "$(ls ~/path/to/images/*.png | shuf -n 1)"` in JSONC config file to randomly choose an image to display. (#698)
|
||||
* Use native methods instead of pciutils to detect GPUs in FreeBSD. (GPU, FreeBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fix text formatting (Wifi, Linux)
|
||||
* Fix terminal detection in some cases (Terminal)
|
||||
* Remove trailing `\0` in JSON results (FreeBSD)
|
||||
* Fix uninitialized variables (GPU, Linux)
|
||||
* Fix a possible segfault (OpenCL)
|
||||
|
||||
Logo:
|
||||
* Add ASCII logos for fedora immutable variants (#700)
|
||||
|
||||
# 2.6.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix module not working (Bluetooth)
|
||||
|
||||
# 2.6.2
|
||||
|
||||
Bugfixes:
|
||||
* Fix building for GCC in Windows (Windows)
|
||||
|
||||
# 2.6.1
|
||||
|
||||
Features:
|
||||
|
||||
+23
-9
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.6.1
|
||||
VERSION 2.8.5
|
||||
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)
|
||||
@@ -293,6 +291,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/os/os.c
|
||||
src/detection/packages/packages.c
|
||||
src/detection/publicip/publicip.c
|
||||
src/detection/terminaltheme/terminaltheme.c
|
||||
src/detection/terminalfont/terminalfont.c
|
||||
src/detection/terminalshell/terminalshell.c
|
||||
src/detection/version/version.c
|
||||
@@ -309,6 +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
|
||||
@@ -348,6 +348,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/swap/swap.c
|
||||
src/modules/media/media.c
|
||||
src/modules/terminal/terminal.c
|
||||
src/modules/terminaltheme/terminaltheme.c
|
||||
src/modules/terminalfont/terminalfont.c
|
||||
src/modules/terminalsize/terminalsize.c
|
||||
src/modules/theme/theme.c
|
||||
@@ -400,6 +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
|
||||
@@ -432,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)
|
||||
@@ -485,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)
|
||||
@@ -514,7 +518,8 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_bsd.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/lm/lm_linux.c
|
||||
@@ -547,6 +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)
|
||||
@@ -602,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
|
||||
@@ -657,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
|
||||
@@ -790,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"
|
||||
@@ -916,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"
|
||||
@@ -1103,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")
|
||||
@@ -1119,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)
|
||||
|
||||
@@ -27,12 +27,15 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
|
||||
|
||||
### Linux
|
||||
|
||||
* Ubuntu: `ppa:zhangsongcui3371/fastfetch`
|
||||
* 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 +43,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`
|
||||
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
fastfetch (2.8.4) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.4
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 23 Feb 2024 16:14:57 +0800
|
||||
|
||||
fastfetch (2.7.1ubuntu2) jammy; urgency=medium
|
||||
|
||||
* Ignore .git
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 14:23:23 +0800
|
||||
|
||||
fastfetch (2.7.1ubuntu1) jammy; urgency=medium
|
||||
|
||||
* Update build scripts
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 13:53:37 +0800
|
||||
|
||||
fastfetch (2.7.1) jammy; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
12
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
Package: fastfetch
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
|
||||
It is written mainly in C, with performance and customizability in mind.
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: fastfetch
|
||||
Source: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
Files: *
|
||||
Copyright: 2024 fastfetch-cli
|
||||
License: Expat
|
||||
|
||||
Files: src/3rdparty/yyjson/*
|
||||
Copyright: 2020 YaoYuan
|
||||
License: Expat
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
fastfetch_2.8.4_source.buildinfo universe/utils optional
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
debuild -S -i -I
|
||||
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=cmake+ninja
|
||||
|
||||
override_dh_ctest_configure:
|
||||
dh_ctest_configure -- -DSET_TWEAK=OFF -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
version=4
|
||||
opts="filenamemangle=s%.*/@ANY_VERSION@%@PACKAGE@-$1.tar.gz%,searchmode=plain" \
|
||||
https://api.github.com/repos/fastfetch-cli/fastfetch/releases?per_page=100 \
|
||||
https://api.github.com/repos/fastfetch-cli/fastfetch/tarball/@ANY_VERSION@
|
||||
+54
-5
@@ -648,6 +648,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"title",
|
||||
"theme",
|
||||
"uptime",
|
||||
@@ -772,6 +773,10 @@
|
||||
"const": "terminalsize",
|
||||
"description": "Print current terminal size"
|
||||
},
|
||||
{
|
||||
"const": "terminaltheme",
|
||||
"description": "Print current terminal theme (foreground and background colors)"
|
||||
},
|
||||
{
|
||||
"const": "theme",
|
||||
"description": "Print current theme of desktop environment"
|
||||
@@ -1002,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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1073,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"
|
||||
@@ -1083,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"
|
||||
},
|
||||
@@ -1168,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"
|
||||
},
|
||||
@@ -1377,6 +1421,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"detectTotal": {
|
||||
"description": "Detect total bytes instead of current rate",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -1431,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"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
"gpu",
|
||||
@@ -49,6 +50,7 @@
|
||||
"users",
|
||||
"bluetooth",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"weather",
|
||||
"netio",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
"gpu",
|
||||
@@ -55,6 +56,7 @@
|
||||
"users",
|
||||
"bluetooth",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
{
|
||||
"type": "weather",
|
||||
|
||||
+3
-3
@@ -163,9 +163,6 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_THREADS
|
||||
"threads\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
@@ -241,6 +238,9 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_DDCUTIL
|
||||
"libddcutil\n"
|
||||
#endif
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
"videodev2\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
"Directx Headers\n"
|
||||
#endif
|
||||
|
||||
@@ -115,7 +115,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
#if __has_include(<wordexp.h>) // https://github.com/termux/termux-packages/pull/7056
|
||||
|
||||
wordexp_t exp;
|
||||
if(wordexp(in, &exp, WRDE_NOCMD) != 0)
|
||||
if(wordexp(in, &exp, 0) != 0)
|
||||
return false;
|
||||
|
||||
if (exp.we_wordc == 1)
|
||||
|
||||
@@ -15,6 +15,7 @@ static FFModuleBaseInfo* B[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* C[] = {
|
||||
(void*) &instance.config.modules.camera,
|
||||
(void*) &instance.config.modules.chassis,
|
||||
(void*) &instance.config.modules.command,
|
||||
(void*) &instance.config.modules.colors,
|
||||
@@ -124,6 +125,7 @@ static FFModuleBaseInfo* T[] = {
|
||||
(void*) &instance.config.modules.terminal,
|
||||
(void*) &instance.config.modules.terminalFont,
|
||||
(void*) &instance.config.modules.terminalSize,
|
||||
(void*) &instance.config.modules.terminalTheme,
|
||||
(void*) &instance.config.modules.title,
|
||||
(void*) &instance.config.modules.theme,
|
||||
NULL,
|
||||
|
||||
+102
-12
@@ -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": [
|
||||
|
||||
@@ -20,6 +20,14 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
continue;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
|
||||
continue;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), ¤tCapacity) != NULL || currentCapacity <= 0)
|
||||
continue;
|
||||
|
||||
bool boolValue;
|
||||
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
@@ -30,16 +38,6 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
battery->capacity = 0.0/0.0;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
|
||||
continue;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), ¤tCapacity) != NULL || currentCapacity <= 0)
|
||||
continue;
|
||||
|
||||
battery->capacity = currentCapacity * 100.0 / maxCapacity;
|
||||
|
||||
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
|
||||
|
||||
@@ -54,13 +54,13 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Ctritical, ");
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
}
|
||||
|
||||
int acadStatus;
|
||||
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus)
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "AC connected");
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
||||
|
||||
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
@@ -68,6 +70,26 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
|
||||
ffStrbufTrimRightSpace(&result->status);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
// Unknown, Charging, Discharging, Not charging, Full
|
||||
if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
|
||||
ffStrbufSetStatic(&result->status, "AC Connected");
|
||||
else if (ffStrbufEqualS(&result->status, "Unknown"))
|
||||
ffStrbufClear(&result->status);
|
||||
|
||||
ffStrbufAppendS(dir, "/capacity_level");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
|
||||
{
|
||||
if (result->status.length)
|
||||
ffStrbufAppendS(&result->status, ", Critical");
|
||||
else
|
||||
ffStrbufSetStatic(&result->status, "Critical");
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->serial);
|
||||
ffStrbufAppendS(dir, "/serial_number");
|
||||
if (ffReadFileBuffer(dir->chars, &result->serial))
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFCameraResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf id;
|
||||
FFstrbuf colorspace;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} FFCameraResult;
|
||||
|
||||
const char* ffDetectCamera(FFlist* result /* list of FFCameraResult */);
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "camera.h"
|
||||
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
|
||||
#define FF_TERMUX_API_PARAM "CameraInfo"
|
||||
|
||||
static inline void wrapYyjsonFree(yyjson_doc** doc)
|
||||
{
|
||||
assert(doc);
|
||||
if (*doc)
|
||||
yyjson_doc_free(*doc);
|
||||
}
|
||||
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
if(ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
FF_TERMUX_API_PATH,
|
||||
FF_TERMUX_API_PARAM,
|
||||
NULL
|
||||
}))
|
||||
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
|
||||
|
||||
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
|
||||
if (!doc)
|
||||
return "Failed to parse camera info";
|
||||
|
||||
yyjson_val* root = yyjson_doc_get_root(doc);
|
||||
if (!yyjson_is_arr(root))
|
||||
return "Camera info result is not a JSON array";
|
||||
|
||||
yyjson_val* device;
|
||||
size_t idx, max;
|
||||
yyjson_arr_foreach(root, idx, max, device)
|
||||
{
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
{
|
||||
const char* facing = yyjson_get_str(yyjson_obj_get(device, "facing"));
|
||||
if (facing)
|
||||
ffStrbufInitF(&camera->name, "builtin-%s", facing);
|
||||
else
|
||||
ffStrbufInitStatic(&camera->name, "Unknown");
|
||||
}
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id")));
|
||||
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
|
||||
if (yyjson_is_obj(sizes))
|
||||
{
|
||||
camera->width = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "width"));
|
||||
camera->height = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "height"));
|
||||
}
|
||||
else
|
||||
camera->width = camera->height = 0;
|
||||
ffStrbufInit(&camera->colorspace);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "camera.h"
|
||||
|
||||
#import <AVFoundation/AVCaptureDevice.h>
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
|
||||
if (!session)
|
||||
return "Failed to create AVCaptureDeviceDiscoverySession";
|
||||
|
||||
for (AVCaptureDevice* device in session.devices)
|
||||
{
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&camera->name, device.localizedName.UTF8String);
|
||||
ffStrbufInitS(&camera->vendor, device.manufacturer.UTF8String);
|
||||
ffStrbufInitS(&camera->id, device.uniqueID.UTF8String);
|
||||
switch (device.activeColorSpace)
|
||||
{
|
||||
case AVCaptureColorSpace_sRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case AVCaptureColorSpace_P3_D65: ffStrbufInitStatic(&camera->colorspace, "P3-D65"); break;
|
||||
case 2 /*AVCaptureColorSpace_HLG_BT2020*/: ffStrbufInitStatic(&camera->colorspace, "BT2020-HLG"); break;
|
||||
case 3 /*AVCaptureColorSpace_AppleLog*/: ffStrbufInitStatic(&camera->colorspace, "AppleLog"); break;
|
||||
}
|
||||
|
||||
CMVideoDimensions size = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription);
|
||||
camera->width = size.width < 0 ? 0 : (uint32_t) size.width;
|
||||
camera->height = size.height < 0 ? 0 : (uint32_t) size.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "camera.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
#include <linux/videodev2.h>
|
||||
#endif
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
char path[] = "/dev/videoN";
|
||||
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
path[sizeof(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
break;
|
||||
|
||||
struct v4l2_capability cap = {};
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
continue;
|
||||
|
||||
struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
|
||||
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&camera->name, (const char*) cap.card);
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInitS(&camera->id, (const char*) cap.bus_info);
|
||||
switch (fmt.fmt.pix.colorspace)
|
||||
{
|
||||
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
|
||||
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
|
||||
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.808"); break;
|
||||
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
|
||||
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
|
||||
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
|
||||
case V4L2_COLORSPACE_REC709:
|
||||
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case V4L2_COLORSPACE_OPRGB: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
|
||||
case V4L2_COLORSPACE_BT2020: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case V4L2_COLORSPACE_RAW: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
|
||||
case V4L2_COLORSPACE_DCI_P3: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
default: ffStrbufInit(&camera->colorspace); break;
|
||||
}
|
||||
camera->width = fmt.fmt.pix.width;
|
||||
camera->height = fmt.fmt.pix.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(result);
|
||||
return "Fastfetch was compiled without <linux/videodev2.h>";
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
extern "C" {
|
||||
#include "camera.h"
|
||||
#include "common/library.h"
|
||||
}
|
||||
#include "util/windows/com.hpp"
|
||||
#include "util/windows/unicode.hpp"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
|
||||
template <typename Fn>
|
||||
struct on_scope_exit {
|
||||
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
|
||||
~on_scope_exit() { this->_fn(); }
|
||||
|
||||
private:
|
||||
Fn _fn;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(mfplat, NULL, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
|
||||
FF_LIBRARY_LOAD(mf, NULL, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
|
||||
|
||||
const char* error = ffInitCom();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
IMFAttributes* FF_AUTO_RELEASE_COM_OBJECT attrs = nullptr;
|
||||
if (FAILED(ffMFCreateAttributes(&attrs, 1)))
|
||||
return "MFCreateAttributes() failed";
|
||||
|
||||
if (FAILED(attrs->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
)))
|
||||
return "SetGUID(MF_*) failed";
|
||||
|
||||
IMFActivate** devices = NULL;
|
||||
uint32_t count;
|
||||
|
||||
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count)))
|
||||
return "MFEnumDeviceSources() failed";
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
IMFActivate* device = devices[i];
|
||||
|
||||
wchar_t buffer[256];
|
||||
uint32_t length = 0;
|
||||
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitNWS(&camera->name, length, buffer);
|
||||
ffStrbufInit(&camera->colorspace);
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInit(&camera->id);
|
||||
camera->width = 0;
|
||||
camera->height = 0;
|
||||
|
||||
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0)
|
||||
ffStrbufSetNWS(&camera->id, length, buffer);
|
||||
|
||||
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
|
||||
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source))))
|
||||
continue;
|
||||
|
||||
on_scope_exit destroySource([&] { source->Shutdown(); });
|
||||
|
||||
IMFPresentationDescriptor* FF_AUTO_RELEASE_COM_OBJECT pd = nullptr;
|
||||
if (FAILED(source->CreatePresentationDescriptor(&pd)))
|
||||
continue;
|
||||
|
||||
IMFStreamDescriptor* FF_AUTO_RELEASE_COM_OBJECT sd = NULL;
|
||||
BOOL selected;
|
||||
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd)))
|
||||
continue;
|
||||
|
||||
IMFMediaTypeHandler* FF_AUTO_RELEASE_COM_OBJECT handler = NULL;
|
||||
if (FAILED(sd->GetMediaTypeHandler(&handler)))
|
||||
continue;
|
||||
|
||||
DWORD mediaTypeCount;
|
||||
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount)))
|
||||
continue;
|
||||
|
||||
// Assume first type is the maximum resolution
|
||||
IMFMediaType* FF_AUTO_RELEASE_COM_OBJECT type = NULL;
|
||||
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
|
||||
{
|
||||
GUID majorType;
|
||||
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
|
||||
continue;
|
||||
|
||||
MFVideoPrimaries primaries;
|
||||
static_assert(sizeof(primaries) == sizeof(uint32_t), "");
|
||||
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries)))
|
||||
{
|
||||
switch (primaries)
|
||||
{
|
||||
case MFVideoPrimaries_BT709: ffStrbufSetStatic(&camera->colorspace, "sRGB"); break;
|
||||
case MFVideoPrimaries_BT470_2_SysM:
|
||||
case MFVideoPrimaries_BT470_2_SysBG: ffStrbufSetStatic(&camera->colorspace, "NTSC"); break;
|
||||
case MFVideoPrimaries_SMPTE170M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M"); break;
|
||||
case MFVideoPrimaries_SMPTE240M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M"); break;
|
||||
case MFVideoPrimaries_EBU3213: ffStrbufSetStatic(&camera->colorspace, "EBU 3213"); break;
|
||||
case MFVideoPrimaries_SMPTE_C: ffStrbufSetStatic(&camera->colorspace, "SMPTE C"); break;
|
||||
case MFVideoPrimaries_BT2020: ffStrbufSetStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case MFVideoPrimaries_XYZ: ffStrbufSetStatic(&camera->colorspace, "XYZ"); break;
|
||||
case MFVideoPrimaries_DCI_P3: ffStrbufSetStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
case MFVideoPrimaries_ACES: ffStrbufSetStatic(&camera->colorspace, "ACES"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &camera->width, &camera->height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CoTaskMemFree(devices);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -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:")))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -6,6 +6,8 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
|
||||
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
|
||||
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
|
||||
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
|
||||
const char* FF_GPU_VENDOR_NAME_QUALCOMM = "Qualcomm";
|
||||
const char* FF_GPU_VENDOR_NAME_MTK = "MTK";
|
||||
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
|
||||
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
|
||||
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
|
||||
@@ -33,6 +35,10 @@ const char* ffGetGPUVendorString(unsigned vendorId)
|
||||
return FF_GPU_VENDOR_NAME_INTEL;
|
||||
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
|
||||
return FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
else if(arrayContains((const unsigned[]) {0x5143}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
else if(arrayContains((const unsigned[]) {0x14c3}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_MTK;
|
||||
else if(arrayContains((const unsigned[]) {0x15ad}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_VMWARE;
|
||||
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
|
||||
|
||||
@@ -42,3 +42,7 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
|
||||
|
||||
const char* ffGetGPUVendorString(unsigned vendorId);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, uint16_t subVendor, uint16_t subDevice, FFGPUResult* gpu);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "3rdparty/nvml/nvml.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
{
|
||||
// https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h
|
||||
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
ffReadFileBuffer("/usr/share/pciids/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
|
||||
struct pci_conf confs[128];
|
||||
struct pci_match_conf match = {
|
||||
.pc_class = PCIC_DISPLAY,
|
||||
.flags = PCI_GETCONF_MATCH_CLASS,
|
||||
};
|
||||
struct pci_conf_io pcio = {
|
||||
.pat_buf_len = sizeof(match),
|
||||
.num_patterns = 1,
|
||||
.patterns = &match,
|
||||
.match_buf_len = sizeof(confs),
|
||||
.matches = confs,
|
||||
};
|
||||
|
||||
if (ioctl(fd, PCIOCGETCONF, &pcio) < 0)
|
||||
return "ioctl(fd, PCIOCGETCONF, &pc) failed";
|
||||
|
||||
if (pcio.status == PCI_GETCONF_ERROR)
|
||||
return "ioctl(fd, PCIOCGETCONF, &pc) returned error";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
||||
|
||||
for (uint32_t i = 0; i < pcio.num_matches; ++i)
|
||||
{
|
||||
struct pci_conf* pc = &confs[i];
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(pc->pc_vendor));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInitS(&gpu->driver, pc->pd_name);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
if (pciids.length == 0)
|
||||
loadPciIds(&pciids);
|
||||
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, pc->pc_subvendor, pc->pc_subdevice, gpu);
|
||||
}
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = (uint32_t) pc->pc_sel.pc_domain,
|
||||
.bus = pc->pc_sel.pc_bus,
|
||||
.device = pc->pc_sel.pc_dev,
|
||||
.func = pc->pc_sel.pc_func,
|
||||
},
|
||||
}, (FFGpuDriverResult) {
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.type = &gpu->type,
|
||||
.frequency = &gpu->frequency,
|
||||
}, "libnvidia-ml.so");
|
||||
|
||||
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+140
-308
@@ -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,195 +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;
|
||||
|
||||
char class[1024];
|
||||
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
|
||||
ffReadFileBuffer("/usr/local/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
if(
|
||||
//https://pci-ids.ucw.cz/read/PD/03
|
||||
strcasecmp("VGA compatible controller", class) != 0 &&
|
||||
strcasecmp("XGA compatible controller", class) != 0 &&
|
||||
strcasecmp("3D controller", class) != 0 &&
|
||||
strcasecmp("Display controller", class) != 0
|
||||
) return;
|
||||
|
||||
pci->ffpci_fill_info(device, PCI_FILL_IDENT);
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
pciDetectVendorName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
pciDetectDeviceName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
pciDetectDriverName(gpu, pci, device);
|
||||
|
||||
#if FF_USE_PCI_MEMORY
|
||||
// Libpci reports at least 2 false results (#495, #497)
|
||||
pciDetectMemory(gpu, pci, device);
|
||||
pciDetectType(gpu);
|
||||
#else
|
||||
gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
#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
|
||||
@@ -353,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
uint64_t value = 0;
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ static uint64_t time1;
|
||||
|
||||
void ffPrepareNetIO(FFNetIOOptions* options)
|
||||
{
|
||||
if (options->detectTotal) return;
|
||||
|
||||
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
|
||||
ffNetIOGetIoCounters(&ioCounters1, options);
|
||||
time1 = ffTimeGetNow();
|
||||
@@ -17,6 +19,15 @@ void ffPrepareNetIO(FFNetIOOptions* options)
|
||||
const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
const char* error = NULL;
|
||||
|
||||
if (options->detectTotal)
|
||||
{
|
||||
error = ffNetIOGetIoCounters(result, options);
|
||||
if (error)
|
||||
return error;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (time1 == 0)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
|
||||
|
||||
@@ -23,15 +23,15 @@ typedef struct OpenCLData
|
||||
|
||||
static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
{
|
||||
cl_platform_id platformID;
|
||||
cl_uint numPlatforms;
|
||||
cl_platform_id platformID = NULL;
|
||||
cl_uint numPlatforms = 0;
|
||||
data->ffclGetPlatformIDs(1, &platformID, &numPlatforms);
|
||||
|
||||
if(numPlatforms == 0)
|
||||
return "clGetPlatformIDs returned 0 platforms";
|
||||
|
||||
cl_device_id deviceID;
|
||||
cl_uint numDevices;
|
||||
cl_device_id deviceID = NULL;
|
||||
cl_uint numDevices = 0;
|
||||
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices);
|
||||
|
||||
if(numDevices == 0)
|
||||
@@ -40,7 +40,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
if(numDevices == 0)
|
||||
return "clGetDeviceIDs returned 0 devices";
|
||||
|
||||
char version[64];
|
||||
char version[64] = "";
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL);
|
||||
if(!ffStrSet(version))
|
||||
return "clGetDeviceInfo returned NULL or empty string";
|
||||
|
||||
@@ -99,14 +99,16 @@ static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname)
|
||||
return num_elements;
|
||||
}
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
getBrewPackages(result);
|
||||
result->macports = getMacPortsPackages();
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
|
||||
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
|
||||
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT)) getBrewPackages(result);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT)) result->macports = getMacPortsPackages();
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT);
|
||||
result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default");
|
||||
result->nixSystem += getNixPackages(&baseDir, "/run/current-system");
|
||||
ffStrbufSet(&baseDir, &instance.state.platform.homeDir);
|
||||
result->nixUser = getNixPackages(&baseDir, "/.nix-profile");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options)
|
||||
{
|
||||
result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
|
||||
result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages");
|
||||
}
|
||||
|
||||
@@ -253,44 +253,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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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\\"))
|
||||
|
||||
@@ -315,7 +315,7 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
|
||||
detectFromConfigFile("lxterminal/lxterminal.conf", "fontname =", terminalFont);
|
||||
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "tilix"))
|
||||
detectFromGSettings("/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", "default", terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "gnome-terminal-"))
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "gnome-terminal"))
|
||||
detectFromGSettings("/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", "default", terminalFont);
|
||||
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "kgx"))
|
||||
detectKgx(terminalFont);
|
||||
|
||||
@@ -281,7 +281,7 @@ FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version)
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionKgx(FFstrbuf* version)
|
||||
{
|
||||
if(ffProcessAppendStdOut(version, (char* const[]){
|
||||
"gnome-terminal",
|
||||
"kgx",
|
||||
"--version",
|
||||
NULL
|
||||
})) return false;
|
||||
@@ -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[]){
|
||||
@@ -400,6 +414,15 @@ static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version)
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
static bool getTerminalVersionScreen(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if(!getExeVersionRaw(exe, version)) return false;
|
||||
// Screen version 4.09.01 (GNU) 20-Aug-23
|
||||
ffStrbufSubstrAfter(version, strlen("Screen version ") - 1);
|
||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
|
||||
@@ -440,7 +463,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal-"))
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal"))
|
||||
return getTerminalVersionGnome(version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "konsole"))
|
||||
@@ -473,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);
|
||||
|
||||
@@ -511,6 +537,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "contour"))
|
||||
return getTerminalVersionContour(exe, version);
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "screen"))
|
||||
return getTerminalVersionScreen(exe, version);
|
||||
|
||||
const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION");
|
||||
if(termProgramVersion)
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex
|
||||
args, &size,
|
||||
NULL, 0
|
||||
) == 0)
|
||||
ffStrbufSetS(exePath, args);
|
||||
ffStrbufSetNS(exePath, (uint32_t) (size - 1), args);
|
||||
|
||||
size = ARG_MAX;
|
||||
if(sysctl(
|
||||
@@ -123,6 +123,9 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex
|
||||
|
||||
static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid, int32_t* tty)
|
||||
{
|
||||
if (pid <= 0)
|
||||
return "Invalid pid";
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
char statFilePath[64];
|
||||
@@ -144,8 +147,13 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid, int
|
||||
)
|
||||
return "sscanf(stat) failed";
|
||||
|
||||
if (tty && (tty_ >> 8) == 0x88)
|
||||
*tty = tty_ & 0xFF;
|
||||
if (tty)
|
||||
{
|
||||
if ((tty_ >> 8) == 0x88)
|
||||
*tty = tty_ & 0xFF;
|
||||
else
|
||||
*tty = -1;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
@@ -209,11 +217,13 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
|
||||
name[0] = '\0';
|
||||
|
||||
pid_t ppid = 0;
|
||||
int32_t tty = -1;
|
||||
|
||||
while (getProcessNameAndPpid(pid, name, &ppid, &result->tty) == NULL)
|
||||
while (getProcessNameAndPpid(pid, name, &ppid, &tty) == NULL)
|
||||
{
|
||||
//Common programs that are between terminal and own process, but are not the shell
|
||||
if(
|
||||
// tty < 0 || //A shell should connect to a tty
|
||||
ffStrEquals(name, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell
|
||||
ffStrEquals(name, "sudo") ||
|
||||
ffStrEquals(name, "su") ||
|
||||
@@ -237,6 +247,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
|
||||
|
||||
result->pid = (uint32_t) pid;
|
||||
result->ppid = (uint32_t) ppid;
|
||||
result->tty = tty;
|
||||
ffStrbufSetS(&result->processName, name);
|
||||
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName, &result->exePath);
|
||||
break;
|
||||
@@ -255,6 +266,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
|
||||
{
|
||||
//Known shells
|
||||
if (
|
||||
ffStrEquals(name, "sh") ||
|
||||
ffStrEquals(name, "ash") ||
|
||||
ffStrEquals(name, "bash") ||
|
||||
ffStrEquals(name, "zsh") ||
|
||||
@@ -272,6 +284,10 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
|
||||
ffStrEquals(name, "oil.ovm") ||
|
||||
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")
|
||||
)
|
||||
{
|
||||
@@ -297,6 +313,25 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
|
||||
return ppid;
|
||||
}
|
||||
|
||||
static bool getTerminalInfoByPidEnv(FFTerminalResult* result, const char* pidEnv)
|
||||
{
|
||||
const char* envStr = getenv(pidEnv);
|
||||
if (envStr == NULL)
|
||||
return false;
|
||||
|
||||
pid_t pid = (pid_t) strtol(envStr, NULL, 10);
|
||||
result->pid = (uint32_t) pid;
|
||||
char name[256];
|
||||
if (getProcessNameAndPpid(pid, name, (pid_t*) &result->ppid, NULL) == NULL)
|
||||
{
|
||||
ffStrbufSetS(&result->processName, name);
|
||||
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName, &result->exePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void getTerminalFromEnv(FFTerminalResult* result)
|
||||
{
|
||||
if(
|
||||
@@ -319,58 +354,80 @@ static void getTerminalFromEnv(FFTerminalResult* result)
|
||||
const char* term = NULL;
|
||||
|
||||
//SSH
|
||||
if(getenv("SSH_CONNECTION") != NULL)
|
||||
if(
|
||||
getenv("SSH_TTY") != NULL
|
||||
)
|
||||
term = getenv("SSH_TTY");
|
||||
else if(
|
||||
getenv("KITTY_PID") != NULL ||
|
||||
getenv("KITTY_INSTALLATION_DIR") != NULL
|
||||
)
|
||||
{
|
||||
if (getTerminalInfoByPidEnv(result, "KITTY_PID"))
|
||||
return;
|
||||
term = "kitty";
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef __linux__ // WSL
|
||||
//Windows Terminal
|
||||
if(!ffStrSet(term) && (
|
||||
else if(
|
||||
getenv("WT_SESSION") != NULL ||
|
||||
getenv("WT_PROFILE_ID") != NULL
|
||||
)) term = "Windows Terminal";
|
||||
) term = "Windows Terminal";
|
||||
|
||||
//ConEmu
|
||||
if(!ffStrSet(term) && (
|
||||
else if(
|
||||
getenv("ConEmuPID") != NULL
|
||||
)) term = "ConEmu";
|
||||
) term = "ConEmu";
|
||||
#endif
|
||||
|
||||
//Alacritty
|
||||
if(!ffStrSet(term) && (
|
||||
else if(
|
||||
getenv("ALACRITTY_SOCKET") != NULL ||
|
||||
getenv("ALACRITTY_LOG") != NULL ||
|
||||
getenv("ALACRITTY_WINDOW_ID") != NULL
|
||||
)) term = "Alacritty";
|
||||
) term = "Alacritty";
|
||||
|
||||
#ifdef __ANDROID__
|
||||
//Termux
|
||||
if(!ffStrSet(term) && (
|
||||
else if(
|
||||
getenv("TERMUX_VERSION") != NULL ||
|
||||
getenv("TERMUX_MAIN_PACKAGE_FORMAT") != NULL
|
||||
)) term = "com.termux";
|
||||
)
|
||||
{
|
||||
if (getTerminalInfoByPidEnv(result, "TERMUX_APP__PID"))
|
||||
return;
|
||||
term = "com.termux";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
//Konsole
|
||||
if(!ffStrSet(term) && (
|
||||
else if(
|
||||
getenv("KONSOLE_VERSION") != NULL
|
||||
)) term = "konsole";
|
||||
) term = "konsole";
|
||||
|
||||
else if(
|
||||
getenv("GNOME_TERMINAL_SCREEN") != NULL ||
|
||||
getenv("GNOME_TERMINAL_SERVICE") != NULL
|
||||
) term = "gnome-terminal";
|
||||
#endif
|
||||
|
||||
//MacOS, mintty
|
||||
if(!ffStrSet(term))
|
||||
else if(getenv("TERM_PROGRAM") != NULL)
|
||||
term = getenv("TERM_PROGRAM");
|
||||
|
||||
if(!ffStrSet(term))
|
||||
else if(getenv("LC_TERMINAL") != NULL)
|
||||
term = getenv("LC_TERMINAL");
|
||||
|
||||
//Normal Terminal
|
||||
if(!ffStrSet(term))
|
||||
else
|
||||
{
|
||||
term = getenv("TERM");
|
||||
|
||||
//TTY
|
||||
if(!ffStrSet(term) || ffStrEquals(term, "linux"))
|
||||
term = ttyname(STDIN_FILENO);
|
||||
//TTY
|
||||
if(!ffStrSet(term) || ffStrEquals(term, "linux"))
|
||||
term = ttyname(STDIN_FILENO);
|
||||
}
|
||||
|
||||
if(ffStrSet(term))
|
||||
{
|
||||
@@ -429,6 +486,8 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
ffStrbufInitStatic(&result->prettyName, "WezTerm");
|
||||
else if(ffStrbufStartsWithS(&result->processName, "tmux:"))
|
||||
ffStrbufInitStatic(&result->prettyName, "tmux");
|
||||
else if(ffStrbufStartsWithS(&result->processName, "screen-"))
|
||||
ffStrbufInitStatic(&result->prettyName, "screen");
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
@@ -437,7 +496,7 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
else if(ffStrbufStartsWithS(&result->processName, "gnome-terminal-"))
|
||||
else if(ffStrbufStartsWithS(&result->processName, "gnome-terminal"))
|
||||
ffStrbufInitStatic(&result->prettyName, "GNOME Terminal");
|
||||
else if(ffStrbufStartsWithS(&result->processName, "kgx"))
|
||||
ffStrbufInitStatic(&result->prettyName, "GNOME Console");
|
||||
|
||||
@@ -86,7 +86,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
|
||||
|
||||
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
|
||||
{
|
||||
uint32_t ppid;
|
||||
uint32_t ppid = 0;
|
||||
|
||||
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName, &result->exePath, NULL))
|
||||
{
|
||||
@@ -291,17 +291,18 @@ conhost:
|
||||
|
||||
static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
|
||||
{
|
||||
uint32_t ppid;
|
||||
uint32_t ppid = 0;
|
||||
bool hasGui;
|
||||
|
||||
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName, &result->exePath, &hasGui))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result)
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
|
||||
|
||||
if (winsize.ws_row == 0 || winsize.ws_col == 0)
|
||||
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
|
||||
ffGetTerminalResponse("\e[18t", "\e[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
|
||||
|
||||
if (winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0)
|
||||
ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
|
||||
ffGetTerminalResponse("\e[14t", "\e[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
|
||||
|
||||
if (winsize.ws_row == 0 && winsize.ws_col == 0)
|
||||
return false;
|
||||
|
||||
@@ -14,7 +14,7 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result)
|
||||
}
|
||||
else
|
||||
{
|
||||
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &result->rows, &result->columns);
|
||||
ffGetTerminalResponse("\e[18t", "\e[8;%hu;%hut", &result->rows, &result->columns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "terminaltheme.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
static bool detectByEscapeCode(FFTerminalThemeResult* result)
|
||||
{
|
||||
int command = 0;
|
||||
|
||||
if (ffGetTerminalResponse("\e]10;?\e\\", "\e]%d;rgb:%" SCNx16 "/%" SCNx16 "/%" SCNx16 "\e\\", &command, &result->fg.r, &result->fg.g, &result->fg.b) == NULL)
|
||||
{
|
||||
if (command != 10)
|
||||
return false;
|
||||
if (result->fg.r > 0x0100 || result->fg.g > 0x0100 || result->fg.b > 0x0100)
|
||||
result->fg.r /= 0x0100, result->fg.g /= 0x0100, result->fg.b /= 0x0100;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (ffGetTerminalResponse("\e]11;?\e\\", "\e]%d;rgb:%" SCNx16 "/%" SCNx16 "/%" SCNx16 "\e\\", &command, &result->bg.r, &result->bg.g, &result->bg.b) == NULL)
|
||||
{
|
||||
if (command != 11)
|
||||
return false;
|
||||
if (result->bg.r > 0x0100 || result->bg.g > 0x0100 || result->bg.b > 0x0100)
|
||||
result->bg.r /= 0x0100, result->bg.g /= 0x0100, result->bg.b /= 0x0100;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static FFTerminalThemeColor fgbgToColor(int num)
|
||||
{
|
||||
// https://github.com/dalance/termbg/blob/13c478a433fa182e65c401d26a1e7792a7f7f453/src/lib.rs#L251
|
||||
switch (num)
|
||||
{
|
||||
case 0: return (FFTerminalThemeColor){ 0, 0, 0, false}; // black
|
||||
case 1: return (FFTerminalThemeColor){205, 0, 0, false}; // red
|
||||
case 2: return (FFTerminalThemeColor){ 0, 205, 0, false}; // green
|
||||
case 3: return (FFTerminalThemeColor){205, 205, 0, false}; // yellow
|
||||
case 4: return (FFTerminalThemeColor){ 0, 0, 238, false}; // blue
|
||||
case 5: return (FFTerminalThemeColor){205, 0, 205, false}; // magenta
|
||||
case 6: return (FFTerminalThemeColor){ 0, 205, 205, false}; // cyan
|
||||
case 7: return (FFTerminalThemeColor){229, 229, 229, false}; // white
|
||||
|
||||
case 8: return (FFTerminalThemeColor){127, 127, 127, false}; // bright black
|
||||
case 9: return (FFTerminalThemeColor){255, 0, 0, false}; // bright red
|
||||
case 10: return (FFTerminalThemeColor){ 0, 255, 0, false}; // bright green
|
||||
case 11: return (FFTerminalThemeColor){255, 255, 0, false}; // bright yellow
|
||||
case 12: return (FFTerminalThemeColor){ 92, 92, 255, false}; // bright blue
|
||||
case 13: return (FFTerminalThemeColor){255, 0, 255, false}; // bright magenta
|
||||
case 14: return (FFTerminalThemeColor){ 0, 255, 255, false}; // bright cyan
|
||||
case 15: return (FFTerminalThemeColor){255, 255, 255, false}; // bright white
|
||||
|
||||
default: return (FFTerminalThemeColor){ 0, 0, 0, false}; // invalid
|
||||
}
|
||||
}
|
||||
|
||||
static bool detectByEnv(FFTerminalThemeResult* result)
|
||||
{
|
||||
const char* color = getenv("COLORFGBG"); // 7;0
|
||||
|
||||
if (!ffStrSet(color))
|
||||
return false;
|
||||
|
||||
int f, g;
|
||||
if (sscanf(color, "%d;%d", &f, &g) != 2)
|
||||
return false;
|
||||
|
||||
result->fg = fgbgToColor(f);
|
||||
result->bg = fgbgToColor(g);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool detectColor(FFTerminalThemeResult* result)
|
||||
{
|
||||
if (detectByEscapeCode(result))
|
||||
return true;
|
||||
|
||||
return detectByEnv(result);
|
||||
}
|
||||
|
||||
bool ffDetectTerminalTheme(FFTerminalThemeResult* result)
|
||||
{
|
||||
if (!detectColor(result)) return false;
|
||||
result->fg.dark = result->fg.r * 299 + result->fg.g * 587 + result->fg.b * 114 < 128000;
|
||||
result->bg.dark = result->bg.r * 299 + result->bg.g * 587 + result->bg.b * 114 < 128000;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFTerminalThemeColor
|
||||
{
|
||||
uint16_t r;
|
||||
uint16_t g;
|
||||
uint16_t b;
|
||||
bool dark;
|
||||
} FFTerminalThemeColor;
|
||||
|
||||
typedef struct FFTerminalThemeResult
|
||||
{
|
||||
FFTerminalThemeColor fg;
|
||||
FFTerminalThemeColor bg;
|
||||
} FFTerminalThemeResult;
|
||||
|
||||
bool ffDetectTerminalTheme(FFTerminalThemeResult* result);
|
||||
@@ -250,7 +250,11 @@ static const char* detectWifiWithIoctls(FFlist* result)
|
||||
item->conn.txRate = 0.0/0.0;
|
||||
|
||||
ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name);
|
||||
if (!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up\n"))
|
||||
if (!ffAppendFileBuffer(path.chars, &item->inf.status))
|
||||
continue;
|
||||
|
||||
ffStrbufTrimRightSpace(&item->inf.status);
|
||||
if (!ffStrbufEqualS(&item->inf.status, "up"))
|
||||
continue;
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
+19
-5
@@ -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;
|
||||
}
|
||||
@@ -300,7 +315,7 @@ static void listModules(bool pretty)
|
||||
{
|
||||
++count;
|
||||
if (pretty)
|
||||
printf("%d)%s%-13s: %s\n", count, count > 9 ? " " : " ", (*modules)->name, (*modules)->description);
|
||||
printf("%d)%s%-14s: %s\n", count, count > 9 ? " " : " ", (*modules)->name, (*modules)->description);
|
||||
else
|
||||
printf("%s:%s\n", (*modules)->name, (*modules)->description);
|
||||
}
|
||||
@@ -483,10 +498,8 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
if(isJsonConfig ? parseJsoncFile(value) : parseConfigFile(data, value))
|
||||
return;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateA(128);
|
||||
if (ffPathExpandEnv(value, &absolutePath))
|
||||
{
|
||||
bool success = isJsonConfig ? parseJsoncFile(absolutePath.chars) : parseConfigFile(data, absolutePath.chars);
|
||||
bool success = isJsonConfig ? parseJsoncFile(value) : parseConfigFile(data, value);
|
||||
|
||||
if(success)
|
||||
return;
|
||||
@@ -494,6 +507,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
|
||||
//Try to load as a relative path
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateA(128);
|
||||
FF_LIST_FOR_EACH(FFstrbuf, path, instance.state.platform.dataDirs)
|
||||
{
|
||||
//We need to copy it, because if a config file loads a config file, the value of path must be unchanged
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,18 @@
|
||||
,clll:.$2 .,::::::::::::'
|
||||
$1:ooooooo$2 .;::::::::::::::
|
||||
$1looooooo$2 ,:::::::::::::::'
|
||||
$1looooooo$2 .::::::::::::::::
|
||||
$1looooooo$2 ;:::::::::::::::.
|
||||
$1looooooo$2 .::::::::::::::::
|
||||
$1looooool$2;;;;,::::::::::::::::
|
||||
$1looool$2::, .::::::::::::::
|
||||
$1looooc$2:: ;::
|
||||
$1looooc$2::;. .::;
|
||||
$1loooool$2:::::::::::.
|
||||
$1looooooo$2. .::::::'
|
||||
$1looooooo$2 .::::::,;,..
|
||||
$1looooooo$2 :::;' ';:;.
|
||||
$1looooooo$2 ::: :::
|
||||
$1cooooooo$2 .::' '::.
|
||||
$1 .ooooc $2 ::, ,::
|
||||
''''
|
||||
@@ -0,0 +1,17 @@
|
||||
:oooo, .','
|
||||
.';;;.;oooooooolooooo'
|
||||
coooooooooooooooooooooooolc'
|
||||
.':oooooooooooo$2ll$1ooooooooooooool
|
||||
.oooooooooooooooo$2ll$1oooooooooooo$2l$1ool
|
||||
ooooooooooooooooo$2ll$1ooooooooooo$2ll$1oo'
|
||||
oooo$2l$1oooooooooo$2lll$1ooooooooo$2lll$1oo
|
||||
.ooooo$2lll$1ooooo$2lll$1ooooooooo$2lll$1ool
|
||||
.ooooooo$2lll$1oo$2llll$1oooo$2lllll$1ooooo:
|
||||
'oooooooo$2llllllllllll$1oooooooo'
|
||||
.c,.oo$2lllll$1oooooooo.$2
|
||||
'll;
|
||||
'll.
|
||||
lll
|
||||
lll
|
||||
;ll,
|
||||
.l:
|
||||
@@ -0,0 +1,17 @@
|
||||
.;ooooooooooooooooooooooooooo.
|
||||
,dddddddddddddddddddddddddddddd'$3;
|
||||
$1 lddddddddddddddddddddddddddddd'$3;;;
|
||||
$1ddddd$2,XXX.$1ddddd$2,XXX.$1dddd'$2,XXX.$3;;;;;
|
||||
$1ddddd$2XX$1x$2XX$1ddddd$2XX$1x$2XX$1ddd'$2,XX$3x$2XX$3;;;;;
|
||||
$1ddddd$2'XXX'$1ddddd$2'XXX'$1dd'$2XXXXXX'$3;;;;;
|
||||
$1dddddd$2;X;$1ddddddd$2;X:$1d'$2XXX$3;;;;;;;;;;;
|
||||
$1dddddd$2;X;$1ddddddd$2;X:$2XXX$3;;;;;;;;;;;;;
|
||||
$1dddddd$2;X;$1dddddd'$2;XXX,,,,,,XXX.$3;;;;;
|
||||
$1dddddd$2;X;$1dddd'$2XXXX$2XXXXXXXXX$3x$2XX$3;;;;;
|
||||
$1dddddd$2;X;$1dd'$2XXX$3;;;;;;;;;;;$2XXX$3;;;;;;
|
||||
$1dddddd$2;X;$1'$2XXX$3;;;;;;;;;;;;;;;;;;;;;;
|
||||
$1dddddd$2;XXXXX,,,,,,,,,,,,,;XXX:$3;;;;;
|
||||
$1dddddd$2:XXXXXXXXXXXXXXXXXXXX$3x$2XX$3;;;;;
|
||||
$1ddddd'$3;;;;;;;;;;;;;;;;;;;$2'XXX'$3;;;;'
|
||||
$1ddd'$3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
$1o'$3;;;;;;;;;;;;;;;;;;;;;;;;;;;;'
|
||||
@@ -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::,..
|
||||
...,;:::::::;,...
|
||||
@@ -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?!.
|
||||
.^^:..::::::::.....:::::::::::..:.
|
||||
@@ -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
|
||||
+121
-1
@@ -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"},
|
||||
@@ -974,7 +991,7 @@ static const FFlogo C[] = {
|
||||
// ContainerLinux
|
||||
{
|
||||
.names = {"ContainerLinux", "Container Linux", "Container Linux by CoreOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_CONTAINER_LINUX,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_COREOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
@@ -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"},
|
||||
@@ -1468,6 +1501,68 @@ static const FFlogo F[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// FedoraSilverblue
|
||||
{
|
||||
.names = {"Fedora_silverblue", "fedora-silverblue", "fedora-linux-silverblue", "fedora-linux_silverblue"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_SILVERBLUE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_CYAN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// FedoraKinoite
|
||||
{
|
||||
.names = {"Fedora_kinoite", "fedora-kinoite", "fedora-linux-kinoite", "fedora-linux_kinoite"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_KINOITE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// FedoraSericea
|
||||
{
|
||||
.names = {"Fedora_sericea", "fedora-sericea", "fedora-linux-sericea", "fedora-linux_sericea"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_SERICEA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// FedoraOnyx placeholder - Currently does not have a logo
|
||||
//{
|
||||
//.names = {"Fedora_onyx", "fedora-onyx", "fedora-linux-onyx", "fedora-linux_onyx"},
|
||||
//.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
//.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_ONYX,
|
||||
//.colors = {
|
||||
//FF_COLOR_FG_BLUE,
|
||||
//FF_COLOR_FG_WHITE,
|
||||
//},
|
||||
//.colorKeys = FF_COLOR_FG_BLUE,
|
||||
//.colorTitle = FF_COLOR_FG_BLUE,
|
||||
//},
|
||||
// FedoraCoreOS
|
||||
{
|
||||
.names = {"Fedora_coreos", "fedora-coreos", "fedora-linux-coreos", "fedora-linux_coreos"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_COREOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_RED,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// FemboyOS
|
||||
{
|
||||
.names = {"FemboyOS"},
|
||||
@@ -3127,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"},
|
||||
@@ -3820,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"},
|
||||
@@ -4327,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
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -24,6 +24,8 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de
|
||||
|
||||
if (!device->connected)
|
||||
ffStrbufAppendS(&buffer, " [disconnected]");
|
||||
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format
|
||||
|
||||
#define FF_DATETIME_DISPLAY_NAME "Date & Time"
|
||||
#define FF_DATETIME_NUM_FORMAT_ARGS 20
|
||||
#define FF_DATETIME_NUM_FORMAT_ARGS 22
|
||||
|
||||
typedef struct FFDateTimeResult
|
||||
{
|
||||
@@ -17,23 +17,25 @@ typedef struct FFDateTimeResult
|
||||
uint16_t year; //2022
|
||||
uint8_t yearShort; //22
|
||||
uint8_t month; //2
|
||||
FFstrbuf monthPretty; //02
|
||||
FFstrbuf monthName; //February
|
||||
FFstrbuf monthNameShort; //Feb
|
||||
char monthPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //02
|
||||
char monthName[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //February
|
||||
char monthNameShort[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //Feb
|
||||
uint8_t week; //8
|
||||
FFstrbuf weekday; //Monday
|
||||
FFstrbuf weekdayShort; //Mon
|
||||
char weekday[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //Monday
|
||||
char weekdayShort[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //Mon
|
||||
uint16_t dayInYear; //52
|
||||
uint8_t dayInMonth; //21
|
||||
uint8_t dayInWeek; //1
|
||||
uint8_t hour; //15
|
||||
FFstrbuf hourPretty; //15
|
||||
char hourPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //15
|
||||
uint8_t hour12; //3
|
||||
FFstrbuf hour12Pretty; //03
|
||||
char hour12Pretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //03
|
||||
uint8_t minute; //18
|
||||
FFstrbuf minutePretty; //18
|
||||
char minutePretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //18
|
||||
uint8_t second; //37
|
||||
FFstrbuf secondPretty; //37
|
||||
char secondPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //37
|
||||
char offsetFromUtc[FASTFETCH_STRBUF_DEFAULT_ALLOC];
|
||||
char timezoneName[FASTFETCH_STRBUF_DEFAULT_ALLOC];
|
||||
} FFDateTimeResult;
|
||||
|
||||
void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs)
|
||||
@@ -43,80 +45,50 @@ void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs)
|
||||
result.year = (uint16_t) (tm->tm_year + 1900);
|
||||
result.yearShort = (uint8_t) (result.year % 100);
|
||||
result.month = (uint8_t) (tm->tm_mon + 1);
|
||||
|
||||
ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm);
|
||||
|
||||
ffStrbufInitA(&result.monthName, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm);
|
||||
|
||||
ffStrbufInitA(&result.monthNameShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm);
|
||||
|
||||
strftime(result.monthPretty, sizeof(result.monthPretty), "%m", tm);
|
||||
strftime(result.monthName, sizeof(result.monthName), "%B", tm);
|
||||
strftime(result.monthNameShort, sizeof(result.monthNameShort), "%b", tm);
|
||||
result.week = (uint8_t) (tm->tm_yday / 7 + 1);
|
||||
|
||||
ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm);
|
||||
|
||||
ffStrbufInitA(&result.weekdayShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm);
|
||||
|
||||
strftime(result.weekday, sizeof(result.weekday), "%A", tm);
|
||||
strftime(result.weekdayShort, sizeof(result.weekdayShort), "%a", tm);
|
||||
result.dayInYear = (uint8_t) (tm->tm_yday + 1);
|
||||
result.dayInMonth = (uint8_t) tm->tm_mday;
|
||||
result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday;
|
||||
|
||||
result.hour = (uint8_t) tm->tm_hour;
|
||||
|
||||
ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm);
|
||||
|
||||
strftime(result.hourPretty, sizeof(result.hourPretty), "%H", tm);
|
||||
result.hour12 = (uint8_t) (result.hour % 12);
|
||||
|
||||
ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm);
|
||||
|
||||
strftime(result.hour12Pretty, sizeof(result.hour12Pretty), "%I", tm);
|
||||
result.minute = (uint8_t) tm->tm_min;
|
||||
|
||||
ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm);
|
||||
|
||||
strftime(result.minutePretty, sizeof(result.minutePretty), "%M", tm);
|
||||
result.second = (uint8_t) tm->tm_sec;
|
||||
|
||||
ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm);
|
||||
strftime(result.secondPretty, sizeof(result.secondPretty), "%S", tm);
|
||||
strftime(result.offsetFromUtc, sizeof(result.offsetFromUtc), "%z", tm);
|
||||
strftime(result.timezoneName, sizeof(result.timezoneName), "%Z", tm);
|
||||
|
||||
ffPrintFormat(FF_DATETIME_DISPLAY_NAME, 0, moduleArgs, FF_DATETIME_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &result.year}, // 1
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.yearShort}, // 2
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.month}, // 3
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.monthPretty}, // 4
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.monthName}, // 5
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.monthNameShort}, // 6
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.monthPretty}, // 4
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.monthName}, // 5
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.monthNameShort}, // 6
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.week}, // 7
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.weekday}, // 8
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.weekdayShort}, // 9
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.weekday}, // 8
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.weekdayShort}, // 9
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &result.dayInYear}, // 10
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.dayInMonth}, // 11
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.dayInWeek}, // 12
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.hour}, // 13
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.hourPretty}, // 14
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.hourPretty}, // 14
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.hour12}, // 15
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.hour12Pretty}, // 16
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.hour12Pretty}, // 16
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.minute}, // 17
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.minutePretty}, // 18
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.minutePretty}, // 18
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &result.second}, // 19
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.secondPretty} // 20
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.secondPretty}, // 20
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.offsetFromUtc}, // 21
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.timezoneName}, // 22
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&result.hour12Pretty);
|
||||
ffStrbufDestroy(&result.hourPretty);
|
||||
ffStrbufDestroy(&result.minutePretty);
|
||||
ffStrbufDestroy(&result.monthName);
|
||||
ffStrbufDestroy(&result.monthNameShort);
|
||||
ffStrbufDestroy(&result.monthPretty);
|
||||
ffStrbufDestroy(&result.secondPretty);
|
||||
ffStrbufDestroy(&result.weekday);
|
||||
ffStrbufDestroy(&result.weekdayShort);
|
||||
}
|
||||
|
||||
void ffPrintDateTime(FFDateTimeOptions* options)
|
||||
@@ -205,7 +177,9 @@ void ffPrintDateTimeHelpFormat(void)
|
||||
"minute",
|
||||
"minute with leading zero",
|
||||
"second",
|
||||
"second with leading zero"
|
||||
"second with leading zero",
|
||||
"offset from UTC in the ISO 8601 format",
|
||||
"locale-dependent timezone name or abbreviation",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
@@ -202,6 +220,7 @@ void ffInitDiskIOOptions(FFDiskIOOptions* options)
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
|
||||
ffStrbufInit(&options->namePrefix);
|
||||
options->detectTotal = false;
|
||||
}
|
||||
|
||||
void ffDestroyDiskIOOptions(FFDiskIOOptions* options)
|
||||
|
||||
@@ -10,4 +10,5 @@ typedef struct FFDiskIOOptions
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFstrbuf namePrefix;
|
||||
bool detectTotal;
|
||||
} FFDiskIOOptions;
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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"
|
||||
@@ -49,6 +50,7 @@
|
||||
#include "modules/terminal/terminal.h"
|
||||
#include "modules/terminalfont/terminalfont.h"
|
||||
#include "modules/terminalsize/terminalsize.h"
|
||||
#include "modules/terminaltheme/terminaltheme.h"
|
||||
#include "modules/theme/theme.h"
|
||||
#include "modules/title/title.h"
|
||||
#include "modules/uptime/uptime.h"
|
||||
|
||||
+35
-15
@@ -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]",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -238,6 +257,7 @@ void ffInitNetIOOptions(FFNetIOOptions* options)
|
||||
true
|
||||
#endif
|
||||
;
|
||||
options->detectTotal = false;
|
||||
}
|
||||
|
||||
void ffDestroyNetIOOptions(FFNetIOOptions* options)
|
||||
|
||||
@@ -11,4 +11,5 @@ typedef struct FFNetIOOptions
|
||||
|
||||
FFstrbuf namePrefix;
|
||||
bool defaultRouteOnly;
|
||||
bool detectTotal;
|
||||
} FFNetIOOptions;
|
||||
|
||||
@@ -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"
|
||||
@@ -49,6 +50,7 @@
|
||||
#include "modules/terminal/option.h"
|
||||
#include "modules/terminalfont/option.h"
|
||||
#include "modules/terminalsize/option.h"
|
||||
#include "modules/terminaltheme/option.h"
|
||||
#include "modules/theme/option.h"
|
||||
#include "modules/title/option.h"
|
||||
#include "modules/uptime/option.h"
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 FFTerminalThemeOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
} FFTerminalThemeOptions;
|
||||
@@ -0,0 +1,134 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "detection/terminaltheme/terminaltheme.h"
|
||||
#include "modules/terminaltheme/terminaltheme.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define FF_TERMINALTHEME_DISPLAY_NAME "Terminal Theme"
|
||||
#define FF_TERMINALTHEME_NUM_FORMAT_ARGS 4
|
||||
|
||||
void ffPrintTerminalTheme(FFTerminalThemeOptions* options)
|
||||
{
|
||||
FFTerminalThemeResult result = {};
|
||||
|
||||
if(!ffDetectTerminalTheme(&result))
|
||||
{
|
||||
ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, "Failed to detect terminal theme");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
printf("#%02" PRIX16 "%02" PRIX16 "%02" PRIX16 " (FG) - #%02" PRIX16 "%02" PRIX16 "%02" PRIX16 " (BG) [%s]\n",
|
||||
result.fg.r, result.fg.g, result.fg.b,
|
||||
result.bg.r, result.bg.g, result.bg.b,
|
||||
result.bg.dark ? "Dark" : "Light");
|
||||
}
|
||||
else
|
||||
{
|
||||
char fg[32], bg[32];
|
||||
snprintf(fg, sizeof(fg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.fg.r, result.fg.g, result.fg.b);
|
||||
snprintf(bg, sizeof(bg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.bg.r, result.bg.g, result.bg.b);
|
||||
ffPrintFormat(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_TERMINALTHEME_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, fg},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.fg.dark ? "Dark" : "Light"},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, bg},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.bg.dark ? "Dark" : "Light"},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ffParseTerminalThemeCommandOptions(FFTerminalThemeOptions* options, const char* key, const char* value)
|
||||
{
|
||||
const char* subKey = ffOptionTestPrefix(key, FF_TERMINALTHEME_MODULE_NAME);
|
||||
if (!subKey) return false;
|
||||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffParseTerminalThemeJsonObject(FFTerminalThemeOptions* 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_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
|
||||
void ffGenerateTerminalThemeJsonConfig(FFTerminalThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyTerminalThemeOptions))) FFTerminalThemeOptions defaultOptions;
|
||||
ffInitTerminalThemeOptions(&defaultOptions);
|
||||
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
|
||||
}
|
||||
|
||||
void ffGenerateTerminalThemeJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
FFTerminalThemeResult result = {};
|
||||
|
||||
if(!ffDetectTerminalTheme(&result))
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Failed to detect terminal theme");
|
||||
return;
|
||||
}
|
||||
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
|
||||
yyjson_mut_val* fg = yyjson_mut_obj_add_obj(doc, obj, "fg");
|
||||
yyjson_mut_obj_add_uint(doc, fg, "r", result.fg.r);
|
||||
yyjson_mut_obj_add_uint(doc, fg, "g", result.fg.g);
|
||||
yyjson_mut_obj_add_uint(doc, fg, "b", result.fg.b);
|
||||
yyjson_mut_obj_add_bool(doc, fg, "dark", result.fg.dark);
|
||||
|
||||
yyjson_mut_val* bg = yyjson_mut_obj_add_obj(doc, obj, "bg");
|
||||
yyjson_mut_obj_add_uint(doc, bg, "r", result.bg.r);
|
||||
yyjson_mut_obj_add_uint(doc, bg, "g", result.bg.g);
|
||||
yyjson_mut_obj_add_uint(doc, bg, "b", result.bg.b);
|
||||
yyjson_mut_obj_add_bool(doc, bg, "dark", result.bg.dark);
|
||||
}
|
||||
|
||||
void ffPrintTerminalThemeHelpFormat(void)
|
||||
{
|
||||
ffPrintModuleFormatHelp(FF_TERMINALTHEME_MODULE_NAME, "{1} (FG) {3} (BG) [{4}]", FF_TERMINALTHEME_NUM_FORMAT_ARGS, (const char* []) {
|
||||
"Terminal foreground color",
|
||||
"Terminal foreground type (Dark / Light)",
|
||||
"Terminal background color",
|
||||
"Terminal background type (Dark / Light)",
|
||||
});
|
||||
}
|
||||
|
||||
void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options)
|
||||
{
|
||||
ffOptionInitModuleBaseInfo(
|
||||
&options->moduleInfo,
|
||||
FF_TERMINALTHEME_MODULE_NAME,
|
||||
"Print current terminal theme (foreground and background colors)",
|
||||
ffParseTerminalThemeCommandOptions,
|
||||
ffParseTerminalThemeJsonObject,
|
||||
ffPrintTerminalTheme,
|
||||
ffGenerateTerminalThemeJsonResult,
|
||||
ffPrintTerminalThemeHelpFormat,
|
||||
ffGenerateTerminalThemeJsonConfig
|
||||
);
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
}
|
||||
|
||||
void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_TERMINALTHEME_MODULE_NAME "TerminalTheme"
|
||||
|
||||
void ffPrintTerminalTheme(FFTerminalThemeOptions* options);
|
||||
void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options);
|
||||
void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options);
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ typedef struct FFOptionsLibrary
|
||||
FFstrbuf libZ;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
FFstrbuf libPCI;
|
||||
FFstrbuf libWayland;
|
||||
FFstrbuf libXcbRandr;
|
||||
FFstrbuf libXcb;
|
||||
|
||||
@@ -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);
|
||||
@@ -47,9 +48,10 @@ void ffOptionsInitModules(FFOptionsModules* options)
|
||||
ffInitShellOptions(&options->shell);
|
||||
ffInitSoundOptions(&options->sound);
|
||||
ffInitSwapOptions(&options->swap);
|
||||
ffInitTerminalFontOptions(&options->terminalFont);
|
||||
ffInitTerminalOptions(&options->terminal);
|
||||
ffInitTerminalFontOptions(&options->terminalFont);
|
||||
ffInitTerminalSizeOptions(&options->terminalSize);
|
||||
ffInitTerminalThemeOptions(&options->terminalTheme);
|
||||
ffInitThemeOptions(&options->theme);
|
||||
ffInitTitleOptions(&options->title);
|
||||
ffInitUptimeOptions(&options->uptime);
|
||||
@@ -71,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);
|
||||
@@ -109,9 +112,10 @@ void ffOptionsDestroyModules(FFOptionsModules* options)
|
||||
ffDestroyShellOptions(&options->shell);
|
||||
ffDestroySoundOptions(&options->sound);
|
||||
ffDestroySwapOptions(&options->swap);
|
||||
ffDestroyTerminalFontOptions(&options->terminalFont);
|
||||
ffDestroyTerminalOptions(&options->terminal);
|
||||
ffDestroyTerminalFontOptions(&options->terminalFont);
|
||||
ffDestroyTerminalSizeOptions(&options->terminalSize);
|
||||
ffDestroyTerminalThemeOptions(&options->terminalTheme);
|
||||
ffDestroyThemeOptions(&options->theme);
|
||||
ffDestroyTitleOptions(&options->title);
|
||||
ffDestroyUptimeOptions(&options->uptime);
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef struct FFOptionsModules
|
||||
FFBrightnessOptions brightness;
|
||||
FFCPUOptions cpu;
|
||||
FFCPUUsageOptions cpuUsage;
|
||||
FFCameraOptions camera;
|
||||
FFChassisOptions chassis;
|
||||
FFColorsOptions colors;
|
||||
FFCommandOptions command;
|
||||
@@ -48,9 +49,10 @@ typedef struct FFOptionsModules
|
||||
FFShellOptions shell;
|
||||
FFSoundOptions sound;
|
||||
FFSwapOptions swap;
|
||||
FFTerminalFontOptions terminalFont;
|
||||
FFTerminalOptions terminal;
|
||||
FFTerminalFontOptions terminalFont;
|
||||
FFTerminalSizeOptions terminalSize;
|
||||
FFTerminalThemeOptions terminalTheme;
|
||||
FFThemeOptions theme;
|
||||
FFTitleOptions title;
|
||||
FFUptimeOptions uptime;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <pwd.h>
|
||||
#include <limits.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <paths.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <libproc.h>
|
||||
@@ -17,23 +18,31 @@
|
||||
|
||||
static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
FFstrbuf* const exePath = &platform->exePath;
|
||||
ffStrbufEnsureFree(exePath, PATH_MAX);
|
||||
char exePath[PATH_MAX + 1];
|
||||
#ifdef __linux__
|
||||
ssize_t exePathLen = readlink("/proc/self/exe", exePath->chars, exePath->allocated - 1);
|
||||
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
|
||||
exePath[exePathLen] = '\0';
|
||||
#elif defined(__APPLE__)
|
||||
int exePathLen = proc_pidpath((int) getpid(), exePath->chars, exePath->allocated);
|
||||
int exePathLen = proc_pidpath((int) getpid(), exePath, sizeof(exePath));
|
||||
#elif defined(__FreeBSD__)
|
||||
size_t exePathLen = exePath->allocated;
|
||||
size_t exePathLen = sizeof(exePath);
|
||||
if(sysctl(
|
||||
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, (int) getpid()}, 4,
|
||||
exePath->chars, &exePathLen,
|
||||
exePath, &exePathLen,
|
||||
NULL, 0
|
||||
))
|
||||
) < 0)
|
||||
exePathLen = 0;
|
||||
else
|
||||
exePathLen--; // remove terminating NUL
|
||||
#endif
|
||||
if (exePathLen > 0)
|
||||
exePath->length = (uint32_t) exePathLen;
|
||||
{
|
||||
ffStrbufEnsureFree(&platform->exePath, PATH_MAX);
|
||||
if (realpath(platform->exePath.chars, exePath))
|
||||
ffStrbufRecalculateLength(&platform->exePath);
|
||||
else
|
||||
ffStrbufSetNS(&platform->exePath, (uint32_t) exePathLen, exePath);
|
||||
}
|
||||
}
|
||||
|
||||
static void platformPathAddEnv(FFlist* dirs, const char* env)
|
||||
@@ -127,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/");
|
||||
}
|
||||
|
||||
@@ -18,6 +18,14 @@ static void getExePath(FFPlatform* platform)
|
||||
DWORD exePathWLen = GetModuleFileNameW(NULL, exePathW, MAX_PATH);
|
||||
if (exePathWLen == 0 && exePathWLen >= MAX_PATH) return;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hPath = CreateFileW(exePathW, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (hPath != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD len = GetFinalPathNameByHandleW(hPath, exePathW, MAX_PATH, FILE_NAME_OPENED);
|
||||
if (len > 0 && len < MAX_PATH)
|
||||
exePathWLen = len;
|
||||
}
|
||||
|
||||
ffStrbufSetNWS(&platform->exePath, exePathWLen, exePathW);
|
||||
if (ffStrbufStartsWithS(&platform->exePath, "\\\\?\\"))
|
||||
ffStrbufSubstrAfter(&platform->exePath, 3);
|
||||
@@ -32,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)
|
||||
@@ -44,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)
|
||||
@@ -63,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)
|
||||
@@ -122,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)
|
||||
@@ -172,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;
|
||||
}
|
||||
}
|
||||
@@ -191,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:
|
||||
|
||||
@@ -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), "");
|
||||
|
||||
Reference in New Issue
Block a user