Compare commits

...

62 Commits

Author SHA1 Message Date
Carter Li 72baa6cca9 Merge pull request #712 from fastfetch-cli/dev
Release v2.8.0
2024-02-10 12:02:58 +08:00
李通洲 34b023a74f Release: 2.8.0 (ci skip)
For Luna New Year!
2024-02-10 10:32:14 +08:00
李通洲 8249a8ed6a Doc: update changelog 2024-02-09 00:10:29 +08:00
李通洲 7e1ac5e24a Terminal (Windows): code cleanup 2024-02-08 23:15:58 +08:00
李通洲 55c72a8bb3 Camera (Windows): fix Windows Server Core compatibility 2024-02-08 19:14:09 +08:00
Carter Li b602bb20c2 Battery (Linux): print the same format of battery status as other platforms 2024-02-08 14:10:51 +08:00
Carter Li 46ed24275f Battery (FreeBSD): fix typos 2024-02-08 13:59:02 +08:00
Carter Li 71db83f806 PowerAdapter (Linux): don't print not connected either
To align result to macOS
2024-02-08 13:51:30 +08:00
李通洲 0746afa0c2 PowerAdapter (macOS): don't show not connected if no power adapter is detected 2024-02-08 10:53:58 +08:00
李通洲 805c384819 Battery (macOS): don't show an empty battery if no battery is detected 2024-02-08 10:37:06 +08:00
Carter Li 9e4c0e318c Chore: add dpkg related stuff 2024-02-07 14:39:19 +08:00
李通洲 51eaac2fd7 Doc: update changelog 2024-02-06 09:54:33 +08:00
李通洲 92c3df82e6 Logo (Builtin): add PikaOS
Ref: https://github.com/hykilpikonna/hyfetch/pull/231
2024-02-06 09:30:24 +08:00
李通洲 7f238a701e Logo (Builtin): add tatra
Ref: https://github.com/dylanaraps/neofetch/pull/2439
2024-02-06 09:25:44 +08:00
李通洲 72236f62ad Logo (Builtin): add z/OS
Ref: https://github.com/dylanaraps/neofetch/pull/2436
2024-02-06 09:03:01 +08:00
李通洲 51b0c43d76 Platform (Windows): use %USERNAME% if available 2024-02-05 20:01:19 +08:00
李通洲 79e2007d30 Revert "Platform (Linux): use $HOSTNAME if available"
$HOSTNAME doesn't seem to be a standard variable

This reverts commit 02eb604ceb.
2024-02-05 20:01:18 +08:00
李通洲 02eb604ceb Platform (Linux): use $HOSTNAME if available
Ref: #710
2024-02-05 18:23:21 +08:00
李通洲 ce6b2b85f7 Locale (Linux): use environment variable if available
In some machine `setlocale(LC_MESSAGES, NULL)` returns `C` for some reason.
2024-02-05 16:25:12 +08:00
李通洲 48d1980061 CI: build linux old 2024-02-05 14:32:17 +08:00
李通洲 40fae5c5f1 Camera (Android): add empty color space result 2024-02-04 19:07:47 +08:00
李通洲 e296ee1040 CI (Linux): bump version of linux runners
Drop support of Debian 11
2024-02-04 15:48:58 +08:00
李通洲 199e71553d CI: run camera module 2024-02-04 15:14:18 +08:00
李通洲 13fa218e5a Camera: adjust output format 2024-02-04 14:17:18 +08:00
李通洲 eed5efabea Camera (Windows): detect color space 2024-02-04 14:17:18 +08:00
李通洲 d2315e967e Camera (macOS): detect color space 2024-02-04 14:17:18 +08:00
Carter Li cbe3c70480 Camera (Linux): add property colorspace 2024-02-04 14:17:18 +08:00
李通洲 c918226909 Fastfetch: print videodev2 in --list-features 2024-02-04 09:56:22 +08:00
李通洲 18472660ae CI (FreeBSD): remove unused depenencies 2024-02-04 09:27:04 +08:00
李通洲 458c2ccd01 Camera (FreeBSD): enable support
Requires build dependency `v4l_compat`
2024-02-04 09:26:19 +08:00
李通洲 7bb9efcebb Camera (Android): init support 2024-02-02 23:22:40 +08:00
李通洲 8a42dfd68d Camera: tidy; add module to all.jsonc 2024-02-02 22:43:01 +08:00
李通洲 3edd8a6740 Camera (Linux): init support 2024-02-02 22:14:25 +08:00
李通洲 cba22b7155 Camera (Windows): init support 2024-02-02 20:36:22 +08:00
李通洲 246ad6d288 Sound (Windows): tidy 2024-02-02 20:36:22 +08:00
李通洲 295e119810 Camera (macOS): new module 2024-02-02 20:36:22 +08:00
李通洲 cfe22f9524 Terminal (Linux): try fixing #707 (v2) 2024-02-01 17:56:40 +08:00
李通洲 de2c1d7786 CI: unify artifacts name (v2) 2024-02-01 16:00:33 +08:00
李通洲 7d74339aa0 CI: build in parallel 2024-02-01 15:43:56 +08:00
李通洲 7589e962c2 CI: unify artifact names 2024-02-01 15:25:05 +08:00
李通洲 9a189694f9 CI: silence more warnings 2024-02-01 15:24:07 +08:00
李通洲 4069fbfe7b CI: upgrade codeql-action 2024-02-01 15:02:37 +08:00
李通洲 7ccd886909 CI: build aarch64 binaries 2024-02-01 14:29:28 +08:00
李通洲 42957356b2 GPU: remove libpci related stuff 2024-02-01 13:38:15 +08:00
李通洲 9038cd32b2 Terminal (Linux): don't assume blackbox is build for flatpak 2024-02-01 09:14:06 +08:00
李通洲 128c3bfea6 TerminalShell (Linux): try supporting blackbox
Fix #707
2024-02-01 09:02:49 +08:00
李通洲 60ed822f6a GPU (Linux): fix detection in some cases 2024-01-31 18:58:48 +08:00
Carter Li 527ec1bc61 Logo (Builtin): add asahi2; make asahi logo actually work 2024-01-31 16:47:22 +08:00
Carter Li cbf203901b CPU (Linux): code refactor 2024-01-31 14:36:00 +08:00
Carter Li cf6f3dbe0c CI (Windows): fix build 2024-01-31 13:35:57 +08:00
Carter Li ab625497ce CPU (Linux): code refactor 2024-01-31 13:28:18 +08:00
Yussef Dalton 83532b68dd CPU (Linux): use marketing name on Asahi Linux 2024-01-31 11:02:41 +08:00
Carter Li cd2a1495b8 GPU (FreeBSD): use ffGPUParsePciIds 2024-01-31 10:39:09 +08:00
Carter Li b01d2bdd8c GPU (Linux): rewrite; drop libpci dependency 2024-01-31 10:20:49 +08:00
Carter Li 736d5316cc Merge pull request #705 from fastfetch-cli/dev
Release v2.7.1
2024-01-30 19:25:55 +08:00
李通洲 efe42a2c7d GPU: fix a copy-paste error 2024-01-30 18:54:26 +08:00
李通洲 ee07755139 Release: v2.7.1 2024-01-30 18:45:56 +08:00
李通洲 3d924eeadd Merge remote-tracking branch 'upstream/master' into dev 2024-01-30 18:27:24 +08:00
李通洲 aaa091f23b Terminal (Linux): fix segfault 2024-01-30 15:22:26 +08:00
李通洲 53cd1e5378 DateTime: print timezone info; simplify code 2024-01-29 22:01:54 +08:00
李通洲 3747683f0d GPU: add vendor code of QTI & MTK 2024-01-29 21:49:42 +08:00
李通洲 59c1e3d8c5 Platform: detect real path of exe path 2024-01-28 10:45:21 +08:00
55 changed files with 1337 additions and 578 deletions
+151 -57
View File
@@ -10,7 +10,7 @@ jobs:
steps: steps:
- name: checkout repository - name: checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install codespell - name: Install codespell
shell: bash shell: bash
@@ -26,7 +26,6 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-22.04, ubuntu-20.04]
compiler: [ compiler: [
{ cc: gcc, cxx: "g++" }, { cc: gcc, cxx: "g++" },
{ cc: clang, cxx: "clang++" }, { 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 # The feature libraries are all build against glibc, so they can't be used with musl
- compiler: { cc: "musl-gcc", cxx: "musl-g++" } - compiler: { cc: "musl-gcc", cxx: "musl-g++" }
enableFeatures: ON enableFeatures: ON
runs-on: ${{ matrix.os }} runs-on: ubuntu-22.04
steps: steps:
- name: checkout repository - name: checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -46,16 +45,16 @@ jobs:
run: uname -a run: uname -a
- name: install required packages - 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 - name: configure project
env: env:
CC: ${{ matrix.compiler.cc }} CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }} 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 - name: build project
run: cmake --build . run: cmake --build . --verbose -j4
- name: run tests - name: run tests
run: ctest run: ctest
@@ -72,9 +71,68 @@ jobs:
- name: run flashfetch - name: run flashfetch
run: time ./flashfetch run: time ./flashfetch
linux: Linux-old-amd64:
name: Linux name: Linux-old-amd64
runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package 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: permissions:
security-events: write security-events: write
contents: read contents: read
@@ -88,15 +146,15 @@ jobs:
run: uname -a run: uname -a
- name: install required packages - 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 - name: install linuxbrew packages
run: | run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" /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 - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: c 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 . 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 - name: build project
run: cmake --build . --target package --verbose run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis - name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3
- name: list features - name: list features
run: ./fastfetch --list-features run: ./fastfetch --list-features
@@ -134,11 +192,46 @@ jobs:
- name: upload artifacts - name: upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: fastfetch-linux name: fastfetch-linux-amd64
path: ./fastfetch-*.* path: ./fastfetch-*.*
macos: linux-aarch64:
name: MacOS 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 runs-on: macos-latest
permissions: permissions:
security-events: write security-events: write
@@ -156,7 +249,7 @@ jobs:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: c languages: c
@@ -164,10 +257,10 @@ jobs:
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' . run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
- name: build project - name: build project
run: cmake --build . --target package --verbose run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis - name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3
- name: list features - name: list features
run: ./fastfetch --list-features run: ./fastfetch --list-features
@@ -190,11 +283,11 @@ jobs:
- name: upload artifacts - name: upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: fastfetch-macos name: fastfetch-macos-universal
path: ./fastfetch-*.* path: ./fastfetch-*.*
freebsd: freebsd-amd64:
name: FreeBSD name: FreeBSD-amd64
runs-on: macos-12 runs-on: macos-12
permissions: permissions:
security-events: write security-events: write
@@ -211,9 +304,9 @@ jobs:
run: | run: |
uname -a uname -a
sudo pkg update 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 -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package --verbose cmake --build . --target package --verbose -j4
./fastfetch --list-features ./fastfetch --list-features
time ./fastfetch time ./fastfetch
time ./fastfetch --format json time ./fastfetch --format json
@@ -224,11 +317,11 @@ jobs:
- name: upload artifacts - name: upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: fastfetch-freebsd name: fastfetch-freebsd-amd64
path: ./fastfetch-*.* path: ./fastfetch-*.*
win64: windows-amd64:
name: Win64 name: Windows-amd64
runs-on: windows-latest runs-on: windows-latest
permissions: permissions:
security-events: write 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 . run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project - name: build project
run: cmake --build . --verbose run: cmake --build . --verbose -j4
- name: copy necessary dlls - name: copy necessary dlls
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll . run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
@@ -278,19 +371,19 @@ jobs:
run: ctest run: ctest
- name: create zip archive - 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-$(./fastfetch --version-raw)-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive - 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-$(./fastfetch --version-raw)-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts - name: upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: fastfetch-win64 name: fastfetch-windows-amd64
path: ./fastfetch-*-Win64.* path: ./fastfetch-*-windows-amd64.*
win32: windows-i686:
name: Win32 name: Windows-i686
runs-on: windows-latest runs-on: windows-latest
permissions: permissions:
security-events: write security-events: write
@@ -313,7 +406,7 @@ jobs:
run: uname -a run: uname -a
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: c, cpp 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 . run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project - name: build project
run: cmake --build . --verbose run: cmake --build . --verbose -j4
- name: perform CodeQL analysis - name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3
- name: copy necessary dlls - name: copy necessary dlls
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll . run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
@@ -345,27 +438,28 @@ jobs:
run: ctest run: ctest
- name: create zip archive - 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-$(./fastfetch --version-raw)-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive - 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-$(./fastfetch --version-raw)-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts - name: upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: fastfetch-win32 name: fastfetch-windows-i686
path: ./fastfetch-*-Win32.* path: ./fastfetch-*-windows-i686.*
release: release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch' if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- linux - linux-amd64
- macos - linux-aarch64
- freebsd - macos-universal
- win64 - freebsd-amd64
- win32 - windows-amd64
- windows-i686
permissions: permissions:
contents: write contents: write
steps: steps:
@@ -376,29 +470,29 @@ jobs:
repository: ${{ github.repository }} repository: ${{ github.repository }}
- name: download artifacts - 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 uses: actions/download-artifact@v4
- name: create release - 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 uses: ncipollo/release-action@v1
with: with:
tag: ${{ needs.linux.outputs.ffversion }} tag: ${{ needs.linux-amd64.outputs.ffversion }}
commit: ${{ github.sha }} commit: ${{ github.sha }}
artifactErrorsFailBuild: true artifactErrorsFailBuild: true
artifacts: fastfetch-*/fastfetch-* 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 - 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: | 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-*/* ls fastfetch-*/*
- name: generate release notes - 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: | 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 echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
sha256sum fastfetch-*/* >> fastfetch-release-notes.md sha256sum fastfetch-*/* >> fastfetch-release-notes.md
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
@@ -407,10 +501,10 @@ jobs:
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
- name: update release body - 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 uses: ncipollo/release-action@v1
with: with:
tag: ${{ needs.linux.outputs.ffversion }} tag: ${{ needs.linux-amd64.outputs.ffversion }}
commit: ${{ github.sha }} commit: ${{ github.sha }}
bodyFile: fastfetch-release-notes.md bodyFile: fastfetch-release-notes.md
allowUpdates: true allowUpdates: true
+28
View File
@@ -1,3 +1,31 @@
# 2.8.0
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 # 2.7.0
Features: Features:
+9 -7
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch project(fastfetch
VERSION 2.7.0 VERSION 2.8.0
LANGUAGES C LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool" DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -42,7 +42,6 @@ include(CheckIncludeFile)
include(CMakeDependentOption) 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_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_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" 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_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" 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_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_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF) option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
@@ -310,6 +308,7 @@ set(LIBFASTFETCH_SRC
src/modules/board/board.c src/modules/board/board.c
src/modules/brightness/brightness.c src/modules/brightness/brightness.c
src/modules/break/break.c src/modules/break/break.c
src/modules/camera/camera.c
src/modules/chassis/chassis.c src/modules/chassis/chassis.c
src/modules/colors/colors.c src/modules/colors/colors.c
src/modules/cpu/cpu.c src/modules/cpu/cpu.c
@@ -434,6 +433,7 @@ if(LINUX)
src/detection/wm/wm_nosupport.c src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c src/util/platform/FFPlatform_unix.c
) )
elseif(ANDROID) elseif(ANDROID)
@@ -487,6 +487,7 @@ elseif(ANDROID)
src/detection/wm/wm_nosupport.c src/detection/wm/wm_nosupport.c
src/detection/de/de_nosupport.c src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c src/detection/wmtheme/wmtheme_nosupport.c
src/detection/camera/camera_android.c
src/util/platform/FFPlatform_unix.c src/util/platform/FFPlatform_unix.c
) )
elseif(BSD) elseif(BSD)
@@ -549,6 +550,7 @@ elseif(BSD)
src/detection/wm/wm_nosupport.c src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c src/util/platform/FFPlatform_unix.c
) )
elseif(APPLE) elseif(APPLE)
@@ -604,6 +606,7 @@ elseif(APPLE)
src/detection/wm/wm_apple.c src/detection/wm/wm_apple.c
src/detection/de/de_nosupport.c src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_apple.m src/detection/wmtheme/wmtheme_apple.m
src/detection/camera/camera_apple.m
src/util/apple/cf_helpers.c src/util/apple/cf_helpers.c
src/util/apple/osascript.m src/util/apple/osascript.m
src/util/platform/FFPlatform_unix.c src/util/platform/FFPlatform_unix.c
@@ -659,6 +662,7 @@ elseif(WIN32)
src/detection/wm/wm_windows.cpp src/detection/wm/wm_windows.cpp
src/detection/de/de_nosupport.c src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_windows.c src/detection/wmtheme/wmtheme_windows.c
src/detection/camera/camera_windows.cpp
src/util/windows/getline.c src/util/windows/getline.c
src/util/windows/com.cpp src/util/windows/com.cpp
src/util/windows/registry.c src/util/windows/registry.c
@@ -792,10 +796,6 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
endforeach() endforeach()
endfunction() endfunction()
ff_lib_enable(LIBPCI
"libpci"
"Pci"
)
ff_lib_enable(VULKAN ff_lib_enable(VULKAN
"vulkan" "vulkan"
"Vulkan" "Vulkan"
@@ -918,9 +918,11 @@ if(LINUX)
) )
elseif(APPLE) elseif(APPLE)
target_link_libraries(libfastfetch target_link_libraries(libfastfetch
PRIVATE "-framework AVFoundation"
PRIVATE "-framework Cocoa" PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreFoundation" PRIVATE "-framework CoreFoundation"
PRIVATE "-framework CoreAudio" PRIVATE "-framework CoreAudio"
PRIVATE "-framework CoreMedia"
PRIVATE "-framework CoreVideo" PRIVATE "-framework CoreVideo"
PRIVATE "-framework CoreWLAN" PRIVATE "-framework CoreWLAN"
PRIVATE "-framework IOBluetooth" PRIVATE "-framework IOBluetooth"
+18
View File
@@ -0,0 +1,18 @@
fastfetch (2.7.1ubuntu2) jammy; urgency=medium
* Ignore .git
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 14:23:23 +0800
fastfetch (2.7.1ubuntu1) jammy; urgency=medium
* Update build scripts
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 13:53:37 +0800
fastfetch (2.7.1) jammy; urgency=medium
* Initial release.
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
+1
View File
@@ -0,0 +1 @@
12
+13
View File
@@ -0,0 +1,13 @@
Source: fastfetch
Section: universe/utils
Priority: optional
Maintainer: Carter Li <zhangsongcui@live.cn>
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Standards-Version: 4.0.0
Homepage: https://github.com/fastfetch-cli/fastfetch
Package: fastfetch
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
It is written mainly in C, with performance and customizability in mind.
+11
View File
@@ -0,0 +1,11 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: fastfetch
Source: https://github.com/fastfetch-cli/fastfetch
Files: *
Copyright: 2024 fastfetch-cli
License: Expat
Files: src/3rdparty/yyjson/*
Copyright: 2020 YaoYuan
License: Expat
+1
View File
@@ -0,0 +1 @@
fastfetch_2.7.1ubuntu2_source.buildinfo universe/utils optional
Vendored Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
debuild -S -i -I
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
Vendored Executable
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/make -f
%:
dh $@ --buildsystem=cmake+ninja
override_dh_ctest_configure:
dh_ctest_configure -- -DSET_TWEAK=OFF -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
+4
View File
@@ -0,0 +1,4 @@
version=4
opts="filenamemangle=s%.*/@ANY_VERSION@%@PACKAGE@-$1.tar.gz%,searchmode=plain" \
https://api.github.com/repos/fastfetch-cli/fastfetch/releases?per_page=100 \
https://api.github.com/repos/fastfetch-cli/fastfetch/tarball/@ANY_VERSION@
+1
View File
@@ -50,6 +50,7 @@
"users", "users",
"bluetooth", "bluetooth",
"sound", "sound",
"camera",
"gamepad", "gamepad",
"weather", "weather",
"netio", "netio",
+1
View File
@@ -56,6 +56,7 @@
"users", "users",
"bluetooth", "bluetooth",
"sound", "sound",
"camera",
"gamepad", "gamepad",
{ {
"type": "weather", "type": "weather",
+3 -3
View File
@@ -163,9 +163,6 @@ void ffListFeatures(void)
#ifdef FF_HAVE_THREADS #ifdef FF_HAVE_THREADS
"threads\n" "threads\n"
#endif #endif
#ifdef FF_HAVE_LIBPCI
"libpci\n"
#endif
#ifdef FF_HAVE_VULKAN #ifdef FF_HAVE_VULKAN
"vulkan\n" "vulkan\n"
#endif #endif
@@ -241,6 +238,9 @@ void ffListFeatures(void)
#ifdef FF_HAVE_DDCUTIL #ifdef FF_HAVE_DDCUTIL
"libddcutil\n" "libddcutil\n"
#endif #endif
#if __has_include(<linux/videodev2.h>)
"videodev2\n"
#endif
#ifdef FF_HAVE_DIRECTX_HEADERS #ifdef FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n" "Directx Headers\n"
#endif #endif
+1
View File
@@ -15,6 +15,7 @@ static FFModuleBaseInfo* B[] = {
}; };
static FFModuleBaseInfo* C[] = { static FFModuleBaseInfo* C[] = {
(void*) &instance.config.modules.camera,
(void*) &instance.config.modules.chassis, (void*) &instance.config.modules.chassis,
(void*) &instance.config.modules.command, (void*) &instance.config.modules.command,
(void*) &instance.config.modules.colors, (void*) &instance.config.modules.colors,
+8 -10
View File
@@ -20,6 +20,14 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
continue; continue;
int currentCapacity, maxCapacity;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
continue;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0)
continue;
bool boolValue; bool boolValue;
FFBatteryResult* battery = ffListAdd(results); FFBatteryResult* battery = ffListAdd(results);
@@ -30,16 +38,6 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
ffStrbufInit(&battery->technology); ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status); ffStrbufInit(&battery->status);
ffStrbufInit(&battery->manufactureDate); ffStrbufInit(&battery->manufactureDate);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
continue;
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0)
continue;
battery->capacity = currentCapacity * 100.0 / maxCapacity; battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName); ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
+2 -2
View File
@@ -54,13 +54,13 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING) else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
ffStrbufAppendS(&battery->status, "Charging, "); ffStrbufAppendS(&battery->status, "Charging, ");
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL) if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
ffStrbufAppendS(&battery->status, "Ctritical, "); ffStrbufAppendS(&battery->status, "Critical, ");
} }
int acadStatus; int acadStatus;
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus) if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus)
{ {
ffStrbufAppendS(&battery->status, "AC connected"); ffStrbufAppendS(&battery->status, "AC Connected");
} }
else else
{ {
+22
View File
@@ -5,6 +5,8 @@
#include <dirent.h> #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) static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
{ {
uint32_t dirLength = dir->length; uint32_t dirLength = dir->length;
@@ -68,6 +70,26 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
ffStrbufTrimRightSpace(&result->status); ffStrbufTrimRightSpace(&result->status);
ffStrbufSubstrBefore(dir, dirLength); 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); ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/serial_number"); ffStrbufAppendS(dir, "/serial_number");
if (ffReadFileBuffer(dir->chars, &result->serial)) if (ffReadFileBuffer(dir->chars, &result->serial))
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "fastfetch.h"
typedef struct FFCameraResult
{
FFstrbuf name;
FFstrbuf vendor;
FFstrbuf id;
FFstrbuf colorspace;
uint32_t width;
uint32_t height;
} FFCameraResult;
const char* ffDetectCamera(FFlist* result /* list of FFCameraResult */);
+61
View File
@@ -0,0 +1,61 @@
#include "camera.h"
#include "common/processing.h"
#include "common/properties.h"
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
#define FF_TERMUX_API_PARAM "CameraInfo"
static inline void wrapYyjsonFree(yyjson_doc** doc)
{
assert(doc);
if (*doc)
yyjson_doc_free(*doc);
}
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FF_TERMUX_API_PATH,
FF_TERMUX_API_PARAM,
NULL
}))
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
if (!doc)
return "Failed to parse camera info";
yyjson_val* root = yyjson_doc_get_root(doc);
if (!yyjson_is_arr(root))
return "Camera info result is not a JSON array";
yyjson_val* device;
size_t idx, max;
yyjson_arr_foreach(root, idx, max, device)
{
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
{
const char* facing = yyjson_get_str(yyjson_obj_get(device, "facing"));
if (facing)
ffStrbufInitF(&camera->name, "builtin-%s", facing);
else
ffStrbufInitStatic(&camera->name, "Unknown");
}
ffStrbufInit(&camera->vendor);
ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id")));
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
if (yyjson_is_obj(sizes))
{
camera->width = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "width"));
camera->height = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "height"));
}
else
camera->width = camera->height = 0;
ffStrbufInit(&camera->colorspace);
}
return NULL;
}
+31
View File
@@ -0,0 +1,31 @@
#include "camera.h"
#import <AVFoundation/AVCaptureDevice.h>
const char* ffDetectCamera(FFlist* result)
{
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
if (!session)
return "Failed to create AVCaptureDeviceDiscoverySession";
for (AVCaptureDevice* device in session.devices)
{
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitS(&camera->name, device.localizedName.UTF8String);
ffStrbufInitS(&camera->vendor, device.manufacturer.UTF8String);
ffStrbufInitS(&camera->id, device.uniqueID.UTF8String);
switch (device.activeColorSpace)
{
case AVCaptureColorSpace_sRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
case AVCaptureColorSpace_P3_D65: ffStrbufInitStatic(&camera->colorspace, "P3-D65"); break;
case 2 /*AVCaptureColorSpace_HLG_BT2020*/: ffStrbufInitStatic(&camera->colorspace, "BT2020-HLG"); break;
case 3 /*AVCaptureColorSpace_AppleLog*/: ffStrbufInitStatic(&camera->colorspace, "AppleLog"); break;
}
CMVideoDimensions size = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription);
camera->width = size.width < 0 ? 0 : (uint32_t) size.width;
camera->height = size.height < 0 ? 0 : (uint32_t) size.height;
}
return NULL;
}
+61
View File
@@ -0,0 +1,61 @@
#include "camera.h"
#include "common/io/io.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#if __has_include(<linux/videodev2.h>)
#include <linux/videodev2.h>
#endif
const char* ffDetectCamera(FFlist* result)
{
#if __has_include(<linux/videodev2.h>)
char path[] = "/dev/videoN";
for (uint32_t i = 0; i <= 9; ++i)
{
path[sizeof(path) - 2] = (char) (i + '0');
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
if (fd < 0)
break;
struct v4l2_capability cap = {};
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
continue;
struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
continue;
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitS(&camera->name, (const char*) cap.card);
ffStrbufInit(&camera->vendor);
ffStrbufInitS(&camera->id, (const char*) cap.bus_info);
switch (fmt.fmt.pix.colorspace)
{
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.808"); break;
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
case V4L2_COLORSPACE_REC709:
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
case V4L2_COLORSPACE_OPRGB: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
case V4L2_COLORSPACE_BT2020: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
case V4L2_COLORSPACE_RAW: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
case V4L2_COLORSPACE_DCI_P3: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
default: ffStrbufInit(&camera->colorspace); break;
}
camera->width = fmt.fmt.pix.width;
camera->height = fmt.fmt.pix.height;
}
return NULL;
#else
FF_UNUSED(result);
return "Fastfetch was compiled without <linux/videodev2.h>";
#endif
}
+129
View File
@@ -0,0 +1,129 @@
extern "C" {
#include "camera.h"
#include "common/library.h"
}
#include "util/windows/com.hpp"
#include "util/windows/unicode.hpp"
#include <initguid.h>
#include <mfapi.h>
#include <mfidl.h>
template <typename Fn>
struct on_scope_exit {
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
~on_scope_exit() { this->_fn(); }
private:
Fn _fn;
};
extern "C"
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
{
FF_LIBRARY_LOAD(mfplat, NULL, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
FF_LIBRARY_LOAD(mf, NULL, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
const char* error = ffInitCom();
if (error)
return error;
IMFAttributes* FF_AUTO_RELEASE_COM_OBJECT attrs = nullptr;
if (FAILED(ffMFCreateAttributes(&attrs, 1)))
return "MFCreateAttributes() failed";
if (FAILED(attrs->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
)))
return "SetGUID(MF_*) failed";
IMFActivate** devices = NULL;
uint32_t count;
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count)))
return "MFEnumDeviceSources() failed";
for (uint32_t i = 0; i < count; i++)
{
IMFActivate* device = devices[i];
wchar_t buffer[256];
uint32_t length = 0;
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0)
continue;
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
ffStrbufInitNWS(&camera->name, length, buffer);
ffStrbufInit(&camera->colorspace);
ffStrbufInit(&camera->vendor);
ffStrbufInit(&camera->id);
camera->width = 0;
camera->height = 0;
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0)
ffStrbufSetNWS(&camera->id, length, buffer);
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source))))
continue;
on_scope_exit destroySource([&] { source->Shutdown(); });
IMFPresentationDescriptor* FF_AUTO_RELEASE_COM_OBJECT pd = nullptr;
if (FAILED(source->CreatePresentationDescriptor(&pd)))
continue;
IMFStreamDescriptor* FF_AUTO_RELEASE_COM_OBJECT sd = NULL;
BOOL selected;
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd)))
continue;
IMFMediaTypeHandler* FF_AUTO_RELEASE_COM_OBJECT handler = NULL;
if (FAILED(sd->GetMediaTypeHandler(&handler)))
continue;
DWORD mediaTypeCount;
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount)))
continue;
// Assume first type is the maximum resolution
IMFMediaType* FF_AUTO_RELEASE_COM_OBJECT type = NULL;
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
{
GUID majorType;
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
continue;
MFVideoPrimaries primaries;
static_assert(sizeof(primaries) == sizeof(uint32_t), "");
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries)))
{
switch (primaries)
{
case MFVideoPrimaries_BT709: ffStrbufSetStatic(&camera->colorspace, "sRGB"); break;
case MFVideoPrimaries_BT470_2_SysM:
case MFVideoPrimaries_BT470_2_SysBG: ffStrbufSetStatic(&camera->colorspace, "NTSC"); break;
case MFVideoPrimaries_SMPTE170M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M"); break;
case MFVideoPrimaries_SMPTE240M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M"); break;
case MFVideoPrimaries_EBU3213: ffStrbufSetStatic(&camera->colorspace, "EBU 3213"); break;
case MFVideoPrimaries_SMPTE_C: ffStrbufSetStatic(&camera->colorspace, "SMPTE C"); break;
case MFVideoPrimaries_BT2020: ffStrbufSetStatic(&camera->colorspace, "BT.2020"); break;
case MFVideoPrimaries_XYZ: ffStrbufSetStatic(&camera->colorspace, "XYZ"); break;
case MFVideoPrimaries_DCI_P3: ffStrbufSetStatic(&camera->colorspace, "DCI-P3"); break;
case MFVideoPrimaries_ACES: ffStrbufSetStatic(&camera->colorspace, "ACES"); break;
default: break;
}
}
MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &camera->width, &camera->height);
break;
}
}
CoTaskMemFree(devices);
return nullptr;
}
+71
View File
@@ -4,6 +4,7 @@
#include "common/properties.h" #include "common/properties.h"
#include "detection/temps/temps_linux.h" #include "detection/temps/temps_linux.h"
#include "util/mallocHelper.h" #include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <stdlib.h> #include <stdlib.h>
@@ -34,6 +35,10 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
FF_AUTO_FREE char* line = NULL; FF_AUTO_FREE char* line = NULL;
size_t len = 0; size_t len = 0;
#ifdef __aarch64__
FF_STRBUF_AUTO_DESTROY implementer = ffStrbufCreate();
#endif
while(getline(&line, &len, cpuinfo) != -1) while(getline(&line, &len, cpuinfo) != -1)
{ {
//Stop after the first CPU //Stop after the first CPU
@@ -47,12 +52,36 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
ffParsePropLine(line, "cpu MHz :", cpuMHz) || ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
ffParsePropLine(line, "isa :", cpuIsa) || ffParsePropLine(line, "isa :", cpuIsa) ||
ffParsePropLine(line, "uarch :", cpuUarch) || 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, "Hardware :", &cpu->name)) || //For Android devices
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER (cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS (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; 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) const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{ {
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET; cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
@@ -167,6 +234,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectAndroid(cpu); detectAndroid(cpu);
#endif #endif
#if defined(__linux__) && defined(__aarch64__)
detectAsahi(cpu);
#endif
if (cpu->name.length == 0) if (cpu->name.length == 0)
{ {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
+78
View File
@@ -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_AMD = "AMD";
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel"; const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA"; 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_VMWARE = "VMware";
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel"; const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft"; const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
@@ -33,6 +35,10 @@ const char* ffGetGPUVendorString(unsigned vendorId)
return FF_GPU_VENDOR_NAME_INTEL; return FF_GPU_VENDOR_NAME_INTEL;
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3)) else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
return FF_GPU_VENDOR_NAME_NVIDIA; 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)) else if(arrayContains((const unsigned[]) {0x15ad}, vendorId, 1))
return FF_GPU_VENDOR_NAME_VMWARE; return FF_GPU_VENDOR_NAME_VMWARE;
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1)) else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
@@ -112,3 +118,75 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
return "GPU detection failed"; return "GPU detection failed";
} }
#ifndef _WIN32
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
{
if (content->length)
{
char buffer[32];
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++;
}
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device);
start = memmem(start, (size_t) (end - start), buffer, len);
if (start)
{
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
end = content->chars + content->length;
char* openingBracket = memchr(start, '[', (uint32_t) (end - start));
if (openingBracket)
{
openingBracket++;
char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket));
if (closingBracket)
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
}
if (!gpu->name.length)
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
}
}
}
if (!gpu->name.length)
{
const char* subclassStr;
switch (subclass)
{
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
default: subclassStr = ""; break;
}
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
}
}
#endif
+4
View File
@@ -42,3 +42,7 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGetGPUVendorString(unsigned vendorId); const char* ffGetGPUVendorString(unsigned vendorId);
#ifndef _WIN32
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
#endif
+2 -67
View File
@@ -61,75 +61,10 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) pc->pc_vendor << 16) + pc->pc_device; gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func;
gpu->frequency = FF_GPU_FREQUENCY_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (pciids.length) ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
{
char buffer[32];
uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", pc->pc_vendor);
char* start = (char*) memmem(pciids.chars, pciids.length, buffer, len);
char* end = pciids.chars + pciids.length;
if (start)
{
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
end = pciids.chars + pciids.length;
if (!gpu->vendor.length)
ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start);
start = end; // point to '\n' of vendor
end = start + 1; // point to start of devices
// find the start of next vendor
while (end[0] == '\t' || end[0] == '#')
{
end = strchr(end, '\n');
if (!end)
{
end = pciids.chars + pciids.length;
break;
}
else
end++;
}
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", pc->pc_device);
start = memmem(start, (size_t) (end - start), buffer, len);
if (start)
{
start += len;
end = memchr(start, '\n', (uint32_t) (end - start));
if (!end)
end = pciids.chars + pciids.length;
char* openingBracket = memchr(start, '[', (uint32_t) (end - start));
if (openingBracket)
{
openingBracket++;
char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket));
if (closingBracket)
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
}
if (!gpu->name.length)
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
}
}
}
if (!gpu->name.length)
{
const char* subclass;
switch (pc->pc_subclass)
{
case PCIS_DISPLAY_VGA: subclass = " (VGA compatible)"; break;
case PCIS_DISPLAY_XGA: subclass = " (XGA compatible)"; break;
case PCIS_DISPLAY_3D: subclass = " (3D)"; break;
default: subclass = ""; break;
}
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", pc->pc_device, subclass);
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
+91 -273
View File
@@ -1,154 +1,24 @@
#include "detection/gpu/gpu.h" #include "detection/gpu/gpu.h"
#include "detection/vulkan/vulkan.h" #include "detection/vulkan/vulkan.h"
#include "detection/temps/temps_linux.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
#include "detection/gpu/gpu_driver_specific.h" #include "detection/gpu/gpu_driver_specific.h"
#endif #endif
#ifdef FF_HAVE_LIBPCI #include <inttypes.h>
#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>
// Fix building on Ubuntu 20.04 FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
#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)
{ {
const FFlist* tempsResult = ffDetectTemps(); const FFlist* tempsResult = ffDetectTemps();
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult) 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 //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; gpu->temperature = tempValue->value;
return; return;
@@ -156,100 +26,117 @@ 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; ffStrbufAppendS(pciDir, "/driver");
char pathBuf[PATH_MAX];
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
if(resultLength > 0)
{
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
if (slash)
{
slash++;
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
}
uint32_t flags = (uint32_t) pci->ffpci_fill_info(device, PCI_FILL_IO_FLAGS | PCI_FILL_SIZES); ffStrbufAppendS(pciDir, "/module/version");
if (!(flags & PCI_FILL_IO_FLAGS) || !(flags & PCI_FILL_SIZES)) if (ffReadFileBuffer(pciDir->chars, buffer))
{ {
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET; ffStrbufTrimRightSpace(buffer);
ffStrbufAppendC(&gpu->driver, ' ');
ffStrbufAppend(&gpu->driver, buffer);
}
}
}
static bool loadPciIds(FFstrbuf* pciids)
{
ffReadFileBuffer("/usr/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
ffReadFileBuffer("/usr/share/misc/pci.ids", pciids); // debian?
if (pciids->length > 0) return true;
ffReadFileBuffer("/usr/local/share/hwdata/pci.ids", pciids);
if (pciids->length > 0) return true;
return false; return false;
} }
gpu->dedicated.total = gpu->shared.total = 0; static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
for (uint32_t i = 0; i < sizeof(device->size) / sizeof(device->size[0]); i++)
{ {
if (!(device->flags[i] & PCI_IORESOURCE_MEM)) continue; //https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
const char* pciDirPath = "/sys/bus/pci/devices/";
// Assume dedicated memories are prefetchable DIR* dirp = opendir(pciDirPath);
// At least it's true for my laptop if(dirp == NULL)
if (device->flags[i] & PCI_IORESOURCE_PREFETCH) return "Failed to open `/sys/bus/pci/devices/`";
gpu->dedicated.total += device->size[i];
else
gpu->shared.total += device->size[i];
}
if (gpu->dedicated.total == 0 && gpu->shared.total == 0) FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
ffStrbufAppendS(&pciDir, pciDirPath);
const uint32_t pciBaseDirLength = pciDir.length;
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
loadPciIds(&pciids);
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{ {
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET; if(entry->d_name[0] == '.')
return false; continue;
}
return true; ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
} ffStrbufAppendS(&pciDir, entry->d_name);
FF_MAYBE_UNUSED static void pciDetectType(FFGPUResult* gpu) const uint32_t pciDevDirLength = pciDir.length;
{
//There is no straightforward way to detect the type of a GPU.
//The approach taken here is to look at the memory sizes of the device.
//Since integrated GPUs usually use the system ram, they don't have expansive ROMs
//and their memory sizes are usually smaller than 1GB.
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
{
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 // 1GB
? FF_GPU_TYPE_DISCRETE
: FF_GPU_TYPE_INTEGRATED;
}
else
gpu->type = FF_GPU_TYPE_UNKNOWN;
}
static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* results, PCIData* pci, struct pci_dev* device) ffStrbufAppendS(&pciDir, "/modalias");
{ if (!ffReadFileBuffer(pciDir.chars, &buffer))
pci->ffpci_fill_info(device, PCI_FILL_CLASS); continue;
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
if (device->device_class >> 8 != PCI_BASE_CLASS_DISPLAY) uint32_t vendorId, deviceId;
return; uint8_t classId, subclassId;
if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%*8ssd%*8sbc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &classId, &subclassId) != 4)
continue;
pci->ffpci_fill_info(device, PCI_FILL_IDENT); if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
continue;
FFGPUResult* gpu = ffListAdd(results); uint32_t pciDomain, pciBus, pciDevice, pciFunc;
if (sscanf(entry->d_name, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
ffStrbufInit(&gpu->platformApi); continue;
ffStrbufInit(&gpu->vendor);
pciDetectVendorName(gpu, pci, device);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->name);
pciDetectDeviceName(gpu, pci, device);
ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->driver);
pciDetectDriverName(gpu, pci, device); ffStrbufInit(&gpu->platformApi);
#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->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; gpu->frequency = FF_GPU_FREQUENCY_UNSET;
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
pciDetectDriver(gpu, &pciDir, &buffer);
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{ {
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, .type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = { .pciBusId = {
.domain = (uint32_t) device->domain, .domain = pciDomain,
.bus = device->bus, .bus = pciBus,
.device = device->dev, .device = pciDevice,
.func = device->func, .func = pciFunc,
}, },
}, (FFGpuDriverResult) { }, (FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL, .temp = options->temp ? &gpu->temperature : NULL,
@@ -266,77 +153,13 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
#ifdef __linux__ #ifdef __linux__
if(options->temp && gpu->temperature != gpu->temperature) if(options->temp && gpu->temperature != gpu->temperature)
pciDetectTemp(gpu, device); pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
#endif #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
}
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
PCIData pci;
FF_LIBRARY_LOAD(libpci, &instance.config.library.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_alloc);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_init);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_scan_bus);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_cleanup);
FF_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);
#if PCI_LIB_VERSION >= 0x030800
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_string_property);
#endif
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
ffpci_scan_bus(pci.access);
struct pci_dev* device = pci.access->devices;
while(device != NULL)
{
pciHandleDevice(options, gpus, &pci, device);
device = device->next;
}
ffpci_cleanup(pci.access);
return NULL; return NULL;
} }
#endif
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{ {
#ifdef FF_HAVE_DIRECTX_HEADERS #ifdef FF_HAVE_DIRECTX_HEADERS
@@ -345,10 +168,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
return NULL; return NULL;
#endif #endif
#ifdef FF_HAVE_LIBPCI
return pciDetectGPUs(options, gpus); return pciDetectGPUs(options, gpus);
#else
FF_UNUSED(options, gpus);
return "fastfetch is built without libpci support";
#endif
} }
+8
View File
@@ -4,6 +4,14 @@
void ffDetectLocale(FFstrbuf* result) 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 #ifdef LC_MESSAGES
ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL)); ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL));
@@ -13,5 +13,3 @@ typedef struct FFPowerAdapterResult
} FFPowerAdapterResult; } FFPowerAdapterResult;
const char* ffDetectPowerAdapter(FFlist* results); const char* ffDetectPowerAdapter(FFlist* results);
#define FF_POWERADAPTER_NOT_CONNECTED -1
@@ -6,6 +6,9 @@
#include <IOKit/ps/IOPSKeys.h> #include <IOKit/ps/IOPSKeys.h>
const char* ffDetectPowerAdapter(FFlist* results) const char* ffDetectPowerAdapter(FFlist* results)
{
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
if (details && CFDictionaryContainsKey(details, CFSTR(kIOPSPowerAdapterWattsKey)))
{ {
FFPowerAdapterResult* adapter = ffListAdd(results); FFPowerAdapterResult* adapter = ffListAdd(results);
@@ -14,11 +17,8 @@ const char* ffDetectPowerAdapter(FFlist* results)
ffStrbufInit(&adapter->manufacturer); ffStrbufInit(&adapter->manufacturer);
ffStrbufInit(&adapter->modelName); ffStrbufInit(&adapter->modelName);
ffStrbufInit(&adapter->serial); ffStrbufInit(&adapter->serial);
adapter->watts = FF_POWERADAPTER_NOT_CONNECTED; adapter->watts = 0;
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
if (details)
{
ffCfDictGetString(details, CFSTR(kIOPSNameKey), &adapter->name); ffCfDictGetString(details, CFSTR(kIOPSNameKey), &adapter->name);
if (ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName) != NULL) if (ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName) != NULL)
{ {
+11 -18
View File
@@ -28,6 +28,14 @@ static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFl
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device")) if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
return; 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 //input_power_limit must exist and be not empty
ffStrbufAppendS(dir, "/input_power_limit"); ffStrbufAppendS(dir, "/input_power_limit");
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer); bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
@@ -35,24 +43,14 @@ static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFl
if (!available) if (!available)
return; return;
FFPowerAdapterResult* result = ffListAdd(results); FFPowerAdapterResult* result = ffListAdd(results);
ffStrbufInit(&result->name); ffStrbufInit(&result->name);
ffStrbufInit(&result->description); 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); result->watts = (int) (ffStrbufToDouble(&tmpBuffer) / 1e6 + 0.5);
//At this point, we have a battery. Try to get as much values as possible.
ffStrbufInit(&result->manufacturer); ffStrbufInit(&result->manufacturer);
ffStrbufInit(&result->modelName);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/manufacturer"); ffStrbufAppendS(dir, "/manufacturer");
if (ffReadFileBuffer(dir->chars, &result->manufacturer)) if (ffReadFileBuffer(dir->chars, &result->manufacturer))
ffStrbufTrimRightSpace(&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."); ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
ffStrbufSubstrBefore(dir, dirLength); ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->modelName);
ffStrbufAppendS(dir, "/model_name"); ffStrbufAppendS(dir, "/model_name");
if (ffReadFileBuffer(dir->chars, &result->modelName)) if (ffReadFileBuffer(dir->chars, &result->modelName))
ffStrbufTrimRightSpace(&result->modelName); ffStrbufTrimRightSpace(&result->modelName);
ffStrbufSubstrBefore(dir, dirLength); ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/serial_number"); ffStrbufAppendS(dir, "/serial_number");
if (ffReadFileBuffer(dir->chars, &result->serial)) if (ffReadFileBuffer(dir->chars, &result->serial))
ffStrbufTrimRightSpace(&result->serial); ffStrbufTrimRightSpace(&result->serial);
@@ -95,8 +91,5 @@ const char* ffDetectPowerAdapter(FFlist* results)
ffStrbufSubstrBefore(&baseDir, baseDirLength); ffStrbufSubstrBefore(&baseDir, baseDirLength);
} }
if(results->length == 0)
return "\"/sys/class/power_supply/\" doesn't contain any power adapter folder";
return NULL; return NULL;
} }
+2 -2
View File
@@ -17,8 +17,8 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
IMMDeviceEnumerator* FF_AUTO_RELEASE_COM_OBJECT pEnum = NULL; IMMDeviceEnumerator* FF_AUTO_RELEASE_COM_OBJECT pEnum = NULL;
if (FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&pEnum))) if (FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&pEnum)))
return "CoCreateInstance(__uuidof(MMDeviceEnumerator)) failed"; return "CoCreateInstance(CLSID_MMDeviceEnumerator) failed";
LPWSTR mainDeviceId = NULL; LPWSTR mainDeviceId = NULL;
@@ -356,6 +356,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionXterm(FFstrbuf* exe, FFstrbuf* ver
return version->length > 0; 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) FF_MAYBE_UNUSED static bool getTerminalVersionUrxvt(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{ {
if(ffProcessAppendStdErr(version, (char* const[]){ if(ffProcessAppendStdErr(version, (char* const[]){
@@ -482,6 +496,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
if(ffStrbufIgnCaseEqualS(processName, "xterm")) if(ffStrbufIgnCaseEqualS(processName, "xterm"))
return getTerminalVersionXterm(exe, version); return getTerminalVersionXterm(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "blackbox"))
return getTerminalVersionBlackbox(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "st")) if(ffStrbufIgnCaseEqualS(processName, "st"))
return getTerminalVersionSt(exe, version); return getTerminalVersionSt(exe, version);
@@ -285,6 +285,9 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrEquals(name, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case ffStrEquals(name, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
ffStrEquals(name, "login") || ffStrEquals(name, "login") ||
ffStrEquals(name, "sshd") || ffStrEquals(name, "sshd") ||
#ifdef __linux__
ffStrStartsWith(name, "flatpak-") || // #707
#endif
ffStrEndsWith(name, ".sh") ffStrEndsWith(name, ".sh")
) )
{ {
@@ -312,7 +315,11 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
static bool getTerminalInfoByPidEnv(FFTerminalResult* result, const char* pidEnv) static bool getTerminalInfoByPidEnv(FFTerminalResult* result, const char* pidEnv)
{ {
pid_t pid = (pid_t) strtol(getenv(pidEnv), NULL, 10); const char* envStr = getenv(pidEnv);
if (envStr == NULL)
return false;
pid_t pid = (pid_t) strtol(envStr, NULL, 10);
result->pid = (uint32_t) pid; result->pid = (uint32_t) pid;
char name[256]; char name[256];
if (getProcessNameAndPpid(pid, name, (pid_t*) &result->ppid, NULL) == NULL) if (getProcessNameAndPpid(pid, name, (pid_t*) &result->ppid, NULL) == NULL)
@@ -298,10 +298,11 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
{ {
if(!hasGui) if(!hasGui)
{ {
//We are nested shell //We are in nested shell
ffStrbufClear(&result->processName); ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName); ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe); ffStrbufClear(&result->exe);
ffStrbufClear(&result->exePath);
result->exeName = ""; result->exeName = "";
pid = ppid; pid = ppid;
continue; continue;
@@ -320,6 +321,7 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
ffStrbufClear(&result->processName); ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName); ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe); ffStrbufClear(&result->exe);
ffStrbufClear(&result->exePath);
result->exeName = ""; result->exeName = "";
return 0; return 0;
} }
+18
View File
@@ -0,0 +1,18 @@
$1_wwM $2_ww
$1MMM$2MMMM
$1MM
$3_ww##############yy_
$4wMMMMM$3###########$4MMMMm
$4,MMMMMMMMM$3######$4MMMMMMMM0_
$4wMMMMMMMMMMMMM$5MM$60MMMMMMMMMMm
$4,MMMMMMMMMMMMMMM$5MMMM$60MMMMMMMMM0,
$4wMMMMMMMMMMMMMMMM$5MMMMM0$6MMMMMMMMMMb
$4_MMMMMMMMMMMMMMMMMM$5MMMMMMM0$6MMMMMMMMM0,
$4_MMMMMMMMMMMMMMMMMMM$5MMMM$7M$5MMMW$6MMMMMMMMMM_
$4_MMMMMMMMMMMMMMMMMMMM$5MMMM$7M0$5MMMW$6MMMMMMMMMM_
$4~MMMMMMMMMMMMMMMMM$5MMMM$7M$5MMMW$6MMMMM00~
$4~MMMMMMMMMMMMM$5MMMWMMM$60MM$5MMM$6~
$4~MMMMMMMMMM$5MMMMM$60MMM~~
$4~MMMMMM$5MMM$60MM~
$4~MM$5M$6@~
$4M
+28
View File
@@ -0,0 +1,28 @@
'',,, ,,,d,
',, ,,'
', ,.
., '
. .
' .
.. oddddkdlc:;,.. ..
. ............lllc, .
. ....................: .
. . ....................
'. ..........'o........d0XX0.
....lllllllcOOOcllllll............cxlxc...;okkkx.
..................................';lc'...lo.
.'''''''''''''.....................,;,.......
',,,,,,,,,,,,,,,,''...............dkkkd......
',,,,,,,,,,,,,,,,,,,'............;okkkd;....
.,,,,,,,,,,,,,,,,,,,,,............;cll;.....
,,,,,,,,,,,,,,,,,,,,'....................:d,
,,,,,,,,,,,,,,,,,,,....................oxxx:
.,,,,,,,,,,,,,,,,,'..................oxxxxx. .
.,,,,,,,,,,,,,,'.......... ,oxxxxxxx .
.;,,,,,,,,,,,,'.. 'cxxxxxxxxx,
:dl:,'',,'.... .;lxxxxxxxxxd;
,codol:;'. ...,;cldxxxxxxxxxoc.
.:cxxxxxdlccccc:ccldxxxxxxxxxxxxxx::.
.'::dxxxxxxxxxxxxxxxxxxxxxxxd::'.
..,::cdxxxxxxxxxxxxxdc::,..
...,;:::::::;,...
+15
View File
@@ -0,0 +1,15 @@
. .:. . .:.
.^^.!.:::. .^!?J?^
.:^.^!!!~:~^. .7??77!~~^.
.~^.!??77?!.^~: ..:^^7JJJ7~~^.
.^~.^7???7~.~~. .7??????????!
.:^:^^~^^:!^ ^: .......^!:...
.!7~.::.!.::. ~BG~ :^ ^~:
:!!~ ~. ?BBBB! ^?J!. .!~.
:!. .JBY. .Y#BBBY?~!???J7. :^^.
.. :5#B#P~P#BBP?7?55J?J7:
^P#BBBBBBBB5?7J5555J!.....
!BBBBBBGBBGJ77::Y555J?77777^
?BBBBG5JJ5PJ?!: .?Y??????77?~.
.YBGPYJ??????Y?^^^^~7?????????7?!.
.^^:..::::::::.....:::::::::::..:.
+7
View File
@@ -0,0 +1,7 @@
// OOOOOOO SSSSSSS
// OO OO SS
zzzzzz // OO OO SS
zz // OO OO SSSS
zz // OO OO SS
zz // OO OO SS
zzzzzz // OOOOOOO SSSSSSS
+58
View File
@@ -468,6 +468,23 @@ static const FFlogo A[] = {
.colorKeys = FF_COLOR_FG_YELLOW, .colorKeys = FF_COLOR_FG_YELLOW,
.colorTitle = FF_COLOR_FG_GREEN, .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 // Aster
{ {
.names = {"aster"}, .names = {"aster"},
@@ -1445,6 +1462,22 @@ static const FFlogo F[] = {
.colorKeys = FF_COLOR_FG_BLUE, .colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = 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 // FedoraSmall
{ {
.names = {"Fedora_small", "fedora-linux-small"}, .names = {"Fedora_small", "fedora-linux-small"},
@@ -3189,6 +3222,14 @@ static const FFlogo P[] = {
FF_COLOR_FG_WHITE, FF_COLOR_FG_WHITE,
}, },
}, },
// PikaOS
{
.names = {"PikaOS"},
.lines = FASTFETCH_DATATEXT_LOGO_PIKAOS,
.colors = {
FF_COLOR_FG_YELLOW,
},
},
// Pisi // Pisi
{ {
.names = {"Pisi"}, .names = {"Pisi"},
@@ -3882,6 +3923,15 @@ static const FFlogo T[] = {
FF_COLOR_FG_WHITE, FF_COLOR_FG_WHITE,
}, },
}, },
// Tatra
{
.names = {"Tatra"},
.lines = FASTFETCH_DATATEXT_LOGO_TATRA,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_GREEN,
},
},
// TeArch // TeArch
{ {
.names = {"TeArch"}, .names = {"TeArch"},
@@ -4389,6 +4439,14 @@ static const FFlogo Z[] = {
.colorKeys = FF_COLOR_FG_BLUE, .colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = 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 // LAST
{}, {},
}; };
+170
View File
@@ -0,0 +1,170 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/libc/libc.h"
#include "detection/camera/camera.h"
#include "modules/camera/camera.h"
#include "util/stringUtils.h"
#define FF_CAMERA_NUM_FORMAT_ARGS 5
static void printDevice(FFCameraOptions* options, const FFCameraResult* device, uint8_t index)
{
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&device->name, stdout);
if (device->colorspace.length > 0)
{
fputs(" - ", stdout);
ffStrbufWriteTo(&device->colorspace, stdout);
}
if (device->width > 0 && device->height > 0)
printf(" (%ux%u px)\n", (unsigned) device->width, (unsigned) device->height);
else
putchar('\n');
}
else
{
ffPrintFormat(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_CAMERA_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->colorspace},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->id},
{FF_FORMAT_ARG_TYPE_UINT, &device->width},
{FF_FORMAT_ARG_TYPE_UINT, &device->height},
});
}
}
void ffPrintCamera(FFCameraOptions* options)
{
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFCameraResult));
const char* error = ffDetectCamera(&result);
if (error)
{
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, "%s", error);
return;
}
if (result.length == 0)
{
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, "No camera found");
return;
}
for(uint32_t i = 0; i < result.length; i++)
{
uint8_t index = (uint8_t) (result.length == 1 ? 0 : i + 1);
printDevice(options, FF_LIST_GET(FFCameraResult, result, i), index);
}
FF_LIST_FOR_EACH(FFCameraResult, dev, result)
{
ffStrbufDestroy(&dev->name);
ffStrbufDestroy(&dev->id);
ffStrbufDestroy(&dev->colorspace);
}
}
bool ffParseCameraCommandOptions(FFCameraOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_CAMERA_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
return false;
}
void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module)
{
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
void ffGenerateCameraJsonConfig(FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
__attribute__((__cleanup__(ffDestroyCameraOptions))) FFCameraOptions defaultOptions;
ffInitCameraOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
}
void ffGenerateCameraJsonResult(FF_MAYBE_UNUSED FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFCameraResult));
const char* error = ffDetectCamera(&result);
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFCameraResult, dev, result)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &dev->vendor);
yyjson_mut_obj_add_strbuf(doc, obj, "colorSpace", &dev->colorspace);
yyjson_mut_obj_add_strbuf(doc, obj, "id", &dev->id);
yyjson_mut_obj_add_uint(doc, obj, "width", dev->width);
yyjson_mut_obj_add_uint(doc, obj, "height", dev->height);
}
FF_LIST_FOR_EACH(FFCameraResult, dev, result)
{
ffStrbufDestroy(&dev->name);
ffStrbufDestroy(&dev->id);
ffStrbufDestroy(&dev->colorspace);
}
}
void ffPrintCameraHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_CAMERA_MODULE_NAME, "{1} ({4}px x {5}px)", FF_CAMERA_NUM_FORMAT_ARGS, (const char* []) {
"Device name",
"Vendor",
"Color space",
"Identifier",
"Width (in px)",
"Height (in px)",
});
}
void ffInitCameraOptions(FFCameraOptions* options)
{
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_CAMERA_MODULE_NAME,
"Print available cameras",
ffParseCameraCommandOptions,
ffParseCameraJsonObject,
ffPrintCamera,
ffGenerateCameraJsonResult,
ffPrintCameraHelpFormat,
ffGenerateCameraJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs);
}
void ffDestroyCameraOptions(FFCameraOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fastfetch.h"
#define FF_CAMERA_MODULE_NAME "Camera"
void ffPrintCamera(FFCameraOptions* options);
void ffInitCameraOptions(FFCameraOptions* options);
void ffDestroyCameraOptions(FFCameraOptions* options);
+11
View File
@@ -0,0 +1,11 @@
#pragma once
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
typedef struct FFCameraOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
} FFCameraOptions;
+37 -63
View File
@@ -9,7 +9,7 @@
#pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format #pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format
#define FF_DATETIME_DISPLAY_NAME "Date & Time" #define FF_DATETIME_DISPLAY_NAME "Date & Time"
#define FF_DATETIME_NUM_FORMAT_ARGS 20 #define FF_DATETIME_NUM_FORMAT_ARGS 22
typedef struct FFDateTimeResult typedef struct FFDateTimeResult
{ {
@@ -17,23 +17,25 @@ typedef struct FFDateTimeResult
uint16_t year; //2022 uint16_t year; //2022
uint8_t yearShort; //22 uint8_t yearShort; //22
uint8_t month; //2 uint8_t month; //2
FFstrbuf monthPretty; //02 char monthPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //02
FFstrbuf monthName; //February char monthName[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //February
FFstrbuf monthNameShort; //Feb char monthNameShort[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //Feb
uint8_t week; //8 uint8_t week; //8
FFstrbuf weekday; //Monday char weekday[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //Monday
FFstrbuf weekdayShort; //Mon char weekdayShort[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //Mon
uint16_t dayInYear; //52 uint16_t dayInYear; //52
uint8_t dayInMonth; //21 uint8_t dayInMonth; //21
uint8_t dayInWeek; //1 uint8_t dayInWeek; //1
uint8_t hour; //15 uint8_t hour; //15
FFstrbuf hourPretty; //15 char hourPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //15
uint8_t hour12; //3 uint8_t hour12; //3
FFstrbuf hour12Pretty; //03 char hour12Pretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //03
uint8_t minute; //18 uint8_t minute; //18
FFstrbuf minutePretty; //18 char minutePretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //18
uint8_t second; //37 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; } FFDateTimeResult;
void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) 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.year = (uint16_t) (tm->tm_year + 1900);
result.yearShort = (uint8_t) (result.year % 100); result.yearShort = (uint8_t) (result.year % 100);
result.month = (uint8_t) (tm->tm_mon + 1); result.month = (uint8_t) (tm->tm_mon + 1);
strftime(result.monthPretty, sizeof(result.monthPretty), "%m", tm);
ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); strftime(result.monthName, sizeof(result.monthName), "%B", tm);
result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm); strftime(result.monthNameShort, sizeof(result.monthNameShort), "%b", 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);
result.week = (uint8_t) (tm->tm_yday / 7 + 1); result.week = (uint8_t) (tm->tm_yday / 7 + 1);
strftime(result.weekday, sizeof(result.weekday), "%A", tm);
ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC); strftime(result.weekdayShort, sizeof(result.weekdayShort), "%a", tm);
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);
result.dayInYear = (uint8_t) (tm->tm_yday + 1); result.dayInYear = (uint8_t) (tm->tm_yday + 1);
result.dayInMonth = (uint8_t) tm->tm_mday; result.dayInMonth = (uint8_t) tm->tm_mday;
result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday; result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday;
result.hour = (uint8_t) tm->tm_hour; result.hour = (uint8_t) tm->tm_hour;
strftime(result.hourPretty, sizeof(result.hourPretty), "%H", tm);
ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm);
result.hour12 = (uint8_t) (result.hour % 12); result.hour12 = (uint8_t) (result.hour % 12);
strftime(result.hour12Pretty, sizeof(result.hour12Pretty), "%I", tm);
ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm);
result.minute = (uint8_t) tm->tm_min; result.minute = (uint8_t) tm->tm_min;
strftime(result.minutePretty, sizeof(result.minutePretty), "%M", tm);
ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm);
result.second = (uint8_t) tm->tm_sec; result.second = (uint8_t) tm->tm_sec;
strftime(result.secondPretty, sizeof(result.secondPretty), "%S", tm);
ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); strftime(result.offsetFromUtc, sizeof(result.offsetFromUtc), "%z", tm);
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm); strftime(result.timezoneName, sizeof(result.timezoneName), "%Z", tm);
ffPrintFormat(FF_DATETIME_DISPLAY_NAME, 0, moduleArgs, FF_DATETIME_NUM_FORMAT_ARGS, (FFformatarg[]) { 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_UINT16, &result.year}, // 1
{FF_FORMAT_ARG_TYPE_UINT8, &result.yearShort}, // 2 {FF_FORMAT_ARG_TYPE_UINT8, &result.yearShort}, // 2
{FF_FORMAT_ARG_TYPE_UINT8, &result.month}, // 3 {FF_FORMAT_ARG_TYPE_UINT8, &result.month}, // 3
{FF_FORMAT_ARG_TYPE_STRBUF, &result.monthPretty}, // 4 {FF_FORMAT_ARG_TYPE_STRING, result.monthPretty}, // 4
{FF_FORMAT_ARG_TYPE_STRBUF, &result.monthName}, // 5 {FF_FORMAT_ARG_TYPE_STRING, result.monthName}, // 5
{FF_FORMAT_ARG_TYPE_STRBUF, &result.monthNameShort}, // 6 {FF_FORMAT_ARG_TYPE_STRING, result.monthNameShort}, // 6
{FF_FORMAT_ARG_TYPE_UINT8, &result.week}, // 7 {FF_FORMAT_ARG_TYPE_UINT8, &result.week}, // 7
{FF_FORMAT_ARG_TYPE_STRBUF, &result.weekday}, // 8 {FF_FORMAT_ARG_TYPE_STRING, result.weekday}, // 8
{FF_FORMAT_ARG_TYPE_STRBUF, &result.weekdayShort}, // 9 {FF_FORMAT_ARG_TYPE_STRING, result.weekdayShort}, // 9
{FF_FORMAT_ARG_TYPE_UINT16, &result.dayInYear}, // 10 {FF_FORMAT_ARG_TYPE_UINT16, &result.dayInYear}, // 10
{FF_FORMAT_ARG_TYPE_UINT8, &result.dayInMonth}, // 11 {FF_FORMAT_ARG_TYPE_UINT8, &result.dayInMonth}, // 11
{FF_FORMAT_ARG_TYPE_UINT8, &result.dayInWeek}, // 12 {FF_FORMAT_ARG_TYPE_UINT8, &result.dayInWeek}, // 12
{FF_FORMAT_ARG_TYPE_UINT8, &result.hour}, // 13 {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_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_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_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) void ffPrintDateTime(FFDateTimeOptions* options)
@@ -205,7 +177,9 @@ void ffPrintDateTimeHelpFormat(void)
"minute", "minute",
"minute with leading zero", "minute with leading zero",
"second", "second",
"second with leading zero" "second with leading zero",
"offset from UTC in the ISO 8601 format",
"locale-dependent timezone name or abbreviation",
}); });
} }
+1
View File
@@ -8,6 +8,7 @@
#include "modules/brightness/brightness.h" #include "modules/brightness/brightness.h"
#include "modules/board/board.h" #include "modules/board/board.h"
#include "modules/break/break.h" #include "modules/break/break.h"
#include "modules/camera/camera.h"
#include "modules/chassis/chassis.h" #include "modules/chassis/chassis.h"
#include "modules/cpu/cpu.h" #include "modules/cpu/cpu.h"
#include "modules/cpuusage/cpuusage.h" #include "modules/cpuusage/cpuusage.h"
+1
View File
@@ -8,6 +8,7 @@
#include "modules/board/option.h" #include "modules/board/option.h"
#include "modules/break/option.h" #include "modules/break/option.h"
#include "modules/brightness/option.h" #include "modules/brightness/option.h"
#include "modules/camera/option.h"
#include "modules/chassis/option.h" #include "modules/chassis/option.h"
#include "modules/cpu/option.h" #include "modules/cpu/option.h"
#include "modules/cpuusage/option.h" #include "modules/cpuusage/option.h"
-2
View File
@@ -33,8 +33,6 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options)
if(result->name.length > 0) if(result->name.length > 0)
puts(result->name.chars); puts(result->name.chars);
else if(result->watts == FF_POWERADAPTER_NOT_CONNECTED)
puts("not connected");
else else
printf("%dW\n", result->watts); printf("%dW\n", result->watts);
} }
-7
View File
@@ -29,8 +29,6 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va
ffStrbufSetS(&options->libZ, yyjson_get_str(val)); ffStrbufSetS(&options->libZ, yyjson_get_str(val));
#if defined(__linux__) || defined(__FreeBSD__) #if defined(__linux__) || defined(__FreeBSD__)
else if (ffStrEqualsIgnCase(key, "pci"))
ffStrbufSetS(&options->libPCI, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "freetype")) else if (ffStrEqualsIgnCase(key, "freetype"))
ffStrbufSetS(&options->libfreetype, yyjson_get_str(val)); ffStrbufSetS(&options->libfreetype, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "wayland")) else if (ffStrEqualsIgnCase(key, "wayland"))
@@ -95,8 +93,6 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key
ffOptionParseString(key, value, &options->libZ); ffOptionParseString(key, value, &options->libZ);
#if defined(__linux__) || defined(__FreeBSD__) #if defined(__linux__) || defined(__FreeBSD__)
else if(ffStrEqualsIgnCase(subkey, "PCI"))
ffOptionParseString(key, value, &options->libPCI);
else if(ffStrEqualsIgnCase(subkey, "freetype")) else if(ffStrEqualsIgnCase(subkey, "freetype"))
ffOptionParseString(key, value, &options->libfreetype); ffOptionParseString(key, value, &options->libfreetype);
else if(ffStrEqualsIgnCase(subkey, "wayland")) 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); yyjson_mut_obj_add_strbuf(doc, obj, "z", &options->libZ);
#if defined(__linux__) || defined(__FreeBSD__) #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)) if (!ffStrbufEqual(&options->libWayland, &defaultOptions.libWayland))
yyjson_mut_obj_add_strbuf(doc, obj, "wayland", &options->libWayland); yyjson_mut_obj_add_strbuf(doc, obj, "wayland", &options->libWayland);
-1
View File
@@ -12,7 +12,6 @@ typedef struct FFOptionsLibrary
FFstrbuf libZ; FFstrbuf libZ;
#if defined(__linux__) || defined(__FreeBSD__) #if defined(__linux__) || defined(__FreeBSD__)
FFstrbuf libPCI;
FFstrbuf libWayland; FFstrbuf libWayland;
FFstrbuf libXcbRandr; FFstrbuf libXcbRandr;
FFstrbuf libXcb; FFstrbuf libXcb;
+2
View File
@@ -9,6 +9,7 @@ void ffOptionsInitModules(FFOptionsModules* options)
ffInitBoardOptions(&options->board); ffInitBoardOptions(&options->board);
ffInitBreakOptions(&options->break_); ffInitBreakOptions(&options->break_);
ffInitBrightnessOptions(&options->brightness); ffInitBrightnessOptions(&options->brightness);
ffInitCameraOptions(&options->camera);
ffInitCPUOptions(&options->cpu); ffInitCPUOptions(&options->cpu);
ffInitCPUUsageOptions(&options->cpuUsage); ffInitCPUUsageOptions(&options->cpuUsage);
ffInitChassisOptions(&options->chassis); ffInitChassisOptions(&options->chassis);
@@ -72,6 +73,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options)
ffDestroyBoardOptions(&options->board); ffDestroyBoardOptions(&options->board);
ffDestroyBreakOptions(&options->break_); ffDestroyBreakOptions(&options->break_);
ffDestroyBrightnessOptions(&options->brightness); ffDestroyBrightnessOptions(&options->brightness);
ffDestroyCameraOptions(&options->camera);
ffDestroyCPUOptions(&options->cpu); ffDestroyCPUOptions(&options->cpu);
ffDestroyCPUUsageOptions(&options->cpuUsage); ffDestroyCPUUsageOptions(&options->cpuUsage);
ffDestroyChassisOptions(&options->chassis); ffDestroyChassisOptions(&options->chassis);
+1
View File
@@ -12,6 +12,7 @@ typedef struct FFOptionsModules
FFBrightnessOptions brightness; FFBrightnessOptions brightness;
FFCPUOptions cpu; FFCPUOptions cpu;
FFCPUUsageOptions cpuUsage; FFCPUUsageOptions cpuUsage;
FFCameraOptions camera;
FFChassisOptions chassis; FFChassisOptions chassis;
FFColorsOptions colors; FFColorsOptions colors;
FFCommandOptions command; FFCommandOptions command;
+13 -7
View File
@@ -17,17 +17,17 @@
static void getExePath(FFPlatform* platform) static void getExePath(FFPlatform* platform)
{ {
FFstrbuf* const exePath = &platform->exePath; char exePath[PATH_MAX + 1];
ffStrbufEnsureFree(exePath, PATH_MAX);
#ifdef __linux__ #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__) #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__) #elif defined(__FreeBSD__)
size_t exePathLen = exePath->allocated; size_t exePathLen = sizeof(exePath);
if(sysctl( if(sysctl(
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, (int) getpid()}, 4, (int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, (int) getpid()}, 4,
exePath->chars, &exePathLen, exePath, &exePathLen,
NULL, 0 NULL, 0
) < 0) ) < 0)
exePathLen = 0; exePathLen = 0;
@@ -35,7 +35,13 @@ static void getExePath(FFPlatform* platform)
exePathLen--; // remove terminating NUL exePathLen--; // remove terminating NUL
#endif #endif
if (exePathLen > 0) 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) static void platformPathAddEnv(FFlist* dirs, const char* env)
+23 -3
View File
@@ -18,6 +18,14 @@ static void getExePath(FFPlatform* platform)
DWORD exePathWLen = GetModuleFileNameW(NULL, exePathW, MAX_PATH); DWORD exePathWLen = GetModuleFileNameW(NULL, exePathW, MAX_PATH);
if (exePathWLen == 0 && exePathWLen >= MAX_PATH) return; 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); ffStrbufSetNWS(&platform->exePath, exePathWLen, exePathW);
if (ffStrbufStartsWithS(&platform->exePath, "\\\\?\\")) if (ffStrbufStartsWithS(&platform->exePath, "\\\\?\\"))
ffStrbufSubstrAfter(&platform->exePath, 3); ffStrbufSubstrAfter(&platform->exePath, 3);
@@ -32,9 +40,15 @@ static void getHomeDir(FFPlatform* platform)
ffStrbufSetWS(&platform->homeDir, pPath); ffStrbufSetWS(&platform->homeDir, pPath);
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/'); ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/'); ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
CoTaskMemFree(pPath); CoTaskMemFree(pPath);
} }
else
{
ffStrbufSetS(&platform->homeDir, getenv("USERPROFILE"));
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
}
static void getCacheDir(FFPlatform* platform) static void getCacheDir(FFPlatform* platform)
{ {
@@ -44,13 +58,13 @@ static void getCacheDir(FFPlatform* platform)
ffStrbufSetWS(&platform->cacheDir, pPath); ffStrbufSetWS(&platform->cacheDir, pPath);
ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/'); ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/'); ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
CoTaskMemFree(pPath);
} }
else else
{ {
ffStrbufAppend(&platform->cacheDir, &platform->homeDir); ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
ffStrbufAppendS(&platform->cacheDir, "AppData/Local/"); ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
} }
CoTaskMemFree(pPath);
} }
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
@@ -63,9 +77,9 @@ static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
ffStrbufEnsureEndsWithC(&buffer, '/'); ffStrbufEnsureEndsWithC(&buffer, '/');
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual)) if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer); ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
}
CoTaskMemFree(pPath); CoTaskMemFree(pPath);
} }
}
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
{ {
@@ -121,12 +135,18 @@ static void getDataDirs(FFPlatform* platform)
} }
static void getUserName(FFPlatform* platform) static void getUserName(FFPlatform* platform)
{
const char* userName = getenv("USERNAME");
if (ffStrSet(userName))
ffStrbufSetS(&platform->userName, userName);
else
{ {
wchar_t buffer[128]; wchar_t buffer[128];
DWORD len = sizeof(buffer) / sizeof(*buffer); DWORD len = sizeof(buffer) / sizeof(*buffer);
if(GetUserNameW(buffer, &len)) if(GetUserNameW(buffer, &len))
ffStrbufSetWS(&platform->userName, buffer); ffStrbufSetWS(&platform->userName, buffer);
} }
}
static void getHostName(FFPlatform* platform) static void getHostName(FFPlatform* platform)
{ {
+24 -10
View File
@@ -1,16 +1,12 @@
#include <oaidl.h> #include <oaidl.h>
#include <propidl.h>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <string_view> #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() { bool hasValue() {
return this->vt != VT_EMPTY; return this->vt != VT_EMPTY;
} }
@@ -33,11 +29,11 @@ struct FFWmiVariant: VARIANT
return this->cVal; return this->cVal;
} }
else if constexpr (std::is_same_v<T, int16_t>) { else if constexpr (std::is_same_v<T, int16_t>) {
assert(vt == VT_I2); assert(this->vt == VT_I2);
return this->iVal; return this->iVal;
} }
else if constexpr (std::is_same_v<T, int32_t>) { 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; return this->intVal;
} }
else if constexpr (std::is_same_v<T, int64_t>) { else if constexpr (std::is_same_v<T, int64_t>) {
@@ -55,7 +51,7 @@ struct FFWmiVariant: VARIANT
return this->uiVal; return this->uiVal;
} }
else if constexpr (std::is_same_v<T, uint32_t>) { 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; return this->uintVal;
} }
else if constexpr (std::is_same_v<T, uint64_t>) { 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), "");