mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
334 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9742642fc | |||
| 356c905703 | |||
| 47a5473a35 | |||
| 96bca6888a | |||
| bbf31c1a95 | |||
| 42b8c1b429 | |||
| 77fde11039 | |||
| e13f04e80f | |||
| ad026f6105 | |||
| 9107d0e107 | |||
| ee876c54bf | |||
| 4af44a40bf | |||
| 399cfe2fbc | |||
| 71d0cdbfce | |||
| aae740472f | |||
| 8f9beb2789 | |||
| 77b93a904f | |||
| 7934c16bca | |||
| 941ddee2fc | |||
| 16113bf330 | |||
| 505182428b | |||
| 3c2a84ff78 | |||
| 8a3346b650 | |||
| 5b63fb1362 | |||
| 393857b067 | |||
| cb8a9c0796 | |||
| 036752763f | |||
| 3a90af1f44 | |||
| 772de0ff97 | |||
| 53a61a8e58 | |||
| a37328c1aa | |||
| 782325395c | |||
| e13d554433 | |||
| 15c72c04af | |||
| b797246607 | |||
| d54bb4fd16 | |||
| 0a946e3976 | |||
| a339f00d83 | |||
| de15866c9a | |||
| 24ee87720e | |||
| 7310b3ed09 | |||
| bb6cdc7bb0 | |||
| 4a2d20fb74 | |||
| b136b86300 | |||
| d4a7ae8b34 | |||
| 04da7cebdb | |||
| ccb227e694 | |||
| 9c7b868227 | |||
| f333937b35 | |||
| e4f6f15d70 | |||
| 5ae8ef1cb3 | |||
| d863652e1b | |||
| ac540d73b7 | |||
| 37b9da7337 | |||
| 93c0dbde0d | |||
| aa236b4da0 | |||
| 2fd3643632 | |||
| 24f9247c54 | |||
| d312b752a1 | |||
| 1b476757a0 | |||
| c78a8f6317 | |||
| 24c3788055 | |||
| a644762a60 | |||
| 3185d92fb5 | |||
| 2c629bc821 | |||
| 1a6c38bc26 | |||
| 589f9aa8f3 | |||
| 70e5d0b235 | |||
| aa81d80578 | |||
| 7bc6676680 | |||
| ab9b10824f | |||
| f5931e80e7 | |||
| bf4f86b4f6 | |||
| 7f59f22cf4 | |||
| 14f4817381 | |||
| e821468bb0 | |||
| d9315d2332 | |||
| a2b4be388e | |||
| 35e06642f9 | |||
| 92de3e4f30 | |||
| 5b65e182e9 | |||
| a7896c39f0 | |||
| 4f19bf9a18 | |||
| c379c65960 | |||
| 1ae0a83880 | |||
| 77f7c813f4 | |||
| bfec8b5634 | |||
| 15a43a6b11 | |||
| c9e3c34ce1 | |||
| b99b3ad982 | |||
| f4ce5c4143 | |||
| bb4bf63621 | |||
| 60c1a552bb | |||
| 0a979ddd1e | |||
| e45c4b49fd | |||
| b89ace7aae | |||
| 424ca923fc | |||
| e837e1e1d1 | |||
| aea0986928 | |||
| dc2a3492f0 | |||
| 8cf033002c | |||
| 4d7cb25aa6 | |||
| 60cf3ec861 | |||
| 4fd82b16e8 | |||
| 26feccc0e4 | |||
| 9a1bc66dfc | |||
| 24a3783d7c | |||
| 7e072c395f | |||
| 94e1ed1d7e | |||
| 94e6f4040d | |||
| d570e59818 | |||
| 0e9d48fff0 | |||
| e690d73434 | |||
| 8f2b3c6b69 | |||
| 3c0b2fc910 | |||
| 7d0a1c8987 | |||
| 757d947446 | |||
| 4ced4f9631 | |||
| c6859d7edd | |||
| 94cf9a89cc | |||
| bd8d78427b | |||
| e40d4b9b68 | |||
| 4a07485a19 | |||
| 71614e0b0c | |||
| d5b6c14bdf | |||
| 9509718b0e | |||
| c0ca022ac2 | |||
| 708b4a8981 | |||
| 8006b0ca4f | |||
| cc2286f056 | |||
| 81a4be498b | |||
| 56477f5ea6 | |||
| ca05e2e905 | |||
| a524302ea7 | |||
| 945b5f1b15 | |||
| ccb0f853db | |||
| b8f1b0d6aa | |||
| aa7d5bd704 | |||
| 9ee4c08790 | |||
| 725d2f2612 | |||
| 4d5ad691f3 | |||
| b2f3bf3461 | |||
| 44c389d29f | |||
| ac8e03419e | |||
| babb836f91 | |||
| 95e0a5ee95 | |||
| 642a0c78cc | |||
| 1ac90584cb | |||
| ccef5de86e | |||
| e526ec9c32 | |||
| b15e68658f | |||
| dcd0f8d3f6 | |||
| b3da6b0e89 | |||
| ff8c761de0 | |||
| e6258acb55 | |||
| ecafed8fd5 | |||
| 73f99b1298 | |||
| 7a6ed854ec | |||
| e923d78016 | |||
| 615b2f72ae | |||
| 9773349253 | |||
| fc57fa5415 | |||
| bdd9d46517 | |||
| 013499f7a2 | |||
| c4416379bb | |||
| c0c07e7dc9 | |||
| 38ec3718ce | |||
| e2e3561443 | |||
| 199f2fc0cd | |||
| c944b2f599 | |||
| fdd0d47762 | |||
| e5f851dcbb | |||
| 78cb2781e6 | |||
| ef9b5c57b1 | |||
| 52eacd7140 | |||
| b19d8d6700 | |||
| 6b0add44ee | |||
| b66338494f | |||
| 47cec48a49 | |||
| 09ccbca79c | |||
| 4f28ae62a7 | |||
| e953ea6542 | |||
| de72c98a28 | |||
| 7f15f91bd3 | |||
| c570c5bf97 | |||
| 52c304ecae | |||
| 4f4860eee8 | |||
| 695e3cc692 | |||
| e05d9da231 | |||
| c16f9a9e20 | |||
| 74b1871f18 | |||
| 8fdb877840 | |||
| 3a7d7d79c0 | |||
| 28baf2596e | |||
| 30d1a55dde | |||
| 3e068d16df | |||
| c283e39b22 | |||
| f6702d83d0 | |||
| b1a779c178 | |||
| cc1260ee3c | |||
| 92b1788825 | |||
| efdbeb585b | |||
| 304f171d38 | |||
| 9a3909f8ba | |||
| 6ca4b5391b | |||
| cabd36d078 | |||
| 64bacd2572 | |||
| 47be29b89c | |||
| 6407bf6a1f | |||
| e2d145cf31 | |||
| b634c70f80 | |||
| e29169711c | |||
| 662ddac050 | |||
| b90d543afc | |||
| f05d134aa7 | |||
| 74a68aa626 | |||
| fcc5170a10 | |||
| 3a9403a2f1 | |||
| ff170caff6 | |||
| 532b493c42 | |||
| 51cc87e0db | |||
| 878d4608b1 | |||
| 03d1c62787 | |||
| 5c46271898 | |||
| 9a7c732555 | |||
| 8ffe6fda9b | |||
| e563417166 | |||
| ec3f9acd76 | |||
| 6c22fd6902 | |||
| 82b10a527b | |||
| 92c744d971 | |||
| 7a691a4286 | |||
| e98489a74b | |||
| 7a5da23b0c | |||
| edf4837ed6 | |||
| 749bd8db0e | |||
| d2460d8e85 | |||
| eead4cf70e | |||
| 291f88b1e4 | |||
| 93f1a44d0f | |||
| 550e107683 | |||
| 7a8b94b6d4 | |||
| 2005b396fa | |||
| 2a80b5ed36 | |||
| 47a32c725d | |||
| fc26acd0ab | |||
| e57f7d378a | |||
| 6de74587bd | |||
| 6e5e7851d4 | |||
| 84ccda45b0 | |||
| ec3cd6cc68 | |||
| cae9fee30a | |||
| f0111a8037 | |||
| 8fad590f8b | |||
| 2ae5a9d725 | |||
| 8153c8b82c | |||
| 159f4a3a3c | |||
| 3dbfff57e7 | |||
| a063cd4feb | |||
| dc5da3c3b3 | |||
| 79c9c19b1a | |||
| b49b583e64 | |||
| 0b8e8ad4f2 | |||
| 7fc2c4dcf1 | |||
| a74cbc5781 | |||
| 619ec921ee | |||
| 1b23c9a030 | |||
| d4c11b9a1f | |||
| 55da030e2a | |||
| c64f306550 | |||
| 7ee4a648d0 | |||
| 78ca4e7c87 | |||
| 7a2826358b | |||
| df84721b55 | |||
| f53a1f785d | |||
| 4f3b9776ae | |||
| 39f47d65a9 | |||
| a92e6b6d91 | |||
| 00e044c431 | |||
| 7132762c9c | |||
| 2476b44300 | |||
| d36e827ec9 | |||
| a37115cb00 | |||
| 7dc73c61ab | |||
| a14ef06d14 | |||
| 212e7aa47e | |||
| ebe26eddf0 | |||
| 517e3fcff9 | |||
| 679162c762 | |||
| e4973b3262 | |||
| a1ea7804f3 | |||
| 2c51d55ba2 | |||
| 3b0e1a5833 | |||
| 9bb6d8fd6e | |||
| 4afba798ba | |||
| f4cefe955b | |||
| 1c38ebb551 | |||
| 14dcafe2ca | |||
| cf78216d78 | |||
| 0c256e2908 | |||
| 00fc3f1a1d | |||
| 672e309d89 | |||
| b0c19256f0 | |||
| 205e664b4d | |||
| cb466aec08 | |||
| 33f3744a63 | |||
| 7adb1606f1 | |||
| 184ada6ae8 | |||
| 856c9d58b8 | |||
| f3fba8a389 | |||
| 10468a559a | |||
| c4c9f02433 | |||
| f2dd288a0d | |||
| aa36a83182 | |||
| dd9047c4e9 | |||
| 11634b9a67 | |||
| d832324306 | |||
| a7af5c4f66 | |||
| 0f2022bd40 | |||
| e598598ca8 | |||
| 85599fcf53 | |||
| 6961488d38 | |||
| 209d0c98d9 | |||
| d718cc997c | |||
| 4967d0a222 | |||
| 17ebd5cea8 | |||
| 25e81b39f9 | |||
| 4b253aa4cf | |||
| d7b84bed9f | |||
| 298d091e2e | |||
| ebe30394f2 | |||
| 4c7d479e93 | |||
| d6d204ae5f | |||
| ed23eb0fde |
+1
-1
@@ -1 +1 @@
|
||||
github: LinusDierheimer
|
||||
github: [LinusDierheimer, CarterLi]
|
||||
|
||||
+105
-27
@@ -5,9 +5,44 @@ on:
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
linux-buildtest:
|
||||
name: Linux build test
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
compiler: [gcc, clang]
|
||||
enableFeatures: [ON, OFF]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- 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 rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libcjson-dev
|
||||
|
||||
- name: configure project
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
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_JSONC=${{ matrix.enableFeatures }} .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: run fastfetch
|
||||
run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||
|
||||
- name: run flashfetch
|
||||
run: ./flashfetch
|
||||
|
||||
linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -18,7 +53,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- 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 rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev
|
||||
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 rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libcjson-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
@@ -130,8 +165,8 @@ jobs:
|
||||
name: fastfetch-freebsd
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows:
|
||||
name: Windows
|
||||
win64:
|
||||
name: Win64
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -148,27 +183,11 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG64
|
||||
update: true
|
||||
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-cjson
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
|
||||
- name: create OpenCL.pc
|
||||
run: |
|
||||
cat > /clang64/lib/pkgconfig/OpenCL.pc << EOF
|
||||
prefix=/clang64
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: OpenCL
|
||||
Description: Open Computing Language generic Installable Client Driver Loader
|
||||
Version: 2022.09.30-1
|
||||
Libs: -L${libdir} -lOpenCL.dll
|
||||
Cflags: -I${includedir}
|
||||
EOF
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
@@ -184,7 +203,7 @@ jobs:
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
|
||||
run: cp /clang64/bin/{libcjson,OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -199,13 +218,71 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: zip fastfetch-$(./fastfetch --version-raw)-Windows.zip *.dll fastfetch.exe flashfetch.exe
|
||||
run: zip fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: fastfetch-windows
|
||||
path: ./fastfetch-*-Windows.zip
|
||||
name: fastfetch-win64
|
||||
path: ./fastfetch-*-Win64.zip
|
||||
|
||||
win32:
|
||||
name: Win32
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG32
|
||||
update: true
|
||||
install: git zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd mingw-w64-clang-i686-cjson
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: c, cpp
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang32/bin/{libcjson,OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: zip fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: fastfetch-win32
|
||||
path: ./fastfetch-*-Win32.zip
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch'
|
||||
@@ -215,7 +292,8 @@ jobs:
|
||||
- linux
|
||||
- macos
|
||||
- freebsd
|
||||
- windows
|
||||
- win64
|
||||
- win32
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -235,4 +313,4 @@ jobs:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*
|
||||
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-win64/*,fastfetch-win32/*
|
||||
|
||||
+130
@@ -1,3 +1,133 @@
|
||||
# 1.11.2
|
||||
|
||||
This release should be the last version of fastfetch 1.x (if no serious bugs found, hopefully)
|
||||
|
||||
Features:
|
||||
* Support display name, type, rotation detection on Wayland (Linux, Display)
|
||||
* Print more useful display name instead of intel_backlight (Linux, Brightness)
|
||||
* Icons module supports Windows (Windows, Icons)
|
||||
* Add Wallpaper module which shows the current wallpaper image path
|
||||
* Add mac address detection `--localip-show-mac` (LocalIP, #451)
|
||||
|
||||
Bugfixes:
|
||||
* Fix Gnome version detection on Fedora (DE)
|
||||
* Fix Windows drives detection in WSL (Disk)
|
||||
|
||||
Changes:
|
||||
* In order to make Icons module consistant between different platforms, `--icons-format` no longer supports individual GTK / QT icon params.
|
||||
* `--theme-format` no longer supports individual GTK / plasma theme params.
|
||||
* `--local-ip-*` and `--public-ip-*` have been changed to `--localip-*` and `--publicip-*`
|
||||
* `--localip-compact-type` is no longer supported. Fastfetch now display IPs as `--localip-compat-type multiline` by default, with `--local-compact true` can be set as an alias of `--localip-compact-type oneline`
|
||||
* `--localip-v6first` is no longer supported.
|
||||
|
||||
# 1.11.1
|
||||
|
||||
Features:
|
||||
* Support xonsh detection (TerminalShell)
|
||||
* Support Tabby version / terminal font detection (TerminalFont)
|
||||
|
||||
Bugfixes:
|
||||
* Fix name of Pro Controller (Gamepad, Windows)
|
||||
* Fix compile error with imagemagick enabled (Windows)
|
||||
* Fix copy-and-paste errors (Gamepad)
|
||||
* Flatpak: Fix user package count
|
||||
* Flatpak: Count runtime packages too (#441)
|
||||
* Fix flatpak package count (#441)
|
||||
* Don't print white color blocks with `--pipe` (#450)
|
||||
* Fix iTerm being detected as iTermServer-* sometimes
|
||||
* Fix sound device volume being incorrectly detected as muted sometimes (Sound)
|
||||
* Fix memleaks reported by LeakSanitizer (Linux)
|
||||
* Fix potential memory curruption bug in unicode.c (Windows)
|
||||
|
||||
Logo:
|
||||
* Update Windows 11 ASCII logo to look more visually consistent (#445)
|
||||
* Add another font color index to arch icon (#446)
|
||||
* Add SteamOS
|
||||
* Add macOS small / small2
|
||||
|
||||
# 1.11.0
|
||||
|
||||
Features:
|
||||
* Support linuxbrew (Packages, Linux)
|
||||
* Support foot terminal (#431, Linux)
|
||||
* Support cursor size detection on Windows (Cursor, Windows)
|
||||
* Support cursor detection on macOS (Cursor, macOS)
|
||||
* Support display name, display type and decimal refresh rate detection (Display, macOS / Windows)
|
||||
* Support `--display-compact-type` to display multiple resolutions in one line (Display)
|
||||
* Support flatpak-user (Packages, Linux, #436)
|
||||
* Support `--gpu-force-vulkan` to force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations` (GPU)
|
||||
|
||||
Bugfixes:
|
||||
* Fix date time format
|
||||
* Fix compiling with musl (Wifi, Linux, #429)
|
||||
* Don't exit if libpci is failed to init (GPU, Linux, #433)
|
||||
* Names of most well-known gamepads are correctly printed instead of `Wireless Controller` on Windows
|
||||
|
||||
Logo:
|
||||
* Small update for nobara logo (#435, @regulargvy13)
|
||||
|
||||
# 1.10.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix uninitialized variables (GPU, Windows)
|
||||
* Fix compiling errors (Windows)
|
||||
|
||||
Improvements:
|
||||
* Improve preformance (WmTheme amd Font, Windows and macOS)
|
||||
* Enable nonblocking public-ip / weather detection (Android)
|
||||
|
||||
# 1.10.2
|
||||
|
||||
Bugfixes:
|
||||
* Handle `kAudioObjectPropertyElementMain` for macOS **SDK** < 12 (#425, @nandahkrishna)
|
||||
* Add missing `NULL` for `ffProcessAppendStdOut` (#421)
|
||||
|
||||
# 1.10.1
|
||||
|
||||
New release for debugging #421
|
||||
|
||||
# 1.10.0
|
||||
|
||||
Notable Changes:
|
||||
|
||||
* With the support of Win32 platform, original Windows 64bit artifact file is renamed to Win64 to avoid possible confusion
|
||||
|
||||
Features:
|
||||
* Bluetooth module
|
||||
* Sound module
|
||||
* Gamepad module
|
||||
* Support colored percentage numbers output (#409)
|
||||
* Support `--localip-compact-type` option (#408)
|
||||
* Terminator terminal font detection (@Zerogiven, #415)
|
||||
* Windows 32bit compatibility
|
||||
* Support global configuration in MSYS2 environment (Windows)
|
||||
* Support GPU driver version detection on Windows 11
|
||||
* Support scaled resolution detection for wayland (Linux)
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix build with older libnm versions
|
||||
* Fix a rare case that fails to detect terminal
|
||||
* Fix Muffin detection (@Zerogiven, #411)
|
||||
* Fix IPv6 detection (Windows)
|
||||
* Fix scoop package count detection when scoop is installed in non-default path (Windows, #417)
|
||||
* Fix UB reported by clang
|
||||
* Honor $SCOOP when detecting scoop packages (#417)
|
||||
|
||||
Other:
|
||||
|
||||
* Simplified wmtheme output format (Windows)
|
||||
* Improved GPU detection performance on Windows 11
|
||||
* Lastest Mac model identifier support (macOS)
|
||||
|
||||
# 1.9.1
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix builds on s390x (@jonathanspw, #402)
|
||||
* Fix zero refresh rate on some monitors (macOS)
|
||||
* Fix default formatting of Wifi module
|
||||
|
||||
# 1.9.0
|
||||
|
||||
Notable Changes:
|
||||
|
||||
+91
-34
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 1.9.0
|
||||
VERSION 1.11.2
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast system information tool"
|
||||
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
|
||||
@@ -57,7 +57,7 @@ cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD OR APPLE" OFF)
|
||||
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE" OFF)
|
||||
@@ -67,13 +67,12 @@ cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
|
||||
cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF)
|
||||
cmake_dependent_option(USE_WIN_GPU_DXGI "Use DXGI to detect GPUs instead of WMI. Faster, but may ignore GPUs that only support DX9" ON "WIN32" OFF)
|
||||
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
@@ -117,7 +116,11 @@ if(NOT WIN32)
|
||||
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
if(NOT WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
include(CheckIPOSupported)
|
||||
@@ -161,6 +164,8 @@ if(NOT TARGET_DIR_ETC)
|
||||
set(TARGET_DIR_ETC "${TARGET_DIR_ROOT}/etc")
|
||||
endif()
|
||||
|
||||
message(STATUS "Target dirs: ROOT=\"${TARGET_DIR_ROOT}\" USR=\"${TARGET_DIR_USR}\" HOME=\"${TARGET_DIR_HOME}\" ETC=\"${TARGET_DIR_ETC}\"")
|
||||
|
||||
#https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${TARGET_DIR_USR}" CACHE PATH "..." FORCE)
|
||||
@@ -226,15 +231,15 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/font.c
|
||||
src/common/format.c
|
||||
src/common/init.c
|
||||
src/common/io.c
|
||||
src/common/library.c
|
||||
src/common/parsing.c
|
||||
src/common/printing.c
|
||||
src/common/properties.c
|
||||
src/common/settings.c
|
||||
src/detection/bluetooth/bluetooth.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuUsage/cpuUsage.c
|
||||
src/detection/datetime.c
|
||||
src/detection/datetime/datetime.c
|
||||
src/detection/disk/disk.c
|
||||
src/detection/displayserver/displayserver.c
|
||||
src/detection/font/font.c
|
||||
@@ -242,11 +247,12 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/host/host.c
|
||||
src/detection/locale/locale.c
|
||||
src/detection/media/media.c
|
||||
src/detection/opencl/opencl.c
|
||||
src/detection/os/os.c
|
||||
src/detection/packages/packages.c
|
||||
src/detection/terminalfont/terminalfont.c
|
||||
src/detection/terminalshell/terminalshell.c
|
||||
src/detection/vulkan.c
|
||||
src/detection/vulkan/vulkan.c
|
||||
src/logo/builtin.c
|
||||
src/logo/image/im6.c
|
||||
src/logo/image/im7.c
|
||||
@@ -254,6 +260,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/logo/logo.c
|
||||
src/modules/battery.c
|
||||
src/modules/bios.c
|
||||
src/modules/bluetooth.c
|
||||
src/modules/board.c
|
||||
src/modules/brightness.c
|
||||
src/modules/break.c
|
||||
@@ -272,6 +279,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/gpu.c
|
||||
src/modules/host.c
|
||||
src/modules/icons.c
|
||||
src/modules/gamepad.c
|
||||
src/modules/kernel.c
|
||||
src/modules/locale.c
|
||||
src/modules/localip.c
|
||||
@@ -287,6 +295,8 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/display.c
|
||||
src/modules/separator.c
|
||||
src/modules/shell.c
|
||||
src/modules/sound.c
|
||||
src/modules/swap.c
|
||||
src/modules/media.c
|
||||
src/modules/terminal.c
|
||||
src/modules/terminalfont.c
|
||||
@@ -296,6 +306,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/uptime.c
|
||||
src/modules/users.c
|
||||
src/modules/vulkan.c
|
||||
src/modules/wallpaper.c
|
||||
src/modules/weather.c
|
||||
src/modules/wifi.c
|
||||
src/modules/wm.c
|
||||
@@ -304,10 +315,13 @@ set(LIBFASTFETCH_SRC
|
||||
src/util/FFstrbuf.c
|
||||
src/util/FFvaluestore.c
|
||||
src/util/platform/FFPlatform.c
|
||||
src/util/stringUtils.c
|
||||
)
|
||||
|
||||
if(LINUX)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
@@ -318,6 +332,7 @@ if(LINUX)
|
||||
src/detection/cpu/cpu_linux.c
|
||||
src/detection/cpuUsage/cpuUsage_linux.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
@@ -326,9 +341,11 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gtk.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_linux.c
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
@@ -336,23 +353,28 @@ if(LINUX)
|
||||
src/detection/packages/packages_linux.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/qt.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/swap/swap_linux.c
|
||||
src/detection/temps/temps_linux.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/theme/theme_linux.c
|
||||
src/detection/uptime/uptime_linux.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_android.c
|
||||
src/detection/bios/bios_nosupport.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
src/detection/board/board_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
@@ -364,7 +386,9 @@ elseif(ANDROID)
|
||||
src/detection/font/font_nosupport.c
|
||||
src/detection/gpu/gpu_nosupport.c
|
||||
src/detection/host/host_android.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_nosupport.c
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
@@ -372,23 +396,29 @@ elseif(ANDROID)
|
||||
src/detection/packages/packages_linux.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/sound/sound_nosupport.c
|
||||
src/detection/swap/swap_linux.c
|
||||
src/detection/temps/temps_linux.c
|
||||
src/detection/terminalfont/terminalfont_android.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/uptime/uptime_linux.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_nosupport.c
|
||||
src/detection/wifi/wifi_android.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(BSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_bsd.c
|
||||
src/detection/bios/bios_bsd.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/board/board_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
@@ -403,9 +433,11 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gtk.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_nosupport.c
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_bsd.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
@@ -413,37 +445,44 @@ elseif(BSD)
|
||||
src/detection/packages/packages_linux.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_bsd.c
|
||||
src/detection/qt.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/swap/swap_bsd.c
|
||||
src/detection/temps/temps_linux.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/theme/theme_linux.c
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_apple.c
|
||||
src/detection/bios/bios_apple.c
|
||||
src/detection/bluetooth/bluetooth_apple.m
|
||||
src/detection/board/board_nosupport.c
|
||||
src/detection/brightness/brightness_apple.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/cpuUsage/cpuUsage_apple.c
|
||||
src/detection/cursor/cursor_nosupport.c
|
||||
src/detection/cursor/cursor_apple.m
|
||||
src/detection/disk/disk_apple.m
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/displayserver/displayserver_apple.c
|
||||
src/detection/font/font_apple.m
|
||||
src/detection/gpu/gpu_apple.c
|
||||
src/detection/host/host_apple.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_apple.c
|
||||
src/detection/media/media_apple.m
|
||||
src/detection/memory/memory_apple.c
|
||||
src/detection/opengl/opengl_apple.c
|
||||
@@ -451,12 +490,15 @@ elseif(APPLE)
|
||||
src/detection/packages/packages_apple.c
|
||||
src/detection/poweradapter/poweradapter_apple.c
|
||||
src/detection/processes/processes_bsd.c
|
||||
src/detection/sound/sound_apple.c
|
||||
src/detection/swap/swap_apple.c
|
||||
src/detection/temps/temps_apple.c
|
||||
src/detection/terminalfont/terminalfont_apple.m
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_apple.c
|
||||
src/detection/wifi/wifi_apple.m
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/util/apple/cf_helpers.c
|
||||
@@ -465,10 +507,12 @@ elseif(APPLE)
|
||||
)
|
||||
elseif(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_windows.c
|
||||
src/common/networking_windows.c
|
||||
src/common/processing_windows.c
|
||||
src/detection/battery/battery_windows.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/brightness/brightness_windows.cpp
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
@@ -478,24 +522,31 @@ elseif(WIN32)
|
||||
src/detection/disk/disk_windows.c
|
||||
src/detection/displayserver/displayserver_windows.c
|
||||
src/detection/font/font_windows.c
|
||||
src/detection/gpu/gpu_windows.cpp
|
||||
src/detection/gpu/gpu_windows.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_windows.c
|
||||
src/detection/localip/localip_windows.c
|
||||
src/detection/gamepad/gamepad_windows.c
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/memory/memory_windows.c
|
||||
src/detection/opengl/opengl_windows.c
|
||||
src/detection/os/os_windows.cpp
|
||||
src/detection/packages/packages_windows.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_windows.cpp
|
||||
src/detection/swap/swap_windows.cpp
|
||||
src/detection/processes/processes_windows.c
|
||||
src/detection/sound/sound_windows.cpp
|
||||
src/detection/swap/swap_windows.c
|
||||
src/detection/terminalfont/terminalfont_windows.c
|
||||
src/detection/terminalshell/terminalshell_windows.cpp
|
||||
src/detection/terminalshell/terminalshell_windows.c
|
||||
src/detection/temps/temps_windows.cpp
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/uptime/uptime_windows.c
|
||||
src/detection/users/users_windows.c
|
||||
src/detection/wallpaper/wallpaper_windows.c
|
||||
src/detection/wifi/wifi_windows.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
src/util/windows/registry.c
|
||||
src/util/windows/unicode.c
|
||||
src/util/windows/wmi.cpp
|
||||
@@ -508,6 +559,9 @@ add_library(libfastfetch OBJECT
|
||||
)
|
||||
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
if(WIN32)
|
||||
target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1)
|
||||
endif()
|
||||
|
||||
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX_H)
|
||||
if(HAVE_UTMPX_H)
|
||||
@@ -634,10 +688,6 @@ ff_lib_enable(OPENCL
|
||||
"OpenCL"
|
||||
"OpenCL"
|
||||
)
|
||||
ff_lib_enable(LIBCJSON
|
||||
"libcjson"
|
||||
"CJson"
|
||||
)
|
||||
ff_lib_enable(LIBNM
|
||||
"libnm"
|
||||
"libnm"
|
||||
@@ -646,6 +696,14 @@ ff_lib_enable(FREETYPE
|
||||
"freetype2"
|
||||
"FreeType2"
|
||||
)
|
||||
ff_lib_enable(PULSE
|
||||
"libpulse"
|
||||
"Pulse"
|
||||
)
|
||||
ff_lib_enable(LIBCJSON
|
||||
"libcjson"
|
||||
"CJson"
|
||||
)
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
|
||||
@@ -660,39 +718,38 @@ endif()
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "-framework Cocoa"
|
||||
PRIVATE "-framework CoreFoundation"
|
||||
PRIVATE "-framework CoreAudio"
|
||||
PRIVATE "-framework CoreVideo"
|
||||
PRIVATE "-framework CoreWLAN"
|
||||
PRIVATE "-framework IOBluetooth"
|
||||
PRIVATE "-framework IOKit"
|
||||
PRIVATE "-framework OpenGL"
|
||||
PRIVATE "-framework OpenCL"
|
||||
PRIVATE "-framework Cocoa"
|
||||
PRIVATE "-framework CoreWLAN"
|
||||
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-framework SystemConfiguration"
|
||||
PRIVATE "-weak_framework CoreDisplay"
|
||||
PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "bthprops"
|
||||
PRIVATE "dwmapi"
|
||||
PRIVATE "gdi32"
|
||||
PRIVATE "iphlpapi"
|
||||
PRIVATE "ole32"
|
||||
PRIVATE "oleaut32"
|
||||
PRIVATE "opengl32"
|
||||
PRIVATE "wbemuuid"
|
||||
PRIVATE "ws2_32"
|
||||
PRIVATE "ntdll"
|
||||
PRIVATE "version"
|
||||
PRIVATE "setupapi"
|
||||
PRIVATE "dxgi"
|
||||
PRIVATE "hid"
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "powrprof"
|
||||
)
|
||||
if(USE_WIN_NTAPI)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI)
|
||||
endif()
|
||||
if(USE_WIN_GPU_DXGI)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_GPU_DXGI)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
|
||||
@@ -45,7 +45,7 @@ The following libraries are used if present at runtime:
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
|
||||
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Bluetooth, Player & Media detection.
|
||||
* [`libEGL`](https://www.khronos.org/registry/EGL/),
|
||||
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
|
||||
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
|
||||
@@ -54,7 +54,8 @@ The following libraries are used if present at runtime:
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
|
||||
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
|
||||
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection on Linux.
|
||||
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection.
|
||||
* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection.
|
||||
|
||||
### macOS
|
||||
|
||||
@@ -63,6 +64,7 @@ The following libraries are used if present at runtime:
|
||||
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Used for fast wallpaper detection ( fallback to AppleScript )
|
||||
|
||||
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
|
||||
|
||||
@@ -88,12 +90,12 @@ All categories not listed here should work without needing a specific implementa
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme
|
||||
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wallpaper, Wifi, WM, WMTheme
|
||||
```
|
||||
|
||||
##### Builtin logos
|
||||
```
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, Zorin
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, SteamOS, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, Zorin
|
||||
```
|
||||
|
||||
##### Package managers
|
||||
@@ -113,7 +115,7 @@ Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
|
||||
|
||||
##### Terminal fonts
|
||||
```
|
||||
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal
|
||||
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
+21
-10
@@ -32,8 +32,8 @@ __fastfetch_complete_help()
|
||||
"battery-format"
|
||||
"poweradapter-format"
|
||||
"locale-format"
|
||||
"local-ip-format"
|
||||
"public-ip-format"
|
||||
"localip-format"
|
||||
"publicip-format"
|
||||
"player-format"
|
||||
"media-format"
|
||||
"datetime-format"
|
||||
@@ -42,6 +42,7 @@ __fastfetch_complete_help()
|
||||
"vulkan-format"
|
||||
"opengl-format"
|
||||
"opencl-format"
|
||||
"bluetooth-format"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
@@ -181,10 +182,13 @@ __fastfetch_completion()
|
||||
"--cpu-temp"
|
||||
"--gpu-temp"
|
||||
"--battery-temp"
|
||||
"--display-detect-name"
|
||||
"--display-precise-refresh-rate"
|
||||
"--localip-show-ipv4"
|
||||
"--localip-show-ipv6"
|
||||
"--localip-show-loop"
|
||||
"--localip-name-prefix"
|
||||
"--localip-compact-type"
|
||||
"--escape-bedrock"
|
||||
"--pipe"
|
||||
"--title-fqdn"
|
||||
@@ -197,7 +201,9 @@ __fastfetch_completion()
|
||||
"--disk-show-subvolumes"
|
||||
"--gpu-hide-integrated"
|
||||
"--gpu-hide-discrete"
|
||||
"--gpu-force-vulkan"
|
||||
"--disk-show-unknown"
|
||||
"--bluetooth-show-disconnected"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_STRING=(
|
||||
@@ -221,6 +227,7 @@ __fastfetch_completion()
|
||||
"--color"
|
||||
"--color-keys"
|
||||
"--color-title"
|
||||
"--display-compact-type"
|
||||
"--separator"
|
||||
"-s"
|
||||
"--structure"
|
||||
@@ -228,8 +235,8 @@ __fastfetch_completion()
|
||||
"--set-keyless"
|
||||
"--player-name"
|
||||
"--percent-type"
|
||||
"--public-ip-url"
|
||||
"--public-ip-timeout"
|
||||
"--publicip-url"
|
||||
"--publicip-timeout"
|
||||
"--weather-output-format"
|
||||
"--weather-timeout"
|
||||
"--os-key"
|
||||
@@ -310,12 +317,12 @@ __fastfetch_completion()
|
||||
"--locale-key"
|
||||
"--locale-format"
|
||||
"--locale-error"
|
||||
"--local-ip-key"
|
||||
"--local-ip-format"
|
||||
"--local-ip-error"
|
||||
"--public-ip-key"
|
||||
"--public-ip-format"
|
||||
"--public-ip-error"
|
||||
"--localip-key"
|
||||
"--localip-format"
|
||||
"--localip-error"
|
||||
"--publicip-key"
|
||||
"--publicip-format"
|
||||
"--publicip-error"
|
||||
"--wifi-key"
|
||||
"--wifi-format"
|
||||
"--wifi-error"
|
||||
@@ -349,6 +356,9 @@ __fastfetch_completion()
|
||||
"--users-key"
|
||||
"--users-format"
|
||||
"--users-error"
|
||||
"--bluetooth-key"
|
||||
"--bluetooth-format"
|
||||
"--bluetooth-error"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_PATH=(
|
||||
@@ -374,6 +384,7 @@ __fastfetch_completion()
|
||||
"--lib-glx"
|
||||
"--lib-osmesa"
|
||||
"--lib-opencl"
|
||||
"--lib-pulse"
|
||||
"--battery-dir"
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors
|
||||
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors
|
||||
|
||||
+4
-3
@@ -3,9 +3,9 @@
|
||||
--kernel-format Sysname: {}; Release: {}; Version: {}
|
||||
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
|
||||
--processes-format Count: {}
|
||||
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}
|
||||
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak-system: {}; flatpak-user: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}
|
||||
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
|
||||
--display-format Width: {}; Height: {}; Refresh rate: {}
|
||||
--display-format Width: {}; Height: {}; Refresh rate: {}; ScaledWith: {}; ScaledHeight: {}
|
||||
--de-format Process name: {}; Pretty name: {}; Version: {}
|
||||
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
|
||||
--wm-theme-format Name: {}
|
||||
@@ -17,7 +17,7 @@
|
||||
--terminal-font-format Pretty: {}; Name: {}; Size: {}; Styles: {}
|
||||
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
|
||||
--cpu-usage-format Percentage: {}
|
||||
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}
|
||||
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {}
|
||||
--memory-format Used: {}; Total: {}; Percentage: {}
|
||||
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; Removable: {}; Hidden: {}; Filesystem: {}; Name: {}
|
||||
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
|
||||
@@ -28,3 +28,4 @@
|
||||
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
|
||||
--opengl-format version: {}; renderer: {}; vendor: {}
|
||||
--opencl-format version: {}; device: {}; vendor: {}
|
||||
--bluetooth-format Name: {}; Address: {}; Type: {}; Battery: {}
|
||||
|
||||
@@ -47,3 +47,53 @@ void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent,
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
// if (green < yellow)
|
||||
// [0, green]: print green
|
||||
// (green, yellow]: print yellow
|
||||
// (yellow, 100]: print red
|
||||
//
|
||||
// if (green > yellow)
|
||||
// [green, 100]: print green
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): PRINT RED
|
||||
void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses)
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
bool colored = !!(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
|
||||
if (colored && !instance->config.pipe)
|
||||
{
|
||||
if(green < yellow)
|
||||
{
|
||||
if (percent <= green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
else if (percent <= yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (percent >= green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
else if (percent >= yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%u%%", (unsigned) percent);
|
||||
|
||||
if (colored && !instance->config.pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, ')');
|
||||
}
|
||||
|
||||
+5
-3
@@ -7,11 +7,13 @@
|
||||
|
||||
enum
|
||||
{
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 2,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 4,
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
};
|
||||
|
||||
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||
void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
#include "dbus.h"
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
|
||||
#include "common/thread.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib)
|
||||
{
|
||||
FF_LIBRARY_LOAD(dbus, &instance->config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_has_next, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false)
|
||||
dbus = NULL; // don't auto dlclose
|
||||
return true;
|
||||
}
|
||||
|
||||
static const FFDBusLibrary* loadLib(const FFinstance* instance)
|
||||
{
|
||||
static FFDBusLibrary lib;
|
||||
static bool loaded = false;
|
||||
static bool loadSuccess = false;
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
if(!loaded)
|
||||
{
|
||||
loaded = true;
|
||||
loadSuccess = loadLibSymbols(instance, &lib);
|
||||
}
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return loadSuccess ? &lib : NULL;
|
||||
}
|
||||
|
||||
const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data)
|
||||
{
|
||||
data->lib = loadLib(instance);
|
||||
if(data->lib == NULL)
|
||||
return "Failed to load DBus library";
|
||||
|
||||
data->connection = data->lib->ffdbus_bus_get(busType, NULL);
|
||||
if(data->connection == NULL)
|
||||
return "Failed to connect to DBus";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_STRING)
|
||||
{
|
||||
const char* value = NULL;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
|
||||
if(!ffStrSet(value))
|
||||
return false;
|
||||
|
||||
ffStrbufAppendS(result, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
|
||||
if(argType == DBUS_TYPE_VARIANT)
|
||||
return ffDBusGetValue(dbus, &subIter, result);
|
||||
|
||||
//At this point we have an array
|
||||
|
||||
bool foundAValue = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(ffDBusGetValue(dbus, &subIter, result))
|
||||
{
|
||||
foundAValue = true;
|
||||
ffStrbufAppendS(result, ", ");
|
||||
}
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &subIter);
|
||||
}
|
||||
|
||||
if(foundAValue)
|
||||
ffStrbufSubstrBefore(result, result->length - 2);
|
||||
|
||||
return foundAValue;
|
||||
}
|
||||
|
||||
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_BOOLEAN)
|
||||
{
|
||||
dbus_bool_t value = 0;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
*result = value != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
return ffDBusGetBool(dbus, &subIter, result);
|
||||
}
|
||||
|
||||
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_BYTE)
|
||||
{
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
return ffDBusGetByte(dbus, &subIter, result);
|
||||
}
|
||||
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method)
|
||||
{
|
||||
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
|
||||
if(message == NULL)
|
||||
return NULL;
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property)
|
||||
{
|
||||
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
|
||||
if(message == NULL)
|
||||
return NULL;
|
||||
|
||||
DBusMessageIter requestIterator;
|
||||
dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator);
|
||||
|
||||
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result)
|
||||
{
|
||||
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
|
||||
if(reply == NULL)
|
||||
return;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(reply);
|
||||
return;
|
||||
}
|
||||
|
||||
ffDBusGetValue(dbus, &rootIterator, result);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(reply);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_DBUS
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_dbus
|
||||
#define FF_INCLUDED_common_dbus
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
|
||||
|
||||
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
|
||||
{ \
|
||||
if(!(dbus)->lib->ffdbus_message_iter_has_next(iterator)) \
|
||||
break; \
|
||||
(dbus)->lib->ffdbus_message_iter_next(iterator); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
typedef struct FFDBusLibrary
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(dbus_bus_get)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_init)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_init_append)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_recurse)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_has_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_unref)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_flush)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_unref)
|
||||
} FFDBusLibrary;
|
||||
|
||||
typedef struct FFDBusData
|
||||
{
|
||||
const FFDBusLibrary* lib;
|
||||
DBusConnection* connection;
|
||||
} FFDBusData;
|
||||
|
||||
const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success
|
||||
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
|
||||
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
|
||||
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result);
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method);
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
|
||||
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
#endif // FF_INCLUDED_common_dbus
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "common/format.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
+41
-32
@@ -1,8 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/thread.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
@@ -10,9 +8,8 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef _WIN32
|
||||
#include <wincon.h>
|
||||
#include <windows.h>
|
||||
#include <locale.h>
|
||||
#include <shlobj.h>
|
||||
#include "util/windows/unicode.h"
|
||||
#else
|
||||
#include <signal.h>
|
||||
@@ -112,9 +109,13 @@ static void defaultConfig(FFinstance* instance)
|
||||
initModuleArg(&instance->config.date);
|
||||
initModuleArg(&instance->config.time);
|
||||
initModuleArg(&instance->config.vulkan);
|
||||
initModuleArg(&instance->config.wallpaper);
|
||||
initModuleArg(&instance->config.openGL);
|
||||
initModuleArg(&instance->config.openCL);
|
||||
initModuleArg(&instance->config.users);
|
||||
initModuleArg(&instance->config.bluetooth);
|
||||
initModuleArg(&instance->config.sound);
|
||||
initModuleArg(&instance->config.gamepad);
|
||||
|
||||
ffStrbufInitA(&instance->config.libPCI, 0);
|
||||
ffStrbufInitA(&instance->config.libVulkan, 0);
|
||||
@@ -138,11 +139,13 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.libOpenCL, 0);
|
||||
ffStrbufInitA(&instance->config.libcJSON, 0);
|
||||
ffStrbufInitA(&instance->config.libfreetype, 0);
|
||||
ffStrbufInit(&instance->config.libPulse);
|
||||
ffStrbufInit(&instance->config.libwlanapi);
|
||||
ffStrbufInit(&instance->config.libnm);
|
||||
|
||||
instance->config.cpuTemp = false;
|
||||
instance->config.gpuTemp = false;
|
||||
instance->config.gpuForceVulkan = false;
|
||||
instance->config.batteryTemp = false;
|
||||
|
||||
instance->config.gpuHideIntegrated = false;
|
||||
@@ -154,18 +157,21 @@ static void defaultConfig(FFinstance* instance)
|
||||
instance->config.titleFQDN = false;
|
||||
|
||||
ffStrbufInitA(&instance->config.diskFolders, 0);
|
||||
instance->config.diskShowRemovable = true;
|
||||
instance->config.diskShowHidden = false;
|
||||
instance->config.diskShowUnknown = false;
|
||||
instance->config.diskShowSubvolumes = false;
|
||||
instance->config.diskShowTypes = FF_DISK_TYPE_REGULAR_BIT | FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
|
||||
instance->config.displayCompactType = FF_DISPLAY_COMPACT_TYPE_NONE;
|
||||
instance->config.displayDetectName = false;
|
||||
instance->config.displayPreciseRefreshRate = false;
|
||||
|
||||
instance->config.bluetoothShowDisconnected = false;
|
||||
|
||||
instance->config.soundType = FF_SOUND_TYPE_MAIN;
|
||||
|
||||
ffStrbufInitA(&instance->config.batteryDir, 0);
|
||||
|
||||
ffStrbufInitA(&instance->config.separatorString, 0);
|
||||
|
||||
instance->config.localIpShowIpV4 = true;
|
||||
instance->config.localIpShowIpV6 = false;
|
||||
instance->config.localIpShowLoop = false;
|
||||
instance->config.localIpShowType = FF_LOCALIP_TYPE_IPV4_BIT;
|
||||
ffStrbufInit(&instance->config.localIpNamePrefix);
|
||||
|
||||
instance->config.publicIpTimeout = 0;
|
||||
@@ -204,40 +210,29 @@ void ffInitInstance(FFinstance* instance)
|
||||
defaultConfig(instance);
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
#if defined(FF_HAVE_THREADS) && !(defined(__APPLE__) || defined(_WIN32) || defined(__ANDROID__))
|
||||
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
|
||||
#define FF_START_DETECTION_THREADS
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*)
|
||||
|
||||
#if !(defined(__APPLE__) || defined(_WIN32))
|
||||
|
||||
#define FF_DETECT_QT_GTK 1
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK2, FFinstance*)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK3, FFinstance*)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK4, FFinstance*)
|
||||
|
||||
#endif //!(defined(__APPLE__) || defined(_WIN32))
|
||||
|
||||
#endif //FF_HAVE_THREADS
|
||||
|
||||
void startDetectionThreads(FFinstance* instance)
|
||||
{
|
||||
#ifdef FF_HAVE_THREADS
|
||||
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, instance));
|
||||
|
||||
#ifdef FF_DETECT_QT_GTK
|
||||
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, instance));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, instance));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, instance));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, instance));
|
||||
#endif
|
||||
|
||||
#else
|
||||
FF_UNUSED(instance);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_THREADS
|
||||
|
||||
static volatile bool ffDisableLinewrap = true;
|
||||
static volatile bool ffHideCursor = true;
|
||||
|
||||
@@ -258,7 +253,7 @@ static void resetConsole()
|
||||
BOOL WINAPI consoleHandler(DWORD signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
@@ -272,8 +267,10 @@ static void exitSignalHandler(int signal)
|
||||
|
||||
void ffStart(FFinstance* instance)
|
||||
{
|
||||
if(instance->config.multithreading)
|
||||
startDetectionThreads(instance);
|
||||
#ifdef FF_START_DETECTION_THREADS
|
||||
if(instance->config.multithreading)
|
||||
startDetectionThreads(instance);
|
||||
#endif
|
||||
|
||||
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
|
||||
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
|
||||
@@ -340,6 +337,7 @@ static void destroyConfig(FFinstance* instance)
|
||||
destroyModuleArg(&instance->config.host);
|
||||
destroyModuleArg(&instance->config.bios);
|
||||
destroyModuleArg(&instance->config.board);
|
||||
destroyModuleArg(&instance->config.chassis);
|
||||
destroyModuleArg(&instance->config.kernel);
|
||||
destroyModuleArg(&instance->config.uptime);
|
||||
destroyModuleArg(&instance->config.processes);
|
||||
@@ -366,6 +364,7 @@ static void destroyConfig(FFinstance* instance)
|
||||
destroyModuleArg(&instance->config.locale);
|
||||
destroyModuleArg(&instance->config.localIP);
|
||||
destroyModuleArg(&instance->config.publicIP);
|
||||
destroyModuleArg(&instance->config.wallpaper);
|
||||
destroyModuleArg(&instance->config.weather);
|
||||
destroyModuleArg(&instance->config.wifi);
|
||||
destroyModuleArg(&instance->config.player);
|
||||
@@ -377,6 +376,9 @@ static void destroyConfig(FFinstance* instance)
|
||||
destroyModuleArg(&instance->config.openGL);
|
||||
destroyModuleArg(&instance->config.openCL);
|
||||
destroyModuleArg(&instance->config.users);
|
||||
destroyModuleArg(&instance->config.bluetooth);
|
||||
destroyModuleArg(&instance->config.sound);
|
||||
destroyModuleArg(&instance->config.gamepad);
|
||||
|
||||
ffStrbufDestroy(&instance->config.libPCI);
|
||||
ffStrbufDestroy(&instance->config.libVulkan);
|
||||
@@ -400,6 +402,7 @@ static void destroyConfig(FFinstance* instance)
|
||||
ffStrbufDestroy(&instance->config.libOpenCL);
|
||||
ffStrbufDestroy(&instance->config.libcJSON);
|
||||
ffStrbufDestroy(&instance->config.libfreetype);
|
||||
ffStrbufDestroy(&instance->config.libPulse);
|
||||
ffStrbufDestroy(&instance->config.libwlanapi);
|
||||
ffStrbufDestroy(&instance->config.libnm);
|
||||
|
||||
@@ -436,6 +439,9 @@ void ffDestroyInstance(FFinstance* instance)
|
||||
void ffListFeatures()
|
||||
{
|
||||
fputs(
|
||||
#ifdef FF_HAVE_THREADS
|
||||
"threads\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
@@ -505,6 +511,9 @@ void ffListFeatures()
|
||||
#ifdef FF_HAVE_FREETYPE
|
||||
"freetype\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_PULSE
|
||||
"libpulse\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_LIBNM
|
||||
"libnm\n"
|
||||
#endif
|
||||
|
||||
-285
@@ -1,285 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <fileapi.h>
|
||||
#else
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
FFstrbuf path;
|
||||
ffStrbufInit(&path);
|
||||
|
||||
while(*fileName != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&path, *fileName);
|
||||
if(*fileName == '/')
|
||||
{
|
||||
mkdir(path.chars
|
||||
#ifndef WIN32
|
||||
, S_IRWXU | S_IRGRP | S_IROTH
|
||||
#endif
|
||||
);
|
||||
}
|
||||
++fileName;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
|
||||
{
|
||||
return write(fd, content->chars, content->length) != -1;
|
||||
}
|
||||
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
createSubfolders(fileName);
|
||||
handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD written;
|
||||
bool ret = !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL);
|
||||
|
||||
CloseHandle(handle);
|
||||
#else
|
||||
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
int fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||
if(fd == -1)
|
||||
{
|
||||
createSubfolders(fileName);
|
||||
fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||
if(fd == -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = write(fd, data, dataSize) != -1;
|
||||
|
||||
close(fd);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
|
||||
{
|
||||
return ffWriteFileData(fileName, buffer->length, buffer->chars);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer)
|
||||
{
|
||||
DWORD readed = 0;
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if(!GetFileSizeEx(handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31);
|
||||
uint32_t free = ffStrbufGetFree(buffer);
|
||||
|
||||
bool success;
|
||||
while(
|
||||
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
|
||||
(uint32_t) readed == free
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
if(readed > 0)
|
||||
buffer->length += (uint32_t) readed;
|
||||
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
|
||||
{
|
||||
ssize_t readed = 0;
|
||||
|
||||
struct stat fileInfo;
|
||||
if(fstat(fd, &fileInfo) != 0)
|
||||
return false;
|
||||
|
||||
ffStrbufEnsureFree(buffer, fileInfo.st_size > 0 ? (uint32_t)fileInfo.st_size : 31);
|
||||
uint32_t free = ffStrbufGetFree(buffer);
|
||||
|
||||
while(
|
||||
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
|
||||
(uint32_t) readed == free
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
|
||||
if(readed > 0)
|
||||
buffer->length += (uint32_t) readed;
|
||||
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
return readed >= 0;
|
||||
}
|
||||
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
DWORD readed;
|
||||
if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL))
|
||||
return -1;
|
||||
|
||||
return (ssize_t)readed;
|
||||
#else
|
||||
int fd = open(fileName, O_RDONLY);
|
||||
if(fd == -1)
|
||||
return -1;
|
||||
|
||||
ssize_t readed = read(fd, data, dataSize);
|
||||
|
||||
close(fd);
|
||||
|
||||
return readed;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
bool ret = ffAppendHandleBuffer(handle, buffer);
|
||||
|
||||
CloseHandle(handle);
|
||||
#else
|
||||
int fd = open(fileName, O_RDONLY);
|
||||
if(fd == -1)
|
||||
return false;
|
||||
|
||||
bool ret = ffAppendFDBuffer(fd, buffer);
|
||||
|
||||
close(fd);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufClear(buffer);
|
||||
return ffAppendFileBuffer(fileName, buffer);
|
||||
}
|
||||
|
||||
// Not thread safe!
|
||||
void ffSuppressIO(bool suppress)
|
||||
{
|
||||
static bool init = false;
|
||||
static int origOut = -1;
|
||||
static int origErr = -1;
|
||||
static int nullFile = -1;
|
||||
|
||||
if(!init)
|
||||
{
|
||||
if(!suppress)
|
||||
return;
|
||||
|
||||
origOut = dup(STDOUT_FILENO);
|
||||
origErr = dup(STDERR_FILENO);
|
||||
nullFile = open("/dev/null", O_WRONLY);
|
||||
init = true;
|
||||
}
|
||||
|
||||
if(nullFile == -1)
|
||||
return;
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
dup2(suppress ? nullFile : origOut, STDOUT_FILENO);
|
||||
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
|
||||
}
|
||||
|
||||
bool ffFileExists(const char* fileName, mode_t mode)
|
||||
{
|
||||
struct stat fileStat;
|
||||
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
|
||||
}
|
||||
|
||||
void ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct termios oldTerm, newTerm;
|
||||
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
|
||||
return;
|
||||
|
||||
newTerm = oldTerm;
|
||||
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
|
||||
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
|
||||
return;
|
||||
|
||||
fputs(request, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
struct pollfd pfd;
|
||||
pfd.fd = STDIN_FILENO;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
//Give the terminal 35ms to respond
|
||||
if(poll(&pfd, 1, 35) <= 0)
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
|
||||
if(readed <= 0)
|
||||
return;
|
||||
|
||||
buffer[readed] = '\0';
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsscanf(buffer, format, args);
|
||||
va_end(args);
|
||||
#else
|
||||
//Unimplemented
|
||||
FF_UNUSED(request, format);
|
||||
#endif
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_io
|
||||
#define FF_INCLUDED_common_io
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <sys/stat.h> //mode_t, fstat, stat
|
||||
|
||||
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
|
||||
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer);
|
||||
|
||||
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer);
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
|
||||
#ifdef _WIN32
|
||||
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer);
|
||||
#endif
|
||||
|
||||
bool ffFileExists(const char* fileName, mode_t mode);
|
||||
|
||||
// Not thread safe!
|
||||
void ffSuppressIO(bool suppress);
|
||||
|
||||
FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_io_io
|
||||
#define FF_INCLUDED_common_io_io
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <fileapi.h>
|
||||
#include <handleapi.h>
|
||||
#include <io.h>
|
||||
typedef HANDLE FFNativeFD;
|
||||
#else
|
||||
#include <unistd.h>
|
||||
typedef int FFNativeFD;
|
||||
#endif
|
||||
|
||||
static inline FFNativeFD FFUnixFD2NativeFD(int unixfd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return unixfd;
|
||||
#else
|
||||
return (FFNativeFD) _get_osfhandle(unixfd);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool ffWriteFDData(FFNativeFD fd, size_t dataSize, const void* data)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return write(fd, data, dataSize) != -1;
|
||||
#else
|
||||
DWORD written;
|
||||
return WriteFile(fd, data, (DWORD) dataSize, &written, NULL) && written == dataSize;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool ffWriteFDBuffer(FFNativeFD fd, const FFstrbuf* content)
|
||||
{
|
||||
return ffWriteFDData(fd, content->length, content->chars);
|
||||
}
|
||||
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
|
||||
|
||||
static inline bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
|
||||
{
|
||||
return ffWriteFileData(fileName, buffer->length, buffer->chars);
|
||||
}
|
||||
|
||||
static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return read(fd, data, dataSize);
|
||||
#else
|
||||
DWORD readed;
|
||||
if(!ReadFile(fd, data, (DWORD)dataSize, &readed, NULL))
|
||||
return -1;
|
||||
|
||||
return (ssize_t)readed;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
|
||||
|
||||
bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer);
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
|
||||
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufClear(buffer);
|
||||
return ffAppendFileBuffer(fileName, buffer);
|
||||
}
|
||||
|
||||
//Bit flags, combine with |
|
||||
typedef enum FFPathType
|
||||
{
|
||||
FF_PATHTYPE_REGULAR = 1,
|
||||
FF_PATHTYPE_LINK = 2,
|
||||
FF_PATHTYPE_DIRECTORY = 4
|
||||
} FFPathType;
|
||||
|
||||
#define FF_PATHTYPE_FILE (FF_PATHTYPE_REGULAR | FF_PATHTYPE_LINK)
|
||||
#define FF_PATHTYPE_ANY (FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY)
|
||||
|
||||
bool ffPathExists(const char* path, FFPathType pathType);
|
||||
|
||||
#ifndef _WIN32
|
||||
FF_C_SCANF(2, 3)
|
||||
void ffGetTerminalResponse(const char* request, const char* format, ...);
|
||||
#endif
|
||||
|
||||
// Not thread safe!
|
||||
bool ffSuppressIO(bool suppress);
|
||||
|
||||
static inline void ffUnsuppressIO(bool* suppressed)
|
||||
{
|
||||
if (!*suppressed) return;
|
||||
ffSuppressIO(false);
|
||||
*suppressed = false;
|
||||
}
|
||||
|
||||
#define FF_SUPPRESS_IO() bool __attribute__((__cleanup__(ffUnsuppressIO), __unused__)) io_suppressed__ = ffSuppressIO(true)
|
||||
|
||||
void ffListFilesRecursively(const char* path);
|
||||
|
||||
static inline bool wrapClose(FFNativeFD* pfd)
|
||||
{
|
||||
assert(pfd);
|
||||
|
||||
#ifndef WIN32
|
||||
if (*pfd < 0)
|
||||
return false;
|
||||
close(*pfd);
|
||||
#else
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
if (*pfd == NULL || *pfd == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
CloseHandle(*pfd);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
#define FF_AUTO_CLOSE_FD __attribute__((__cleanup__(wrapClose)))
|
||||
|
||||
static inline bool wrapFclose(FILE** pfile)
|
||||
{
|
||||
assert(pfile);
|
||||
if (!*pfile)
|
||||
return false;
|
||||
fclose(*pfile);
|
||||
return true;
|
||||
}
|
||||
#define FF_AUTO_CLOSE_FILE __attribute__((__cleanup__(wrapFclose)))
|
||||
|
||||
#endif // FF_INCLUDED_common_io_io
|
||||
@@ -0,0 +1,226 @@
|
||||
#include "io.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#include <dirent.h>
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
FFstrbuf path;
|
||||
ffStrbufInit(&path);
|
||||
|
||||
while(*fileName != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&path, *fileName);
|
||||
if(*fileName == '/')
|
||||
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
|
||||
++fileName;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
|
||||
{
|
||||
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
int FF_AUTO_CLOSE_FD fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||
if(fd == -1)
|
||||
{
|
||||
createSubfolders(fileName);
|
||||
fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||
if(fd == -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return write(fd, data, dataSize) > 0;
|
||||
}
|
||||
|
||||
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
|
||||
{
|
||||
ssize_t readed = 0;
|
||||
|
||||
struct stat fileInfo;
|
||||
if(fstat(fd, &fileInfo) != 0)
|
||||
return false;
|
||||
|
||||
ffStrbufEnsureFree(buffer, fileInfo.st_size > 0 ? (uint32_t)fileInfo.st_size : 31);
|
||||
uint32_t free = ffStrbufGetFree(buffer);
|
||||
|
||||
while(
|
||||
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
|
||||
(uint32_t) readed == free
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
|
||||
if(readed > 0)
|
||||
buffer->length += (uint32_t) readed;
|
||||
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
return readed >= 0;
|
||||
}
|
||||
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
|
||||
{
|
||||
int FF_AUTO_CLOSE_FD fd = open(fileName, O_RDONLY);
|
||||
if(fd == -1)
|
||||
return -1;
|
||||
|
||||
return ffReadFDData(fd, dataSize, data);
|
||||
}
|
||||
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
int FF_AUTO_CLOSE_FD fd = open(fileName, O_RDONLY);
|
||||
if(fd == -1)
|
||||
return false;
|
||||
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
bool ffPathExists(const char* path, FFPathType type)
|
||||
{
|
||||
struct stat fileStat;
|
||||
if(stat(path, &fileStat) != 0)
|
||||
return false;
|
||||
|
||||
int mode = fileStat.st_mode & S_IFMT;
|
||||
|
||||
if(type & FF_PATHTYPE_REGULAR && mode == S_IFREG)
|
||||
return true;
|
||||
|
||||
if(type & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
|
||||
return true;
|
||||
|
||||
if(type & FF_PATHTYPE_LINK && mode == S_IFLNK)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
{
|
||||
struct termios oldTerm, newTerm;
|
||||
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
|
||||
return;
|
||||
|
||||
newTerm = oldTerm;
|
||||
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
|
||||
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
|
||||
return;
|
||||
|
||||
fputs(request, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
struct pollfd pfd;
|
||||
pfd.fd = STDIN_FILENO;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
//Give the terminal 35ms to respond
|
||||
if(poll(&pfd, 1, 35) <= 0)
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
|
||||
if(readed <= 0)
|
||||
return;
|
||||
|
||||
buffer[readed] = '\0';
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsscanf(buffer, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
bool ffSuppressIO(bool suppress)
|
||||
{
|
||||
static bool init = false;
|
||||
static int origOut = -1;
|
||||
static int origErr = -1;
|
||||
static int nullFile = -1;
|
||||
|
||||
if(!init)
|
||||
{
|
||||
if(!suppress)
|
||||
return true;
|
||||
|
||||
origOut = dup(STDOUT_FILENO);
|
||||
origErr = dup(STDERR_FILENO);
|
||||
nullFile = open("/dev/null", O_WRONLY);
|
||||
init = true;
|
||||
}
|
||||
|
||||
if(nullFile == -1)
|
||||
return false;
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
dup2(suppress ? nullFile : origOut, STDOUT_FILENO);
|
||||
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
|
||||
return true;
|
||||
}
|
||||
|
||||
void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName)
|
||||
{
|
||||
DIR* dir = opendir(folder->chars);
|
||||
if(dir == NULL)
|
||||
return;
|
||||
|
||||
uint32_t folderLength = folder->length;
|
||||
|
||||
if(folderName != NULL)
|
||||
printf("%s/\n", folderName);
|
||||
|
||||
struct dirent* entry;
|
||||
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type == DT_DIR)
|
||||
{
|
||||
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(folder, entry->d_name);
|
||||
ffStrbufAppendC(folder, '/');
|
||||
listFilesRecursively(folder, (uint8_t) (indentation + 1), entry->d_name);
|
||||
ffStrbufSubstrBefore(folder, folderLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < indentation; i++)
|
||||
fputs(" | ", stdout);
|
||||
|
||||
puts(entry->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void ffListFilesRecursively(const char* path)
|
||||
{
|
||||
FFstrbuf folder;
|
||||
ffStrbufInitS(&folder, path);
|
||||
ffStrbufEnsureEndsWithC(&folder, '/');
|
||||
listFilesRecursively(&folder, 0, NULL);
|
||||
ffStrbufDestroy(&folder);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "io.h"
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path;
|
||||
ffStrbufInit(&path);
|
||||
|
||||
while(*fileName != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&path, *fileName);
|
||||
if(*fileName == '/')
|
||||
CreateDirectoryA(path.chars, NULL);
|
||||
++fileName;
|
||||
}
|
||||
}
|
||||
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
createSubfolders(fileName);
|
||||
handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD written;
|
||||
return !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL);
|
||||
}
|
||||
|
||||
bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer)
|
||||
{
|
||||
DWORD readed = 0;
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if(!GetFileSizeEx(handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31);
|
||||
uint32_t free = ffStrbufGetFree(buffer);
|
||||
|
||||
bool success;
|
||||
while(
|
||||
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
|
||||
(uint32_t) readed == free
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
if(readed > 0)
|
||||
buffer->length += (uint32_t) readed;
|
||||
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
|
||||
return ffReadFDData(handle, dataSize, data);
|
||||
}
|
||||
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
return ffAppendFDBuffer(handle, buffer);
|
||||
}
|
||||
|
||||
bool ffPathExists(const char* path, FFPathType type)
|
||||
{
|
||||
DWORD attr = GetFileAttributesA(path);
|
||||
if(attr == INVALID_FILE_ATTRIBUTES)
|
||||
return false;
|
||||
|
||||
if(type & FF_PATHTYPE_REGULAR && !(attr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
return true;
|
||||
|
||||
if(type & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
return true;
|
||||
|
||||
if(type & FF_PATHTYPE_LINK && (attr & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffSuppressIO(bool suppress)
|
||||
{
|
||||
(void) suppress; //Not implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName)
|
||||
{
|
||||
uint32_t folderLength = folder->length;
|
||||
|
||||
if(folderName != NULL)
|
||||
printf("%s/\n", folderName);
|
||||
|
||||
ffStrbufAppendC(folder, '*');
|
||||
WIN32_FIND_DATAA entry;
|
||||
HANDLE hFind = FindFirstFileA(folder->chars, &entry);
|
||||
if(hFind == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if(strcmp(entry.cFileName, ".") == 0 || strcmp(entry.cFileName, "..") == 0)
|
||||
continue;
|
||||
|
||||
ffStrbufSubstrBefore(folder, folderLength);
|
||||
ffStrbufAppendS(folder, entry.cFileName);
|
||||
ffStrbufAppendC(folder, '/');
|
||||
listFilesRecursively(folder, (uint8_t) (indentation + 1), entry.cFileName);
|
||||
ffStrbufSubstrBefore(folder, folderLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < indentation; i++)
|
||||
fputs(" | ", stdout);
|
||||
|
||||
puts(entry.cFileName);
|
||||
} while (FindNextFileA(hFind, &entry));
|
||||
FindClose(hFind);
|
||||
}
|
||||
|
||||
void ffListFilesRecursively(const char* path)
|
||||
{
|
||||
FFstrbuf folder;
|
||||
ffStrbufInitS(&folder, path);
|
||||
ffStrbufEnsureEndsWithC(&folder, '/');
|
||||
listFilesRecursively(&folder, 0, NULL);
|
||||
ffStrbufDestroy(&folder);
|
||||
}
|
||||
+21
-6
@@ -6,7 +6,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFcheckmacros.h"
|
||||
|
||||
#if defined(_WIN32) //We don't force MSYS using LoadLibrary because dlopen also searches $LD_LIBRARY_PATH
|
||||
#if defined(_WIN32)
|
||||
#include <libloaderapi.h>
|
||||
#define FF_DLOPEN_FLAGS 0
|
||||
FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); }
|
||||
@@ -24,21 +24,30 @@
|
||||
#define FF_LIBRARY_EXTENSION ".so"
|
||||
#endif
|
||||
|
||||
static inline void ffLibraryUnload(void** handle)
|
||||
{
|
||||
assert(handle);
|
||||
if (*handle)
|
||||
dlclose(*handle);
|
||||
}
|
||||
|
||||
#define FF_LIBRARY_SYMBOL(symbolName) \
|
||||
__typeof__(&symbolName) ff ## symbolName;
|
||||
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \
|
||||
void* libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
|
||||
void* __attribute__((__cleanup__(ffLibraryUnload))) libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
|
||||
if(libraryObjectName == NULL) \
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
|
||||
symbolMapping = dlsym(library, #symbolName); \
|
||||
if(symbolMapping == NULL) \
|
||||
{ \
|
||||
dlclose(library); \
|
||||
return returnValue; \
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, symbolMapping, symbolName, alternateName, returnValue) \
|
||||
symbolMapping = dlsym(library, #symbolName); \
|
||||
if(symbolMapping == NULL && !(symbolMapping = dlsym(library, #alternateName))) \
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
|
||||
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
|
||||
@@ -49,12 +58,18 @@
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
|
||||
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(library, symbolName, alternateName) \
|
||||
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(library, varName, symbolName, alternateName) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, varName.ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName->ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
|
||||
+11
-1
@@ -1,8 +1,14 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
#endif
|
||||
|
||||
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
|
||||
{
|
||||
if(major->length > 0)
|
||||
@@ -59,7 +65,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, uint8_t p
|
||||
long double size = (long double) bytes;
|
||||
uint8_t counter = 0;
|
||||
|
||||
while(size > base && counter < prefixesLength - 1)
|
||||
while(size >= base && counter < prefixesLength - 1)
|
||||
{
|
||||
size /= base;
|
||||
counter++;
|
||||
@@ -164,3 +170,7 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
ffStrbufAppendS(buffer, " [GTK4]");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#ifndef FF_INCLUDED_parsing_h
|
||||
#define FF_INCLUDED_parsing_h
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct FFVersion
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -30,9 +30,20 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
|
||||
//Parent
|
||||
close(pipes[1]);
|
||||
waitpid(childPid, NULL, 0);
|
||||
bool ok = ffAppendFDBuffer(pipes[0], buffer);
|
||||
close(pipes[0]);
|
||||
|
||||
return ok ? NULL : "ffAppendFDBuffer() failed";
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
int status = -1;
|
||||
if(waitpid(childPid, &status, 0) < 0)
|
||||
return "waitpid(childPid, &status, 0) failed";
|
||||
|
||||
if (!WIFEXITED(status))
|
||||
return "WIFEXITED(status) == false";
|
||||
|
||||
if(WEXITSTATUS(status) == 901)
|
||||
return "WEXITSTATUS(status) == 901 ( execvp failed )";
|
||||
|
||||
if(!ffAppendFDBuffer(childPipeFd, buffer))
|
||||
return "ffAppendFDBuffer(childPipeFd, buffer) failed";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
|
||||
@@ -166,10 +166,10 @@ bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uin
|
||||
FFstrbuf baseDir;
|
||||
ffStrbufInitA(&baseDir, 64);
|
||||
|
||||
for(uint32_t i = 0; i < list->length; i++)
|
||||
FF_LIST_FOR_EACH(FFstrbuf, dirPrefix, *list)
|
||||
{
|
||||
//We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it.
|
||||
ffStrbufSet(&baseDir, ffListGet(list, i));
|
||||
ffStrbufSet(&baseDir, dirPrefix);
|
||||
ffStrbufAppendS(&baseDir, relativeFile);
|
||||
|
||||
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
|
||||
|
||||
+61
-10
@@ -2,7 +2,7 @@
|
||||
#include "common/settings.h"
|
||||
#include "common/library.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -57,23 +57,31 @@ typedef enum FFInitState
|
||||
|
||||
typedef struct GVariantGetters
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(g_variant_get_string)
|
||||
FF_LIBRARY_SYMBOL(g_variant_dup_string)
|
||||
FF_LIBRARY_SYMBOL(g_variant_get_boolean)
|
||||
FF_LIBRARY_SYMBOL(g_variant_get_int32)
|
||||
FF_LIBRARY_SYMBOL(g_variant_unref)
|
||||
} GVariantGetters;
|
||||
|
||||
static FFvariant getGVariantValue(GVariant* variant, FFvarianttype type, const GVariantGetters* variantGetters)
|
||||
{
|
||||
FFvariant result;
|
||||
|
||||
if(variant == NULL)
|
||||
return FF_VARIANT_NULL;
|
||||
result = FF_VARIANT_NULL;
|
||||
else if(type == FF_VARIANT_TYPE_STRING)
|
||||
return (FFvariant) {.strValue = variantGetters->ffg_variant_get_string(variant, NULL)};
|
||||
result = (FFvariant) {.strValue = variantGetters->ffg_variant_dup_string(variant, NULL)}; // Dup string, so that variant itself can be freed
|
||||
else if(type == FF_VARIANT_TYPE_BOOL)
|
||||
return (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true};
|
||||
result = (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true};
|
||||
else if(type == FF_VARIANT_TYPE_INT)
|
||||
return (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)};
|
||||
result = (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)};
|
||||
else
|
||||
return FF_VARIANT_NULL;
|
||||
result = FF_VARIANT_NULL;
|
||||
|
||||
if(variant)
|
||||
variantGetters->ffg_variant_unref(variant);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct GSettingsData
|
||||
@@ -102,9 +110,10 @@ static const GSettingsData* getGSettingsData(const FFinstance* instance)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_get_default)
|
||||
|
||||
#define data data.variantGetters
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_dup_string)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_unref);
|
||||
#undef data
|
||||
|
||||
data.schemaSource = data.ffg_settings_schema_source_get_default();
|
||||
@@ -169,7 +178,7 @@ static const DConfData* getDConfData(const FFinstance* instance)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
|
||||
|
||||
#define data data.variantGetters
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_dup_string)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
|
||||
#undef data
|
||||
@@ -288,6 +297,7 @@ typedef struct SQLiteData
|
||||
FF_LIBRARY_SYMBOL(sqlite3_step)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_data_count)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_column_int)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_column_text)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_finalize)
|
||||
FF_LIBRARY_SYMBOL(sqlite3_close)
|
||||
} SQLiteData;
|
||||
@@ -301,6 +311,7 @@ static const SQLiteData* getSQLiteData(const FFinstance* instance)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_step)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_data_count)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_int)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_text)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_finalize)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_close)
|
||||
|
||||
@@ -309,7 +320,7 @@ static const SQLiteData* getSQLiteData(const FFinstance* instance)
|
||||
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
|
||||
{
|
||||
if(!ffFileExists(dbPath, S_IFREG))
|
||||
if(!ffPathExists(dbPath, FF_PATHTYPE_FILE))
|
||||
return 0;
|
||||
|
||||
const SQLiteData* data = getSQLiteData(instance);
|
||||
@@ -341,12 +352,52 @@ int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, cons
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ffSettingsGetSQLite3String(const FFinstance* instance, const char* dbPath, const char* query, FFstrbuf* result)
|
||||
{
|
||||
if(!ffPathExists(dbPath, FF_PATHTYPE_FILE))
|
||||
return false;
|
||||
|
||||
const SQLiteData* data = getSQLiteData(instance);
|
||||
if(data == NULL)
|
||||
return false;
|
||||
|
||||
sqlite3* db;
|
||||
if(data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
|
||||
return false;
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
if(data->ffsqlite3_prepare_v2(db, query, (int) strlen(query), &stmt, NULL) != SQLITE_OK)
|
||||
{
|
||||
data->ffsqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(data->ffsqlite3_step(stmt) != SQLITE_ROW || data->ffsqlite3_data_count(stmt) < 1)
|
||||
{
|
||||
data->ffsqlite3_finalize(stmt);
|
||||
data->ffsqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
ffStrbufSetS(result, (const char *) data->ffsqlite3_column_text(stmt, 0));
|
||||
|
||||
data->ffsqlite3_finalize(stmt);
|
||||
data->ffsqlite3_close(db);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else //FF_HAVE_SQLITE3
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
|
||||
{
|
||||
FF_UNUSED(instance, dbPath, query)
|
||||
return 0;
|
||||
}
|
||||
bool ffSettingsGetSQLite3String(const FFinstance* instance, const char* dbPath, const char* query, FFstrbuf* result)
|
||||
{
|
||||
FF_UNUSED(instance, dbPath, query, result)
|
||||
return false;
|
||||
}
|
||||
#endif //FF_HAVE_SQLITE3
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
@@ -31,6 +31,7 @@ FFvariant ffSettingsGet(const FFinstance* instance, const char* dconfKey, const
|
||||
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type);
|
||||
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
|
||||
bool ffSettingsGetSQLite3String(const FFinstance* instance, const char* dbPath, const char* query, FFstrbuf* result);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
}
|
||||
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; }
|
||||
static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); }
|
||||
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, INFINITE); }
|
||||
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, 0xffffffff /*INFINITE*/); }
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
@@ -168,13 +168,13 @@
|
||||
# Sets the URL of public IP detection server to be used.
|
||||
# Only HTTP protocol is supported, and the value should not contain "http://" prefix.
|
||||
# Default is "ipinfo.io/ip".
|
||||
#--public-ip-url "ipinfo.io/ip"
|
||||
#--publicip-url "ipinfo.io/ip"
|
||||
|
||||
# Public IP timeout option:
|
||||
# Sets the time to wait for the public ip server to respond.
|
||||
# Must be a positive integer.
|
||||
# Default is 0 (disabled).
|
||||
#--public-ip-timeout 0
|
||||
#--publicip-timeout 0
|
||||
|
||||
# Weather output format option:
|
||||
# Sets the weather format to be used. It must be URI encoded.
|
||||
@@ -219,6 +219,13 @@
|
||||
#--gpu-hide-integrated
|
||||
#--gpu-hide-discrete
|
||||
|
||||
# GPU detection options
|
||||
# Forces using vulkan to detect GPUs
|
||||
# which support video memory usage detection with `--allow-slow-operations`
|
||||
# Must be either true or false
|
||||
# Default is false.
|
||||
#--gpu-force-vulkan
|
||||
|
||||
# Shell option
|
||||
# Sets if shell version should be detected and printed
|
||||
# Must be either true or false
|
||||
@@ -247,10 +254,40 @@
|
||||
# Default is "/:/home" ("C:\\;D:\\ ..." on Windows).
|
||||
#--disk-folders /:/home
|
||||
|
||||
# Bluetooth show disconnected option
|
||||
# Sets if disconnected bluetooth devices should be printed
|
||||
# Must be either true or false
|
||||
# Default is false.
|
||||
#--bluetooth-show-disconnected false
|
||||
|
||||
# Display compact output option
|
||||
# Sets if all displays should be printed in one line
|
||||
# Must be either original (print pixel resolution) or scaled (print scaled resolution)
|
||||
# Default is none.
|
||||
#--display-compact-type none
|
||||
|
||||
# Display detect name option
|
||||
# Sets if display name should be detected and printed (if supported)
|
||||
# Must be either true of false
|
||||
# Default is false.
|
||||
#--display-detect-name none
|
||||
|
||||
# Display precise refresh rate option
|
||||
# Sets if decimal refresh rates should not be rounded into integers when printing
|
||||
# Must be either true (keep decimals) of false (round into integers)
|
||||
# Default is false.
|
||||
#--display-precise-refresh-rate false
|
||||
|
||||
# Sound show all option
|
||||
# Sets if all sound devices should be printed
|
||||
# Must be either main, active or all. Default is main
|
||||
# Default is main.
|
||||
#--sound-type main
|
||||
|
||||
# Percentage output type option
|
||||
# Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported.
|
||||
# Only works with default format ( without --module-format option ).
|
||||
# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar; 6: prints bar and hide other texts
|
||||
# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar; 6: prints bar and hide other texts; 9: prints colored number
|
||||
#--percent-type 1
|
||||
|
||||
# Key options:
|
||||
@@ -284,8 +321,8 @@
|
||||
#--battery-key Battery {1}
|
||||
#--poweradapter-key Power Adapter {1}
|
||||
#--locale-key Locale
|
||||
#--local-ip-key Local IP ({1})
|
||||
#--public-ip-key Public IP
|
||||
#--localip-key Local IP ({1})
|
||||
#--publicip-key Public IP
|
||||
#--wifi-key Wifi
|
||||
#--weather-key Weather
|
||||
#--player-key Media Player
|
||||
@@ -295,6 +332,10 @@
|
||||
#--opengl-key OpenGL
|
||||
#--opencl-key OpenCL
|
||||
#--users-key Users
|
||||
#--bluetooth-key Bluetooth
|
||||
#--sound-key Sound
|
||||
#--gamepad-key Gamepad
|
||||
#--wallpaper-key Wallpaper
|
||||
|
||||
# Format options:
|
||||
# Sets the format string for module values.
|
||||
@@ -329,8 +370,8 @@
|
||||
#--battery-format
|
||||
#--poweradapter-format
|
||||
#--locale-format
|
||||
#--local-ip-format
|
||||
#--public-ip-format
|
||||
#--localip-format
|
||||
#--publicip-format
|
||||
#--weather-format
|
||||
#--player-format
|
||||
#--media-format
|
||||
@@ -339,6 +380,10 @@
|
||||
#--opengl-format
|
||||
#--opencl-format
|
||||
#--users-format
|
||||
#--bluetooth-format
|
||||
#--sound-format
|
||||
#--gamepad-format
|
||||
#--wallpaper-format
|
||||
|
||||
# Error options:
|
||||
# Sets the format string to use if an error occured
|
||||
@@ -373,8 +418,8 @@
|
||||
#--battery-error
|
||||
#--poweradapter-error
|
||||
#--locale-error
|
||||
#--local-ip-error
|
||||
#--public-ip-error
|
||||
#--localip-error
|
||||
#--publicip-error
|
||||
#--weather-error
|
||||
#--player-error
|
||||
#--media-error
|
||||
@@ -383,6 +428,10 @@
|
||||
#--opengl-error
|
||||
#--opencl-error
|
||||
#--users-error
|
||||
#--bluetooth-error
|
||||
#--sound-error
|
||||
#--gamepad-error
|
||||
#--wallpaper-error
|
||||
|
||||
# Library options:
|
||||
# Sets an user specific path to a library to load.
|
||||
@@ -409,3 +458,4 @@
|
||||
#--lib-opencl /usr/lib/libOpenCL.so
|
||||
#--lib-cjson /usr/lib/libcjson.so
|
||||
#--lib-freetype /data/data/com.termux/files/usr/lib
|
||||
#--lib-pulse /usr/lib/libpulse.so
|
||||
|
||||
+41
-30
@@ -98,38 +98,49 @@ Library options: Set the path of a library to load
|
||||
--lib-osmesa <path>
|
||||
--lib-opencl <path>
|
||||
--lib-cjson <path>
|
||||
--lib-pulse <path>
|
||||
--lib-freetype <path>
|
||||
|
||||
Module specific options:
|
||||
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS information
|
||||
--shell-version <?value>: Set if shell version should be detected and printed
|
||||
--terminal-version <?value>: Set if terminal version should be detected and printed
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
|
||||
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
|
||||
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-hide-integrated <?value>: Hide integrated GPU if supported. Default is false
|
||||
--gpu-hide-discrete <?value>: Hide discrete GPU if supported. Default is false
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
|
||||
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--public-ip-url: The URL of public IP detection server to be used.
|
||||
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||
--player-name: The name of the player to use
|
||||
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others
|
||||
--command-key <str>: Set the module key to display, can be specified mulitple times
|
||||
--command-text <str>: Set the command text to be executed, can be specified mulitple times
|
||||
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS information
|
||||
--shell-version <?value>: Set if shell version should be detected and printed
|
||||
--terminal-version <?value>: Set if terminal version should be detected and printed
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-show-regular <?value>: Set if regular volume should be printed. Default is true
|
||||
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
|
||||
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
|
||||
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
|
||||
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
|
||||
--display-compact-type: <?string>: Set if all displays should be printed in one line. Default is none
|
||||
--display-detect-name: <?value>: Set if display name should be detected and printed (if supported). Default is false
|
||||
--display-precise-refresh-rate: <?value>:Set if decimal refresh rates should not be rounded into integers when printing
|
||||
--sound-type: <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
|
||||
--gpu-hide-integrated <?value>: Hide integrated GPU if supported. Default is false
|
||||
--gpu-hide-discrete <?value>: Hide discrete GPU if supported. Default is false
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
|
||||
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
|
||||
--localip-show-mac <?value>: Show mac addresses in local ip module. Default is false
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
|
||||
--localip-compact <?value>: Show all IPs in one line. Default is false
|
||||
--publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--publicip-url: The URL of public IP detection server to be used.
|
||||
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||
--player-name: The name of the player to use
|
||||
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others
|
||||
--command-key <str>: Set the module key to display, can be specified mulitple times
|
||||
--command-text <str>: Set the command text to be executed, can be specified mulitple times
|
||||
|
||||
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||
If a value starts with a ?, it is optional. "true" will be used if not set.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Battery
|
||||
Bios
|
||||
Bluetooth
|
||||
Board
|
||||
Break
|
||||
Chassis
|
||||
|
||||
@@ -4,16 +4,23 @@
|
||||
#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 "BatteryStatus"
|
||||
|
||||
const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer;
|
||||
ffStrbufInit(&buffer);
|
||||
|
||||
if(ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api",
|
||||
"BatteryStatus"
|
||||
FF_TERMUX_API_PATH,
|
||||
FF_TERMUX_API_PARAM,
|
||||
NULL
|
||||
}))
|
||||
return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " BatteryStatus` failed";
|
||||
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
|
||||
|
||||
if(buffer.chars[0] != '{')
|
||||
return "`" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` prints invalid result (not a JSON object)";
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
@@ -28,6 +35,17 @@ const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* re
|
||||
ffStrbufClear(&battery->status);
|
||||
}
|
||||
|
||||
if(instance->config.batteryTemp)
|
||||
{
|
||||
if(ffParsePropLines(buffer.chars, "\"temperature\": ", &battery->status))
|
||||
{
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
ffStrbufTrim(&battery->status, '"');
|
||||
battery->temperature = ffStrbufToDouble(&battery->status);
|
||||
ffStrbufClear(&battery->status);
|
||||
}
|
||||
}
|
||||
|
||||
if(ffParsePropLines(buffer.chars, "\"status\": ", &battery->status))
|
||||
{
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "battery.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
@@ -2,11 +2,22 @@
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <batclass.h>
|
||||
#include <devguid.h>
|
||||
#include <winternl.h>
|
||||
#include <powrprof.h>
|
||||
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtPowerInformation(
|
||||
IN POWER_INFORMATION_LEVEL InformationLevel,
|
||||
IN PVOID InputBuffer OPTIONAL,
|
||||
IN ULONG InputBufferLength,
|
||||
OUT PVOID OutputBuffer OPTIONAL,
|
||||
IN ULONG OutputBufferLength);
|
||||
|
||||
static inline void wrapCloseHandle(HANDLE* handle)
|
||||
{
|
||||
@@ -133,7 +144,7 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
else
|
||||
{
|
||||
SYSTEM_BATTERY_STATE info;
|
||||
if (NT_SUCCESS(CallNtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
|
||||
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
|
||||
{
|
||||
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "bios.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth);
|
||||
|
||||
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFBluetoothResult,
|
||||
ffStrbufInit(&result.error);
|
||||
ffListInit(&result.devices, sizeof(FFBluetoothDevice));
|
||||
|
||||
ffDetectBluetoothImpl(instance, &result);
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_bluetooth_bluetooth
|
||||
#define FF_INCLUDED_detection_bluetooth_bluetooth
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBluetoothDevice
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf address;
|
||||
FFstrbuf type;
|
||||
uint8_t battery; // 0-100%
|
||||
bool connected;
|
||||
} FFBluetoothDevice;
|
||||
|
||||
typedef struct FFBluetoothResult
|
||||
{
|
||||
FFstrbuf error;
|
||||
FFlist devices; // List of FFBluetoothDevice
|
||||
} FFBluetoothResult;
|
||||
|
||||
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#import <IOBluetooth/IOBluetooth.h>
|
||||
|
||||
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
|
||||
if(!ioDevices)
|
||||
{
|
||||
ffStrbufAppendS(&bluetooth->error, "IOBluetoothDevice.pairedDevices failed");
|
||||
return;
|
||||
}
|
||||
|
||||
for(IOBluetoothDevice* ioDevice in ioDevices)
|
||||
{
|
||||
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
||||
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
|
||||
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = !!ioDevice.isConnected;
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode)
|
||||
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved1)
|
||||
ffStrbufAppendS(&device->type, "LE audio, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved2)
|
||||
ffStrbufAppendS(&device->type, "Reserved for future use, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorPositioning)
|
||||
ffStrbufAppendS(&device->type, "Positioning, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorNetworking)
|
||||
ffStrbufAppendS(&device->type, "Networking, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorRendering)
|
||||
ffStrbufAppendS(&device->type, "Rendering, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorCapturing)
|
||||
ffStrbufAppendS(&device->type, "Capturing, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorObjectTransfer)
|
||||
ffStrbufAppendS(&device->type, "Object Transfer, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorAudio)
|
||||
ffStrbufAppendS(&device->type, "Audio, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorTelephony)
|
||||
ffStrbufAppendS(&device->type, "Telephony, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorInformation)
|
||||
ffStrbufAppendS(&device->type, "Information, ");
|
||||
|
||||
if(device->type.length == 0)
|
||||
{
|
||||
switch(ioDevice.deviceClassMajor)
|
||||
{
|
||||
case kBluetoothDeviceClassMajorMiscellaneous:
|
||||
ffStrbufAppendS(&device->type, "Miscellaneous");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorComputer:
|
||||
ffStrbufAppendS(&device->type, "Computer");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorPhone:
|
||||
ffStrbufAppendS(&device->type, "Phone");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorLANAccessPoint:
|
||||
ffStrbufAppendS(&device->type, "LAN/Network Access point");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorAudio:
|
||||
ffStrbufAppendS(&device->type, "Audio/Video");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorPeripheral:
|
||||
ffStrbufAppendS(&device->type, "Peripheral");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorImaging:
|
||||
ffStrbufAppendS(&device->type, "Imaging");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorWearable:
|
||||
ffStrbufAppendS(&device->type, "Wearable");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorToy:
|
||||
ffStrbufAppendS(&device->type, "Toy");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorHealth:
|
||||
ffStrbufAppendS(&device->type, "Health");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorUnclassified:
|
||||
ffStrbufAppendS(&device->type, "Uncategorized");
|
||||
break;
|
||||
default:
|
||||
ffStrbufAppendS(&device->type, "Unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufTrimRight(&device->type, ' ');
|
||||
ffStrbufTrimRight(&device->type, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include "common/dbus.h"
|
||||
|
||||
/* Example dbus reply, striped to only the relevant parts:
|
||||
array [ //root
|
||||
dict entry( //object
|
||||
object path "/org/bluez/hci0/dev_03_21_8B_91_16_4D"
|
||||
array [
|
||||
dict entry( //property
|
||||
string "org.bluez.Device1"
|
||||
array [
|
||||
dict entry( //value
|
||||
string "Address"
|
||||
variant string "03:21:8B:91:16:4D"
|
||||
)
|
||||
dict entry( //value
|
||||
string "Name"
|
||||
variant string "JBL TUNE160BT"
|
||||
)
|
||||
dict entry( //value
|
||||
string "Icon"
|
||||
variant string "audio-headset"
|
||||
)
|
||||
dict entry( //value
|
||||
string "Connected"
|
||||
variant boolean true
|
||||
)
|
||||
]
|
||||
)
|
||||
dict entry( //property
|
||||
string "org.bluez.Battery1"
|
||||
array [
|
||||
dict entry( //value
|
||||
string "Percentage"
|
||||
variant byte 100
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
*/
|
||||
|
||||
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
|
||||
const char* deviceProperty;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(strcmp(deviceProperty, "Address") == 0)
|
||||
ffDBusGetValue(dbus, &dictIter, &device->address);
|
||||
else if(strcmp(deviceProperty, "Name") == 0)
|
||||
ffDBusGetValue(dbus, &dictIter, &device->name);
|
||||
else if(strcmp(deviceProperty, "Icon") == 0)
|
||||
ffDBusGetValue(dbus, &dictIter, &device->type);
|
||||
else if(strcmp(deviceProperty, "Percentage") == 0)
|
||||
ffDBusGetByte(dbus, &dictIter, &device->battery);
|
||||
else if(strcmp(deviceProperty, "Connected") == 0)
|
||||
ffDBusGetBool(dbus, &dictIter, &device->connected);
|
||||
}
|
||||
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
|
||||
const char* propertyType;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
|
||||
|
||||
if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL)
|
||||
return; //We don't care about other properties
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothValue(dbus, &arrayIter, device);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
}
|
||||
|
||||
static void detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
|
||||
return;
|
||||
|
||||
const char* objectPath;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
|
||||
|
||||
//We don't want adapter objects
|
||||
if(strstr(objectPath, "dev_") == NULL)
|
||||
return;
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothProperty(dbus, &arrayIter, device);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
|
||||
if(device->name.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
ffStrbufDestroy(&device->address);
|
||||
ffStrbufDestroy(&device->type);
|
||||
--bluetooth->devices.length;
|
||||
}
|
||||
}
|
||||
|
||||
static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothObject(bluetooth, dbus, &arrayIter);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* detectBluetooth(const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
FFDBusData dbus;
|
||||
const char* error = ffDBusLoadData(instance, DBUS_BUS_SYSTEM, &dbus);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
|
||||
if(!managedObjects)
|
||||
return "Failed to call GetManagedObjects";
|
||||
|
||||
DBusMessageIter rootIter;
|
||||
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return "Failed to get root iterator of GetManagedObjects";
|
||||
}
|
||||
|
||||
detectBluetoothRoot(bluetooth, &dbus, &rootIter);
|
||||
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
ffStrbufAppendS(&bluetooth->error, detectBluetooth(instance, bluetooth));
|
||||
#else
|
||||
FF_UNUSED(instance);
|
||||
ffStrbufAppendS(&bluetooth->error, "Fastfetch was compiled without DBus support");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
ffStrbufAppendS(&bluetooth->error, "Bluetooth not supported on this platform");
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#include "bluetooth.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <bluetoothapis.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-sign"
|
||||
|
||||
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = {
|
||||
.fReturnConnected = TRUE,
|
||||
.fReturnRemembered = TRUE,
|
||||
.fReturnAuthenticated = TRUE,
|
||||
.fReturnUnknown = TRUE,
|
||||
.dwSize = sizeof(btsp)
|
||||
};
|
||||
|
||||
BLUETOOTH_DEVICE_INFO btdi = {
|
||||
.dwSize = sizeof(btdi)
|
||||
};
|
||||
HBLUETOOTH_DEVICE_FIND hFind = BluetoothFindFirstDevice(&btsp, &btdi);
|
||||
if(!hFind)
|
||||
ffStrbufAppendS(&bluetooth->error, "BluetoothFindFirstDevice() failed or no devices found");
|
||||
|
||||
do {
|
||||
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = !!btdi.fConnected;
|
||||
|
||||
ffStrbufSetWS(&device->name, btdi.szName);
|
||||
for (uint32_t i = 0; i < sizeof(btdi.Address.rgBytes) / sizeof(btdi.Address.rgBytes); ++i)
|
||||
ffStrbufAppendF(&device->address, "%X:", btdi.Address.rgBytes[i]);
|
||||
ffStrbufTrimRight(&device->name, ':');
|
||||
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
|
||||
|
||||
if(BitTest(&btdi.ulClassofDevice, 13))
|
||||
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 14))
|
||||
ffStrbufAppendS(&device->type, "LE audio, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 15))
|
||||
ffStrbufAppendS(&device->type, "Reserved for future use, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 16))
|
||||
ffStrbufAppendS(&device->type, "Positioning, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 17))
|
||||
ffStrbufAppendS(&device->type, "Networking, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 18))
|
||||
ffStrbufAppendS(&device->type, "Rendering, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 19))
|
||||
ffStrbufAppendS(&device->type, "Capturing, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 20))
|
||||
ffStrbufAppendS(&device->type, "Object Transfer, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 21))
|
||||
ffStrbufAppendS(&device->type, "Audio, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 22))
|
||||
ffStrbufAppendS(&device->type, "Telephony, ");
|
||||
if(BitTest(&btdi.ulClassofDevice, 23))
|
||||
ffStrbufAppendS(&device->type, "Information, ");
|
||||
|
||||
if(device->type.length == 0)
|
||||
{
|
||||
uint32_t majorDeviceClasses = (btdi.ulClassofDevice >> 8) & ~(UINT32_MAX << 5);
|
||||
switch(majorDeviceClasses)
|
||||
{
|
||||
case 0b00000:
|
||||
ffStrbufAppendS(&device->type, "Miscellaneous");
|
||||
break;
|
||||
case 0b00001:
|
||||
ffStrbufAppendS(&device->type, "Computer");
|
||||
break;
|
||||
case 0b00010:
|
||||
ffStrbufAppendS(&device->type, "Phone");
|
||||
break;
|
||||
case 0b00011:
|
||||
ffStrbufAppendS(&device->type, "LAN/Network Access point");
|
||||
break;
|
||||
case 0b00100:
|
||||
ffStrbufAppendS(&device->type, "Audio/Video");
|
||||
break;
|
||||
case 0b00101:
|
||||
ffStrbufAppendS(&device->type, "Peripheral");
|
||||
break;
|
||||
case 0b00110:
|
||||
ffStrbufAppendS(&device->type, "Imaging");
|
||||
break;
|
||||
case 0b00111:
|
||||
ffStrbufAppendS(&device->type, "Wearable");
|
||||
break;
|
||||
case 0b01000:
|
||||
ffStrbufAppendS(&device->type, "Toy");
|
||||
break;
|
||||
case 0b01001:
|
||||
ffStrbufAppendS(&device->type, "Health");
|
||||
break;
|
||||
case 0b11111:
|
||||
ffStrbufAppendS(&device->type, "Uncategorized");
|
||||
break;
|
||||
default:
|
||||
ffStrbufAppendS(&device->type, "Unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufTrimRight(&device->type, ' ');
|
||||
ffStrbufTrimRight(&device->type, ',');
|
||||
}
|
||||
} while (BluetoothFindNextDevice(hFind, &btdi));
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "board.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "brightness.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
|
||||
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
{
|
||||
@@ -22,11 +24,27 @@ const char* ffDetectBrightness(FFlist* result)
|
||||
continue;
|
||||
|
||||
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
|
||||
if(CGDisplayIsBuiltin(screen))
|
||||
ffStrbufInitS(&display->name, "built-in");
|
||||
else
|
||||
ffStrbufInitF(&display->name, "external-%u", (unsigned) screen);
|
||||
display->value = brightness * 100;
|
||||
ffStrbufInit(&display->name);
|
||||
|
||||
if(CoreDisplay_DisplayCreateInfoDictionary)
|
||||
{
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
|
||||
if(displayInfo)
|
||||
{
|
||||
CFDictionaryRef productNames;
|
||||
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
|
||||
{
|
||||
if(!ffCfDictGetString(productNames, CFSTR("en_US"), &display->name))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(CGDisplayIsBuiltin(screen))
|
||||
ffStrbufAppendS(&display->name, "built-in");
|
||||
else
|
||||
ffStrbufAppendF(&display->name, "external-%u", (unsigned) screen);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "brightness.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
@@ -12,13 +13,13 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
if(dirp == NULL)
|
||||
return "Failed to open `/sys/class/backlight/`";
|
||||
|
||||
FFstrbuf backlightDir;
|
||||
FF_STRBUF_AUTO_DESTROY backlightDir;
|
||||
ffStrbufInitA(&backlightDir, 64);
|
||||
ffStrbufAppendS(&backlightDir, backlightDirPath);
|
||||
|
||||
uint32_t backlightDirLength = backlightDir.length;
|
||||
|
||||
FFstrbuf buffer;
|
||||
FF_STRBUF_AUTO_DESTROY buffer;
|
||||
ffStrbufInit(&buffer);
|
||||
|
||||
struct dirent* entry;
|
||||
@@ -38,18 +39,26 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
if(ffReadFileBuffer(backlightDir.chars, &buffer))
|
||||
{
|
||||
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&display->name, entry->d_name);
|
||||
ffStrbufSubstrBeforeLastC(&backlightDir, '/');
|
||||
ffStrbufAppendS(&backlightDir, "/device");
|
||||
ffStrbufInitA(&display->name, PATH_MAX + 1);
|
||||
if(realpath(backlightDir.chars, display->name.chars))
|
||||
{
|
||||
ffStrbufRecalculateLength(&display->name);
|
||||
ffStrbufSubstrAfterLastC(&display->name, '/');
|
||||
if(ffStrbufStartsWithS(&display->name, "card") && isdigit(display->name.chars[4]))
|
||||
ffStrbufSubstrAfterFirstC(&display->name, '-');
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&display->name, entry->d_name);
|
||||
double maxBrightness = ffStrbufToDouble(&buffer);
|
||||
display->value = (float) (actualBrightness * 100 / maxBrightness);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
ffStrbufDestroy(&backlightDir);
|
||||
ffStrbufDestroy(&buffer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "chassis.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "cpu.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
|
||||
@@ -131,7 +131,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
|
||||
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
|
||||
if(ffFileExists(BP, S_IFDIR))
|
||||
if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY))
|
||||
{
|
||||
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
|
||||
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "cpu.h"
|
||||
#include "detection/temps/temps_windows.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
@@ -14,25 +15,28 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||
|
||||
{
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
|
||||
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||
pLogicalInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
|
||||
if(pLogicalInfo && GetLogicalProcessorInformationEx(RelationProcessorCore, pLogicalInfo, &length))
|
||||
if(pProcessorInfo && GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
|
||||
{
|
||||
for(
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pLogicalInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pLogicalInfo) + length;
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
{
|
||||
if(ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if(ptr->Relationship == RelationGroup)
|
||||
{
|
||||
cpu->coresOnline += ptr->Group.GroupInfo->ActiveProcessorCount;
|
||||
cpu->coresLogical += ptr->Group.GroupInfo->MaximumProcessorCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cpu->coresOnline = (uint16_t)GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||
cpu->coresLogical = (uint16_t)GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
|
||||
|
||||
FF_HKEY_AUTO_DESTROY hKey;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||
@@ -46,4 +50,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
|
||||
if(instance->config.cpuTemp)
|
||||
ffDetectSmbiosTemp(&cpu->temperature, NULL);
|
||||
}
|
||||
|
||||
@@ -6,23 +6,18 @@
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
{
|
||||
natural_t numCPUs = 0U;
|
||||
processor_info_array_t cpuInfo;
|
||||
mach_msg_type_number_t numCpuInfo;
|
||||
host_cpu_load_info_data_t cpustats;
|
||||
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
|
||||
|
||||
*inUseAll = *totalAll = 0;
|
||||
|
||||
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS)
|
||||
return "host_processor_info() failed";
|
||||
if (numCPUs * CPU_STATE_MAX != numCpuInfo)
|
||||
return "Unexpected host_processor_info() result";
|
||||
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)(&cpustats), &count) != KERN_SUCCESS)
|
||||
return "host_statistics() failed";
|
||||
|
||||
*inUseAll = cpustats.cpu_ticks[CPU_STATE_USER]
|
||||
+ cpustats.cpu_ticks[CPU_STATE_SYSTEM]
|
||||
+ cpustats.cpu_ticks[CPU_STATE_NICE];
|
||||
*totalAll = *inUseAll + cpustats.cpu_ticks[CPU_STATE_IDLE];
|
||||
|
||||
for (natural_t i = 0U; i < numCPUs; ++i) {
|
||||
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER]
|
||||
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
|
||||
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
|
||||
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
|
||||
*inUseAll += (uint64_t)inUse;
|
||||
*totalAll += (uint64_t)total;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "cpuUsage.h"
|
||||
|
||||
#ifdef FF_USE_WIN_NTAPI
|
||||
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <ntstatus.h>
|
||||
@@ -37,26 +35,3 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <processthreadsapi.h>
|
||||
|
||||
static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
|
||||
return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime);
|
||||
}
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
{
|
||||
FILETIME idleTime, kernelTime, userTime;
|
||||
if(!GetSystemTimes(&idleTime, &kernelTime, &userTime))
|
||||
return "GetSystemTimes() failed";
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes
|
||||
// `kernelTime` also includes the amount of time the system has been idle.
|
||||
*totalAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
|
||||
*inUseAll = *totalAll - fileTimeToUint64(&idleTime);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "cursor.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
static void appendColor(FFstrbuf* str, NSDictionary* color)
|
||||
{
|
||||
int r = (int) (((NSNumber*) [color valueForKey:@"red"]).doubleValue * 255);
|
||||
int g = (int) (((NSNumber*) [color valueForKey:@"green"]).doubleValue * 255);
|
||||
int b = (int) (((NSNumber*) [color valueForKey:@"blue"]).doubleValue * 255);
|
||||
int a = (int) (((NSNumber*) [color valueForKey:@"alpha"]).doubleValue * 255);
|
||||
|
||||
if (r == 255 && g == 255 && b == 255 && a == 255)
|
||||
ffStrbufAppendS(str, "White");
|
||||
else if (r == 0 && g == 0 && b == 0 && a == 255)
|
||||
ffStrbufAppendS(str, "Black");
|
||||
else
|
||||
ffStrbufAppendF(str, "#%02X%02X%02X%02X", r, g, b, a);
|
||||
}
|
||||
|
||||
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
|
||||
{
|
||||
NSError* error;
|
||||
NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.apple.universalaccess.plist", instance->state.platform.homeDir.chars];
|
||||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
|
||||
error:&error];
|
||||
if(error)
|
||||
{
|
||||
ffStrbufAppendS(&result->error, error.localizedDescription.UTF8String);
|
||||
return;
|
||||
}
|
||||
|
||||
NSDictionary* color;
|
||||
|
||||
ffStrbufAppendS(&result->theme, "Fill - ");
|
||||
if ((color = [dict valueForKey:@"cursorFill"]))
|
||||
appendColor(&result->theme, color);
|
||||
else
|
||||
ffStrbufAppendS(&result->theme, "Black");
|
||||
|
||||
ffStrbufAppendS(&result->theme, ", Outline - ");
|
||||
|
||||
if ((color = [dict valueForKey:@"cursorOutline"]))
|
||||
appendColor(&result->theme, color);
|
||||
else
|
||||
ffStrbufAppendS(&result->theme, "White");
|
||||
|
||||
NSNumber* mouseDriverCursorSize = [dict valueForKey:@"mouseDriverCursorSize"];
|
||||
if (mouseDriverCursorSize)
|
||||
ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32));
|
||||
else
|
||||
ffStrbufAppendS(&result->size, "32");
|
||||
}
|
||||
@@ -3,8 +3,9 @@
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/settings.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -72,13 +73,13 @@ void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
|
||||
{
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0)
|
||||
if(ffStrbufCompS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG) == 0)
|
||||
ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
|
||||
detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt"))
|
||||
else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
|
||||
detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
|
||||
else if(
|
||||
!detectCursorGTK(instance, result) &&
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
#include "cursor.h"
|
||||
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
FF_HKEY_AUTO_DESTROY hKey;
|
||||
if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Cursors", &hKey, &result->error))
|
||||
ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error);
|
||||
}
|
||||
#include "cursor.h"
|
||||
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
FF_HKEY_AUTO_DESTROY hKey;
|
||||
if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Cursors", &hKey, &result->error))
|
||||
{
|
||||
if (!ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error))
|
||||
return;
|
||||
|
||||
uint32_t cursorBaseSize;
|
||||
ffRegReadUint(hKey, L"CursorBaseSize", &cursorBaseSize, &result->error);
|
||||
ffStrbufAppendF(&result->size, "%u", (unsigned) cursorBaseSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/datetime.h"
|
||||
#include "detection/datetime/datetime.h"
|
||||
#include "common/thread.h"
|
||||
|
||||
#include <time.h>
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_datetime
|
||||
#define FF_INCLUDED_detection_datetime
|
||||
#ifndef FF_INCLUDED_detection_datetime_datetime
|
||||
#define FF_INCLUDED_detection_datetime_datetime
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
@@ -18,11 +18,18 @@ const FFDiskResult* ffDetectDisks()
|
||||
|
||||
if(result.disks.length == 0 && result.error.length == 0)
|
||||
ffStrbufAppendS(&result.error, "No disks found");
|
||||
|
||||
//We need to sort the disks, so that we can detect, which disk a path resides on
|
||||
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
|
||||
//Note that we sort alphabetically here for a better ordering when printing the list,
|
||||
// so the check must be done in reverse order
|
||||
ffListSort(&result.disks, compareDisks);
|
||||
else
|
||||
{
|
||||
//We need to sort the disks, so that we can detect, which disk a path resides on
|
||||
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
|
||||
//Note that we sort alphabetically here for a better ordering when printing the list,
|
||||
// so the check must be done in reverse order
|
||||
ffListSort(&result.disks, compareDisks);
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, result.disks)
|
||||
{
|
||||
if(disk->bytesTotal == 0)
|
||||
disk->type |= FF_DISK_TYPE_UNKNOWN_BIT;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef enum FFDiskType
|
||||
{
|
||||
FF_DISK_TYPE_REGULAR,
|
||||
FF_DISK_TYPE_HIDDEN,
|
||||
FF_DISK_TYPE_EXTERNAL,
|
||||
FF_DISK_TYPE_SUBVOLUME
|
||||
} FFDiskType;
|
||||
|
||||
typedef struct FFDisk
|
||||
{
|
||||
FFstrbuf mountpoint;
|
||||
|
||||
@@ -7,11 +7,11 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
{
|
||||
// FreeBSD doesn't support these flags
|
||||
if(fs->f_flags & MNT_DONTBROWSE)
|
||||
disk->type = FF_DISK_TYPE_HIDDEN;
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
else if(fs->f_flags & MNT_REMOVABLE)
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_REGULAR;
|
||||
disk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
|
||||
ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/proc") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/zroot")
|
||||
)
|
||||
disk->type = FF_DISK_TYPE_HIDDEN;
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
else if((fs->f_flags & MNT_NOSUID) || !(fs->f_flags & MNT_LOCAL))
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_REGULAR;
|
||||
disk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
|
||||
ffStrbufInit(&disk->name);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "disk.h"
|
||||
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
@@ -13,24 +15,32 @@
|
||||
#define readdir readdir64
|
||||
#endif
|
||||
|
||||
static bool isPhysicalDevice(const char* device)
|
||||
static bool isPhysicalDevice(FFstrbuf* device)
|
||||
{
|
||||
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
|
||||
if(strcmp(device, "drvfs") == 0)
|
||||
if(ffStrbufEqualS(device, "drvfs"))
|
||||
return true;
|
||||
|
||||
//Pseudo filesystems don't have a device in /dev
|
||||
const char* devPrefix = "/dev/";
|
||||
if(strncmp(device, devPrefix, strlen(devPrefix)) != 0)
|
||||
//ZFS root pool. The format is rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>
|
||||
if(ffStrbufStartsWithS(device, "rpool/"))
|
||||
return true;
|
||||
|
||||
struct stat deviceStat;
|
||||
if(stat(device->chars, &deviceStat) != 0)
|
||||
return false;
|
||||
|
||||
//Skip /dev/ prefix
|
||||
device += strlen(devPrefix);
|
||||
//Ignore all devices that are not block devices
|
||||
if(!S_ISBLK(deviceStat.st_mode))
|
||||
return false;
|
||||
|
||||
//Pseudo filesystems don't have a device in /dev
|
||||
if(!ffStrbufStartsWithS(device, "/dev/"))
|
||||
return false;
|
||||
|
||||
if(
|
||||
strncmp(device, "loop", 4) == 0 || //Ignore loop devices
|
||||
strncmp(device, "ram", 3) == 0 || //Ignore ram devices
|
||||
strncmp(device, "fd", 2) == 0 //Ignore fd devices
|
||||
ffStrbufStartsWithS(device, "/dev/loop") || //Ignore loop devices
|
||||
ffStrbufStartsWithS(device, "/dev/ram") || //Ignore ram devices
|
||||
ffStrbufStartsWithS(device, "/dev/fd") //Ignore fd devices
|
||||
) return false;
|
||||
|
||||
return true;
|
||||
@@ -102,7 +112,7 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
if(stat(device->chars, &deviceStat) != 0)
|
||||
return;
|
||||
|
||||
FFstrbuf basePath;
|
||||
FF_STRBUF_AUTO_DESTROY basePath;
|
||||
ffStrbufInit(&basePath);
|
||||
|
||||
//Try partlabel first
|
||||
@@ -119,8 +129,6 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
//Use the mountpoint as a last resort
|
||||
if(disk->name.length == 0)
|
||||
ffStrbufAppend(&disk->name, &disk->mountpoint);
|
||||
|
||||
ffStrbufDestroy(&basePath);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
@@ -128,11 +136,11 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
static void detectType(FF_MAYBE_UNUSED const FFlist* devices, FFDisk* currentDisk, FF_MAYBE_UNUSED const char* options)
|
||||
{
|
||||
if(ffStrbufEqualS(¤tDisk->mountpoint, "/") || ffStrbufEqualS(¤tDisk->mountpoint, "/storage/emulated"))
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR;
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/mnt/media_rw/"))
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN;
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -141,6 +149,7 @@ static bool isSubvolume(const FFlist* devices)
|
||||
{
|
||||
const FFstrbuf* currentDevie = ffListGet(devices, devices->length - 1);
|
||||
|
||||
//Filter all disks which device was already found. This catches BTRFS subvolumes.
|
||||
for(uint32_t i = 0; i < devices->length - 1; i++)
|
||||
{
|
||||
const FFstrbuf* otherDevice = ffListGet(devices, i);
|
||||
@@ -149,19 +158,24 @@ static bool isSubvolume(const FFlist* devices)
|
||||
return true;
|
||||
}
|
||||
|
||||
//ZFS subvolumes: rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>.
|
||||
//Test if the third slash is present.
|
||||
if(strncmp(currentDevie->chars, "rpool/", 6) == 0 && ffStrHasNChars(currentDevie->chars, '/', 3))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options)
|
||||
{
|
||||
if(isSubvolume(devices))
|
||||
currentDisk->type = FF_DISK_TYPE_SUBVOLUME;
|
||||
currentDisk->type = FF_DISK_TYPE_SUBVOLUME_BIT;
|
||||
else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL)
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi"))
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN;
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
else
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR;
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -188,7 +202,7 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
return;
|
||||
}
|
||||
|
||||
FFlist devices;
|
||||
FF_LIST_AUTO_DESTROY devices;
|
||||
ffListInit(&devices, sizeof(FFstrbuf));
|
||||
|
||||
char* line = NULL;
|
||||
@@ -196,12 +210,6 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
|
||||
while(getline(&line, &len, mountsFile) != EOF)
|
||||
{
|
||||
if(!isPhysicalDevice(line))
|
||||
continue;
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(&disks->disks);
|
||||
|
||||
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
|
||||
char* currentPos = line;
|
||||
|
||||
@@ -210,6 +218,16 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
ffStrbufInit(device);
|
||||
appendNextEntry(device, ¤tPos);
|
||||
|
||||
if(!isPhysicalDevice(device))
|
||||
{
|
||||
ffStrbufDestroy(device);
|
||||
devices.length--;
|
||||
continue;
|
||||
}
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(&disks->disks);
|
||||
|
||||
//detect mountpoint
|
||||
ffStrbufInit(&disk->mountpoint);
|
||||
appendNextEntry(&disk->mountpoint, ¤tPos);
|
||||
@@ -234,7 +252,6 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, device, devices)
|
||||
ffStrbufDestroy(device);
|
||||
ffListDestroy(&devices);
|
||||
|
||||
fclose(mountsFile);
|
||||
}
|
||||
|
||||
@@ -1,36 +1,31 @@
|
||||
#include "disk.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
{
|
||||
uint32_t length = GetLogicalDriveStringsA(0, NULL);
|
||||
if(length == 0)
|
||||
{
|
||||
ffStrbufAppendS(&disks->error, "GetLogicalDriveStringsA failed");
|
||||
return;
|
||||
}
|
||||
|
||||
char* buf = malloc(length + 1);
|
||||
GetLogicalDriveStringsA(length, buf);
|
||||
wchar_t buf[MAX_PATH + 1];
|
||||
uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf);
|
||||
assert(length < sizeof(buf) / sizeof(*buf));
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
const char* mountpoint = buf + i;
|
||||
const wchar_t* mountpoint = buf + i;
|
||||
|
||||
UINT driveType = GetDriveTypeA(mountpoint);
|
||||
UINT driveType = GetDriveTypeW(mountpoint);
|
||||
if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
{
|
||||
i += (uint32_t)strlen(mountpoint);
|
||||
i += (uint32_t)wcslen(mountpoint);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFDisk* disk = ffListAdd(&disks->disks);
|
||||
ffStrbufInitS(&disk->mountpoint, mountpoint);
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
|
||||
uint64_t bytesFree;
|
||||
if(!GetDiskFreeSpaceExA(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
|
||||
if(!GetDiskFreeSpaceExW(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
|
||||
{
|
||||
disk->bytesTotal = 0;
|
||||
bytesFree = 0;
|
||||
@@ -38,26 +33,33 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
disk->bytesUsed = disk->bytesTotal - bytesFree;
|
||||
|
||||
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
else if(driveType == DRIVE_FIXED)
|
||||
disk->type = FF_DISK_TYPE_REGULAR;
|
||||
disk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_HIDDEN;
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
|
||||
ffStrbufInit(&disk->filesystem);
|
||||
ffStrbufInit(&disk->name);
|
||||
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
|
||||
|
||||
ffStrbufInitA(&disk->filesystem, MAX_PATH + 1);
|
||||
ffStrbufInitA(&disk->name, MAX_PATH + 1);
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
|
||||
UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
GetVolumeInformationA(mountpoint,
|
||||
disk->name.chars, disk->name.allocated, //Volume name
|
||||
|
||||
BOOL result = GetVolumeInformationW(mountpoint,
|
||||
diskName, sizeof(diskName) / sizeof(*diskName), //Volume name
|
||||
NULL, //Serial number
|
||||
NULL, //Max component length
|
||||
NULL, //File system flags
|
||||
disk->filesystem.chars, disk->filesystem.allocated
|
||||
diskFileSystem, sizeof(diskFileSystem) / sizeof(*diskFileSystem)
|
||||
);
|
||||
SetErrorMode(errorMode);
|
||||
ffStrbufRecalculateLength(&disk->name);
|
||||
ffStrbufRecalculateLength(&disk->filesystem);
|
||||
|
||||
if(result)
|
||||
{
|
||||
ffStrbufSetWS(&disk->filesystem, diskFileSystem);
|
||||
ffStrbufSetWS(&disk->name, diskName);
|
||||
}
|
||||
|
||||
//TODO: implement
|
||||
disk->filesUsed = 0;
|
||||
@@ -65,6 +67,4 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
|
||||
i += disk->mountpoint.length;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
#include "displayserver.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
|
||||
{
|
||||
if(refreshRate <= 0)
|
||||
return 0;
|
||||
|
||||
int remainder = refreshRate % 5;
|
||||
if(remainder >= 3)
|
||||
refreshRate += (5 - remainder);
|
||||
else
|
||||
refreshRate -= remainder;
|
||||
|
||||
//All other typicall refresh rates are dividable by 5
|
||||
if(refreshRate == 145)
|
||||
refreshRate = 144;
|
||||
|
||||
return (uint32_t) refreshRate;
|
||||
}
|
||||
|
||||
bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight)
|
||||
bool ffdsAppendDisplay(
|
||||
FFDisplayServerResult* result,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
double refreshRate,
|
||||
uint32_t scaledWidth,
|
||||
uint32_t scaledHeight,
|
||||
FFstrbuf* name,
|
||||
FFDisplayType type)
|
||||
{
|
||||
if(width == 0 || height == 0)
|
||||
return false;
|
||||
@@ -30,6 +20,8 @@ bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t h
|
||||
display->refreshRate = refreshRate;
|
||||
display->scaledWidth = scaledWidth;
|
||||
display->scaledHeight = scaledHeight;
|
||||
ffStrbufInitMove(&display->name, name);
|
||||
display->type = type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,13 +5,50 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_DE_PRETTY_PLASMA "KDE Plasma"
|
||||
#define FF_DE_PRETTY_GNOME "Gnome"
|
||||
#define FF_DE_PRETTY_XFCE4 "Xfce4"
|
||||
#define FF_DE_PRETTY_CINNAMON "Cinnamon"
|
||||
#define FF_DE_PRETTY_MATE "Mate"
|
||||
#define FF_DE_PRETTY_LXDE "LXDE"
|
||||
#define FF_DE_PRETTY_LXQT "LXQT"
|
||||
#define FF_DE_PRETTY_BUDGIE "Budgie"
|
||||
#define FF_DE_PRETTY_UNITY "Unity"
|
||||
|
||||
#define FF_WM_PRETTY_KWIN "KWin"
|
||||
#define FF_WM_PRETTY_MUTTER "Mutter"
|
||||
#define FF_WM_PRETTY_MUFFIN "Muffin"
|
||||
#define FF_WM_PRETTY_MARCO "Marco"
|
||||
#define FF_WM_PRETTY_XFWM4 "Xfwm4"
|
||||
#define FF_WM_PRETTY_OPENBOX "Openbox"
|
||||
#define FF_WM_PRETTY_I3 "i3"
|
||||
#define FF_WM_PRETTY_WAYFIRE "Wayfire"
|
||||
#define FF_WM_PRETTY_SWAY "Sway"
|
||||
#define FF_WM_PRETTY_BSPWM "bspwm"
|
||||
#define FF_WM_PRETTY_DWM "dwm"
|
||||
#define FF_WM_PRETTY_WESTON "Weston"
|
||||
#define FF_WM_PRETTY_XMONAD "XMonad"
|
||||
#define FF_WM_PRETTY_WSLG "WSLg"
|
||||
|
||||
#define FF_WM_PROTOCOL_TTY "TTY"
|
||||
#define FF_WM_PROTOCOL_X11 "X11"
|
||||
#define FF_WM_PROTOCOL_WAYLAND "Wayland"
|
||||
|
||||
typedef enum FFDisplayType {
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
FF_DISPLAY_TYPE_BUILTIN,
|
||||
FF_DISPLAY_TYPE_EXTERNAL,
|
||||
} FFDisplayType;
|
||||
|
||||
typedef struct FFDisplayResult
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t refreshRate;
|
||||
double refreshRate;
|
||||
uint32_t scaledWidth;
|
||||
uint32_t scaledHeight;
|
||||
FFstrbuf name;
|
||||
FFDisplayType type;
|
||||
} FFDisplayResult;
|
||||
|
||||
typedef struct FFDisplayServerResult
|
||||
@@ -27,8 +64,14 @@ typedef struct FFDisplayServerResult
|
||||
|
||||
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance);
|
||||
|
||||
//Used internal
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
|
||||
bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight);
|
||||
bool ffdsAppendDisplay(
|
||||
FFDisplayServerResult* result,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
double refreshRate,
|
||||
uint32_t scaledWidth,
|
||||
uint32_t scaledHeight,
|
||||
FFstrbuf* name,
|
||||
FFDisplayType type);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
#include "displayserver.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <CoreGraphics/CGDirectDisplay.h>
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
|
||||
static void detectDisplays(FFDisplayServerResult* ds)
|
||||
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
|
||||
|
||||
static void detectDisplays(FFDisplayServerResult* ds, bool detectName)
|
||||
{
|
||||
CGDirectDisplayID screens[128];
|
||||
uint32_t screenCount;
|
||||
@@ -20,12 +25,42 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen);
|
||||
if(mode)
|
||||
{
|
||||
//https://github.com/glfw/glfw/commit/aab08712dd8142b642e2042e7b7ba563acd07a45
|
||||
double refreshRate = CGDisplayModeGetRefreshRate(mode);
|
||||
|
||||
if (refreshRate == 0)
|
||||
{
|
||||
CVDisplayLinkRef link;
|
||||
if(CVDisplayLinkCreateWithCGDisplay(screen, &link) == kCVReturnSuccess)
|
||||
{
|
||||
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
||||
if (!(time.flags & kCVTimeIsIndefinite))
|
||||
refreshRate = time.timeScale / (double) time.timeValue + 0.5; //59.97...
|
||||
CVDisplayLinkRelease(link);
|
||||
}
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY name;
|
||||
ffStrbufInit(&name);
|
||||
if(detectName && CoreDisplay_DisplayCreateInfoDictionary)
|
||||
{
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
|
||||
if(displayInfo)
|
||||
{
|
||||
CFDictionaryRef productNames;
|
||||
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
|
||||
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
|
||||
}
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(ds,
|
||||
(uint32_t)CGDisplayModeGetPixelWidth(mode),
|
||||
(uint32_t)CGDisplayModeGetPixelHeight(mode),
|
||||
(uint32_t)CGDisplayModeGetRefreshRate(mode),
|
||||
refreshRate,
|
||||
(uint32_t)CGDisplayModeGetWidth(mode),
|
||||
(uint32_t)CGDisplayModeGetHeight(mode)
|
||||
(uint32_t)CGDisplayModeGetHeight(mode),
|
||||
&name,
|
||||
CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL
|
||||
);
|
||||
CGDisplayModeRelease(mode);
|
||||
}
|
||||
@@ -39,7 +74,7 @@ static void detectWMPlugin(FFstrbuf* name)
|
||||
u_int requestLength = sizeof(request) / sizeof(*request);
|
||||
|
||||
size_t length = 0;
|
||||
struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length);
|
||||
FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length);
|
||||
if(processes == NULL)
|
||||
return;
|
||||
|
||||
@@ -60,21 +95,20 @@ static void detectWMPlugin(FFstrbuf* name)
|
||||
name->chars[0] = (char) toupper(name->chars[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
free(processes);
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInitS(&ds->wmProcessName, "quartz");
|
||||
ffStrbufInitS(&ds->wmProcessName, "WindowServer");
|
||||
ffStrbufInitS(&ds->wmPrettyName, "Quartz Compositor");
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
|
||||
if(instance->config.allowSlowOperations)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY name;
|
||||
ffStrbufInit(&name);
|
||||
detectWMPlugin(&name);
|
||||
if(name.length)
|
||||
ffStrbufAppendF(&ds->wmPrettyName, " (with %s)", name.chars);
|
||||
@@ -83,9 +117,9 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffStrbufAppendS(&ds->deProcessName, "aqua");
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufAppendS(&ds->dePrettyName, "Aqua");
|
||||
|
||||
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
|
||||
detectDisplays(ds);
|
||||
detectDisplays(ds, instance->config.displayDetectName);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,101 @@
|
||||
#include "displayserver.h"
|
||||
#include "detection/os/os.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
#include <WinUser.h>
|
||||
|
||||
typedef struct
|
||||
static void detectDisplays(FFDisplayServerResult* ds, bool detectName)
|
||||
{
|
||||
WCHAR* deviceName;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} DataBundle;
|
||||
DISPLAYCONFIG_PATH_INFO paths[128];
|
||||
uint32_t pathCount = sizeof(paths) / sizeof(paths[0]);
|
||||
DISPLAYCONFIG_MODE_INFO modes[256];
|
||||
uint32_t modeCount = sizeof(modes) / sizeof(modes[0]);
|
||||
|
||||
static CALLBACK WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam)
|
||||
{
|
||||
MONITORINFOEXW mi = { .cbSize = sizeof(mi) };
|
||||
DataBundle* data = (DataBundle*) lparam;
|
||||
if(GetMonitorInfoW(hMonitor, (MONITORINFO *)&mi) && wcscmp(mi.szDevice, data->deviceName) == 0)
|
||||
if (QueryDisplayConfig(
|
||||
QDC_ONLY_ACTIVE_PATHS,
|
||||
&pathCount,
|
||||
paths,
|
||||
&modeCount,
|
||||
modes,
|
||||
NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
data->width = (uint32_t) mi.rcMonitor.right;
|
||||
data->height = (uint32_t) mi.rcMonitor.bottom;
|
||||
return FALSE;
|
||||
for (uint32_t i = 0; i < pathCount; ++i)
|
||||
{
|
||||
DISPLAYCONFIG_PATH_INFO* path = &paths[i];
|
||||
|
||||
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {
|
||||
.header = {
|
||||
.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
|
||||
.size = sizeof(sourceName),
|
||||
.adapterId = path->sourceInfo.adapterId,
|
||||
.id = path->sourceInfo.id,
|
||||
},
|
||||
};
|
||||
|
||||
uint32_t scaledWidth = 0, scaledHeight = 0;
|
||||
if (DisplayConfigGetDeviceInfo(&sourceName.header) == ERROR_SUCCESS)
|
||||
{
|
||||
HDC hdc = CreateICW(sourceName.viewGdiDeviceName, NULL, NULL, NULL);
|
||||
scaledWidth = (uint32_t) GetDeviceCaps(hdc, HORZRES);
|
||||
scaledHeight = (uint32_t) GetDeviceCaps(hdc, VERTRES);
|
||||
DeleteDC(hdc);
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY name;
|
||||
ffStrbufInit(&name);
|
||||
|
||||
if (detectName)
|
||||
{
|
||||
DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {
|
||||
.header = {
|
||||
.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME,
|
||||
.size = sizeof(targetName),
|
||||
.adapterId = path->targetInfo.adapterId,
|
||||
.id = path->targetInfo.id,
|
||||
},
|
||||
};
|
||||
if(DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS)
|
||||
{
|
||||
if (targetName.flags.friendlyNameFromEdid)
|
||||
ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName);
|
||||
else
|
||||
{
|
||||
ffStrbufSetWS(&name, targetName.monitorDevicePath);
|
||||
ffStrbufSubstrAfterFirstC(&name, '#');
|
||||
ffStrbufSubstrBeforeFirstC(&name, '#');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t width = modes[path->sourceInfo.modeInfoIdx].sourceMode.width;
|
||||
uint32_t height = modes[path->sourceInfo.modeInfoIdx].sourceMode.height;
|
||||
if (path->targetInfo.rotation == DISPLAYCONFIG_ROTATION_ROTATE90 ||
|
||||
path->targetInfo.rotation == DISPLAYCONFIG_ROTATION_ROTATE270)
|
||||
{
|
||||
uint32_t temp = width;
|
||||
width = height;
|
||||
height = temp;
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(ds,
|
||||
width,
|
||||
height,
|
||||
path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
&name,
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED
|
||||
? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL
|
||||
);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
BOOL enabled;
|
||||
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled == TRUE)
|
||||
{
|
||||
@@ -45,23 +113,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInit(&ds->displays, sizeof(FFDisplayResult));
|
||||
|
||||
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) };
|
||||
for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum)
|
||||
{
|
||||
if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) };
|
||||
if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0)
|
||||
continue;
|
||||
|
||||
DataBundle data = {
|
||||
.deviceName = displayDevice.DeviceName,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
};
|
||||
EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM)&data);
|
||||
ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, data.width, data.height);
|
||||
}
|
||||
detectDisplays(ds, instance->config.displayDetectName);
|
||||
|
||||
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
|
||||
const FFOSResult* os = ffDetectOS(instance);
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
@@ -5,20 +5,35 @@
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
#include "common/library.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/thread.h"
|
||||
#include <wayland-client.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
typedef struct WaylandData
|
||||
{
|
||||
FFlist* results;
|
||||
FFDisplayServerResult* result;
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
|
||||
FF_LIBRARY_SYMBOL(wl_display_roundtrip)
|
||||
struct wl_display* display;
|
||||
const struct wl_interface* ffwl_output_interface;
|
||||
bool detectName;
|
||||
} WaylandData;
|
||||
|
||||
typedef struct WaylandDisplay
|
||||
{
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
int32_t scale;
|
||||
enum wl_output_transform transform;
|
||||
FFDisplayType type;
|
||||
FFstrbuf name;
|
||||
bool detectName;
|
||||
} WaylandDisplay;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
@@ -47,27 +62,136 @@ static void stubListener(void* data, ...)
|
||||
(void) data;
|
||||
}
|
||||
|
||||
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
WaylandData* wldata = data;
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||
return;
|
||||
|
||||
wldata->ffwl_proxy_destroy((struct wl_proxy*) output);
|
||||
WaylandDisplay* display = data;
|
||||
display->width = width;
|
||||
display->height = height;
|
||||
display->refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0)
|
||||
#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
|
||||
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->scale = scale;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void waylandOutputGeometryListener(void *data,
|
||||
FF_MAYBE_UNUSED struct wl_output *output,
|
||||
FF_MAYBE_UNUSED int32_t x,
|
||||
FF_MAYBE_UNUSED int32_t y,
|
||||
FF_MAYBE_UNUSED int32_t physical_width,
|
||||
FF_MAYBE_UNUSED int32_t physical_height,
|
||||
FF_MAYBE_UNUSED int32_t subpixel,
|
||||
const char *make,
|
||||
const char *model,
|
||||
int32_t transform)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->transform = (enum wl_output_transform) transform;
|
||||
if(display->detectName)
|
||||
{
|
||||
if(make && strcmp(make, "unknown") != 0)
|
||||
ffStrbufAppendS(&display->name, make);
|
||||
if(model && strcmp(model, "unknown") != 0)
|
||||
{
|
||||
if(display->name.length > 0)
|
||||
ffStrbufAppendC(&display->name, '-');
|
||||
ffStrbufAppendS(&display->name, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
static void waylandOutputNameListener(void *data, FF_MAYBE_UNUSED struct wl_output *output, const char *name)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
if(strncmp(name, "eDP-", strlen("eDP-")) == 0)
|
||||
display->type = FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(strncmp(name, "HDMI-", strlen("HDMI-")) == 0 || strncmp(name, "DP-", strlen("DP-")) == 0)
|
||||
display->type = FF_DISPLAY_TYPE_EXTERNAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
WaylandDisplay display = {
|
||||
.detectName = wldata->detectName,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
};
|
||||
ffStrbufInit(&display.name);
|
||||
|
||||
struct wl_output_listener outputListener = {
|
||||
.mode = waylandOutputModeListener,
|
||||
.geometry = waylandOutputGeometryListener,
|
||||
|
||||
#ifdef WL_OUTPUT_DONE_SINCE_VERSION
|
||||
.done = (void*) stubListener,
|
||||
#endif
|
||||
|
||||
#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
|
||||
.scale = waylandOutputScaleListener,
|
||||
#endif
|
||||
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
.name = waylandOutputNameListener,
|
||||
#endif
|
||||
|
||||
#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
|
||||
.description = (void*) stubListener,
|
||||
#endif
|
||||
};
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
return;
|
||||
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
FFDisplayResult* result = ffListAdd(wldata->results);
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270: {
|
||||
int32_t temp = display.width;
|
||||
display.width = display.height;
|
||||
display.height = temp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(wldata->result,
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
&display.name,
|
||||
display.type
|
||||
);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
|
||||
result->width = (uint32_t) width;
|
||||
result->height = (uint32_t) height;
|
||||
result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000);
|
||||
result->scaledWidth = 0;
|
||||
result->scaledHeight = 0;
|
||||
}
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
@@ -75,31 +199,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
|
||||
WaylandData* wldata = data;
|
||||
|
||||
if(strcmp(interface, wldata->ffwl_output_interface->name) == 0)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
//Needs to be static, because the scope of the function will already be lost when calling the listener
|
||||
static struct wl_output_listener outputListener = {
|
||||
.mode = waylandOutputModeListener,
|
||||
.geometry = (void*) stubListener,
|
||||
|
||||
//https://lists.freedesktop.org/archives/wayland-devel/2013-July/010278.html
|
||||
#if WAYLAND_VERSION_MINOR >= 2
|
||||
.done = (void*) stubListener,
|
||||
.scale = (void*) stubListener,
|
||||
#endif
|
||||
|
||||
//https://lists.freedesktop.org/archives/wayland-devel/2021-December/042064.html
|
||||
#if WAYLAND_VERSION_MINOR >= 20
|
||||
.name = (void*) stubListener,
|
||||
.description = (void*) stubListener,
|
||||
#endif
|
||||
};
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, data);
|
||||
}
|
||||
waylandOutputHandler(wldata, registry, name, version);
|
||||
}
|
||||
|
||||
bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
@@ -109,7 +209,6 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
|
||||
@@ -119,26 +218,25 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false)
|
||||
|
||||
struct wl_display* display = ffwl_display_connect(NULL);
|
||||
if(display == NULL)
|
||||
{
|
||||
dlclose(wayland);
|
||||
data.display = ffwl_display_connect(NULL);
|
||||
if(data.display == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
waylandDetectWM(ffwl_display_get_fd(display), result);
|
||||
data.detectName = instance->config.displayDetectName;
|
||||
|
||||
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
|
||||
waylandDetectWM(ffwl_display_get_fd(data.display), result);
|
||||
|
||||
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
|
||||
if(registry == NULL)
|
||||
{
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
ffwl_display_disconnect(data.display);
|
||||
return false;
|
||||
}
|
||||
|
||||
data.results = &result->displays;
|
||||
data.result = result;
|
||||
|
||||
struct wl_registry_listener registry_listener = {
|
||||
.global = waylandGlobalAddListener,
|
||||
@@ -146,17 +244,16 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
};
|
||||
|
||||
data.ffwl_proxy_add_listener(registry, (void(**)(void)) ®istry_listener, &data);
|
||||
ffwl_display_dispatch(display);
|
||||
ffwl_display_roundtrip(display);
|
||||
ffwl_display_dispatch(data.display);
|
||||
data.ffwl_display_roundtrip(data.display);
|
||||
|
||||
data.ffwl_proxy_destroy(registry);
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
ffwl_display_disconnect(data.display);
|
||||
|
||||
//We successfully connected to wayland and detected the display.
|
||||
//So we can set set the session type to wayland.
|
||||
//This is used as an indicator that we are running wayland by the x11 backends.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -187,5 +284,5 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul
|
||||
|
||||
//We are probably running a wayland compositor at this point,
|
||||
//but fastfetch was compiled without the required library, or loading the library failed.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
@@ -48,7 +49,7 @@ static const char* parseEnv()
|
||||
|
||||
if(
|
||||
getenv("WAYLAND_DISPLAY") != NULL &&
|
||||
ffFileExists("/mnt/wslg/", S_IFDIR)
|
||||
ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY)
|
||||
) return "WSLg";
|
||||
|
||||
return NULL;
|
||||
@@ -65,31 +66,34 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce
|
||||
strcasecmp(processName, "kwin_x11") == 0 ||
|
||||
strcasecmp(processName, "kwin_x11_wrapper") == 0 ||
|
||||
strcasecmp(processName, "kwin") == 0
|
||||
) ffStrbufSetS(&result->wmPrettyName, "KWin");
|
||||
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN);
|
||||
else if(
|
||||
strcasecmp(processName, "gnome-shell") == 0 ||
|
||||
strcasecmp(processName, "gnome shell") == 0 ||
|
||||
strcasecmp(processName, "gnome-session-binary") == 0 ||
|
||||
strcasecmp(processName, "Mutter") == 0
|
||||
) ffStrbufSetS(&result->wmPrettyName, "Mutter");
|
||||
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER);
|
||||
else if(
|
||||
strcasecmp(processName, "cinnamon-session") == 0 ||
|
||||
strcasecmp(processName, "Muffin") == 0
|
||||
) ffStrbufSetS(&result->wmPrettyName, "Muffin");
|
||||
strcasecmp(processName, "Muffin") == 0 ||
|
||||
strcasecmp(processName, "Mutter (Muffin)") == 0
|
||||
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN);
|
||||
else if(strcasecmp(processName, "sway") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Sway");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_SWAY);
|
||||
else if(strcasecmp(processName, "weston") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Weston");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WESTON);
|
||||
else if(strcasecmp(processName, "wayfire") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Wayfire");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WAYFIRE);
|
||||
else if(strcasecmp(processName, "openbox") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Openbox");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_OPENBOX);
|
||||
else if(strcasecmp(processName, "xfwm4") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Xfwm4");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XFWM4);
|
||||
else if(strcasecmp(processName, "Marco") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Marco");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MARCO);
|
||||
else if(strcasecmp(processName, "xmonad") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "XMonad");
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XMONAD);
|
||||
else if(strcasecmp(processName, "WSLg") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WSLG);
|
||||
else if( // WMs where the pretty name matches the process name
|
||||
strcasecmp(processName, "dwm") == 0 ||
|
||||
strcasecmp(processName, "bspwm") == 0 ||
|
||||
@@ -119,7 +123,7 @@ static void applyBetterWM(FFDisplayServerResult* result, const char* processName
|
||||
static void getKDE(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "plasmashell");
|
||||
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
|
||||
|
||||
ffParsePropFileData(instance, "xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
@@ -135,21 +139,31 @@ static void getKDE(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
static void getGnome(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "gnome-shell");
|
||||
ffStrbufSetS(&result->dePrettyName, "GNOME");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME);
|
||||
ffParsePropFileData(instance, "gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
|
||||
|
||||
if (result->deVersion.length == 0)
|
||||
{
|
||||
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"gnome-shell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // GNOME Shell 44.1
|
||||
ffStrbufSubstrAfterLastC(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getCinnamon(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "cinnamon");
|
||||
ffStrbufSetS(&result->dePrettyName, "Cinnamon");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
|
||||
ffParsePropFileData(instance, "applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
|
||||
}
|
||||
|
||||
static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "mate-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "MATE");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
|
||||
|
||||
FFstrbuf major;
|
||||
ffStrbufInit(&major);
|
||||
@@ -188,7 +202,7 @@ static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "xfce4-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "Xfce4");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
|
||||
ffParsePropFileData(instance, "gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
@@ -209,7 +223,7 @@ static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "lxqt-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "LXQt");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
|
||||
ffParsePropFileData(instance, "gconfig/lxqt.pc", "Version:", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0)
|
||||
@@ -241,8 +255,8 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
|
||||
static void getBudgie(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->dePrettyName, "Budgie");
|
||||
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
|
||||
ffParsePropFileData(instance, "budgie/budgie-version.xml", "<str>", &result->deVersion);
|
||||
}
|
||||
|
||||
@@ -307,9 +321,9 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
|
||||
if(ffStrSet(env))
|
||||
{
|
||||
if(strcasecmp(env, "x11") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
else if(strcasecmp(env, "tty") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
|
||||
else
|
||||
ffStrbufSetS(&result->wmProtocolName, env);
|
||||
|
||||
@@ -319,14 +333,14 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
|
||||
env = getenv("DISPLAY");
|
||||
if(ffStrSet(env))
|
||||
{
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("TERM");
|
||||
if(ffStrSet(env))
|
||||
if(ffStrSet(env) && strcasecmp(env, "linux") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -408,7 +422,7 @@ void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
|
||||
//We don't want to detect anything in TTY
|
||||
//This can't happen if a connection succeeded, so we don't need to clear wmProcessName
|
||||
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY) == 0)
|
||||
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
return;
|
||||
|
||||
const char* env = parseEnv();
|
||||
|
||||
@@ -62,7 +62,7 @@ static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection,
|
||||
|
||||
static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result)
|
||||
{
|
||||
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0)
|
||||
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0)
|
||||
return;
|
||||
|
||||
xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK");
|
||||
@@ -103,10 +103,7 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
|
||||
xcb_connection_t* connection = ffxcb_connect(NULL, NULL);
|
||||
if(connection == NULL)
|
||||
{
|
||||
dlclose(xcb);
|
||||
return;
|
||||
}
|
||||
|
||||
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(connection));
|
||||
|
||||
@@ -115,23 +112,23 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
|
||||
while(iterator.rem > 0)
|
||||
{
|
||||
ffdsAppendDisplay(
|
||||
result,
|
||||
ffdsAppendDisplay(result,
|
||||
(uint32_t) iterator.data->width_in_pixels,
|
||||
(uint32_t) iterator.data->height_in_pixels,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
(uint32_t) iterator.data->width_in_pixels,
|
||||
(uint32_t) iterator.data->height_in_pixels,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
ffxcb_screen_next(&iterator);
|
||||
}
|
||||
|
||||
ffxcb_disconnect(connection);
|
||||
dlclose(xcb);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -178,17 +175,17 @@ typedef struct XcbRandrData
|
||||
|
||||
static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo)
|
||||
{
|
||||
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
|
||||
modeInfo->dot_clock / (uint32_t) (modeInfo->htotal * modeInfo->vtotal)
|
||||
));
|
||||
double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal);
|
||||
|
||||
return ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) modeInfo->width,
|
||||
(uint32_t) modeInfo->height,
|
||||
refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) modeInfo->width,
|
||||
(uint32_t) modeInfo->height,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
@@ -224,8 +221,10 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
data->defaultRefreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
|
||||
free(crtcInfoReply);
|
||||
@@ -269,8 +268,10 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
|
||||
(uint32_t) monitor->width,
|
||||
(uint32_t) monitor->height,
|
||||
data->defaultRefreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) monitor->width,
|
||||
(uint32_t) monitor->height,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
@@ -329,8 +330,10 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
|
||||
(uint32_t) screen->width_in_pixels,
|
||||
(uint32_t) screen->height_in_pixels,
|
||||
data->defaultRefreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) screen->width_in_pixels,
|
||||
(uint32_t) screen->height_in_pixels,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
@@ -368,10 +371,7 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu
|
||||
|
||||
data.connection = ffxcb_connect(NULL, NULL);
|
||||
if(data.connection == NULL)
|
||||
{
|
||||
dlclose(xcbRandr);
|
||||
return;
|
||||
}
|
||||
|
||||
data.result = result;
|
||||
|
||||
@@ -387,11 +387,10 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu
|
||||
}
|
||||
|
||||
ffxcb_disconnect(data.connection);
|
||||
dlclose(xcbRandr);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#ifdef FF_HAVE_X11
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
typedef struct X11PropertyData
|
||||
@@ -39,7 +40,7 @@ static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Wi
|
||||
|
||||
static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result)
|
||||
{
|
||||
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0)
|
||||
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0)
|
||||
return;
|
||||
|
||||
Window* wmWindow = (Window*) x11GetProperty(data, display, DefaultRootWindow(display), "_NET_SUPPORTING_WM_CHECK");
|
||||
@@ -68,10 +69,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
|
||||
Display* display = ffXOpenDisplay(x11);
|
||||
if(display == NULL)
|
||||
{
|
||||
dlclose(x11);
|
||||
return;
|
||||
}
|
||||
|
||||
if(propertyDataInitialized && ScreenCount(display) > 0)
|
||||
x11DetectWMFromEWMH(&propertyData, display, result);
|
||||
@@ -79,22 +77,22 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
for(int i = 0; i < ScreenCount(display); i++)
|
||||
{
|
||||
Screen* screen = ScreenOfDisplay(display, i);
|
||||
ffdsAppendDisplay(
|
||||
result,
|
||||
(uint32_t) screen->width,
|
||||
(uint32_t) screen->height,
|
||||
ffdsAppendDisplay(result,
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
0,
|
||||
0,
|
||||
0
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
ffXCloseDisplay(display);
|
||||
dlclose(x11);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -136,17 +134,17 @@ typedef struct XrandrData
|
||||
|
||||
static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
|
||||
{
|
||||
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
|
||||
modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)
|
||||
));
|
||||
double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal);
|
||||
|
||||
return ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) modeInfo->width,
|
||||
(uint32_t) modeInfo->height,
|
||||
refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) modeInfo->width,
|
||||
(uint32_t) modeInfo->height,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
@@ -176,8 +174,10 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
|
||||
(uint32_t) crtcInfo->width,
|
||||
(uint32_t) crtcInfo->height,
|
||||
data->defaultRefreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) crtcInfo->width,
|
||||
(uint32_t) crtcInfo->height,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
@@ -212,8 +212,10 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
(uint32_t) monitorInfo->width,
|
||||
(uint32_t) monitorInfo->height,
|
||||
data->defaultRefreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) monitorInfo->width,
|
||||
(uint32_t) monitorInfo->height,
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
@@ -266,8 +268,10 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
data->defaultRefreshRate,
|
||||
0,
|
||||
0
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
||||
@@ -297,10 +301,7 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result
|
||||
|
||||
data.display = ffXOpenDisplay(NULL);
|
||||
if(data.display == NULL)
|
||||
{
|
||||
dlclose(xrandr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(propertyDataInitialized && ScreenCount(data.display) > 0)
|
||||
x11DetectWMFromEWMH(&propertyData, data.display, result);
|
||||
@@ -311,11 +312,10 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result
|
||||
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
|
||||
|
||||
ffXCloseDisplay(data.display);
|
||||
dlclose(xrandr);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -9,6 +9,7 @@ static void detectFont(const FFinstance* instance, FFFontResult* font)
|
||||
|
||||
for(uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i)
|
||||
ffStrbufInit(&font->fonts[i]);
|
||||
ffStrbufInit(&font->display);
|
||||
|
||||
ffDetectFontImpl(instance, font);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef struct FFFontResult
|
||||
* Other: Unset, Unset, Unset, Unset
|
||||
*/
|
||||
FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS];
|
||||
FFstrbuf display;
|
||||
} FFFontResult;
|
||||
|
||||
const FFFontResult* ffDetectFont(const FFinstance* instance);
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
#include "common/font.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "font.h"
|
||||
|
||||
#import <AppKit/NSFont.h>
|
||||
|
||||
static void generateString(FFFontResult* font)
|
||||
{
|
||||
if(font->fonts[0].length > 0)
|
||||
{
|
||||
ffStrbufAppend(&font->display, &font->fonts[0]);
|
||||
ffStrbufAppendS(&font->display, " [System]");
|
||||
if(font->fonts[1].length > 0)
|
||||
ffStrbufAppendS(&font->display, ", ");
|
||||
}
|
||||
|
||||
if(font->fonts[1].length > 0)
|
||||
{
|
||||
ffStrbufAppend(&font->display, &font->fonts[1]);
|
||||
ffStrbufAppendS(&font->display, " [User]");
|
||||
}
|
||||
}
|
||||
|
||||
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
@@ -11,4 +28,5 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
ffStrbufAppendS(&result->fonts[1], [NSFont userFontOfSize:12].familyName.UTF8String);
|
||||
ffStrbufAppendS(&result->fonts[2], [NSFont monospacedSystemFontOfSize:12 weight:400].familyName.UTF8String);
|
||||
ffStrbufAppendS(&result->fonts[3], [NSFont userFixedPitchFontOfSize:12].familyName.UTF8String);
|
||||
generateString(result);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,39 @@
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "common/font.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
#include "font.h"
|
||||
|
||||
static void generateString(FFFontResult* font)
|
||||
{
|
||||
if(font->fonts[0].length > 0)
|
||||
{
|
||||
ffStrbufAppend(&font->display, &font->fonts[0]);
|
||||
ffStrbufAppendS(&font->display, " [QT]");
|
||||
|
||||
for(uint8_t i = 1; i < sizeof(font->fonts) / sizeof(font->fonts[0]); i++)
|
||||
{
|
||||
if(font->fonts[i].length > 0)
|
||||
{
|
||||
ffStrbufAppendS(&font->display, ", ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffParseGTK(&font->display, &font->fonts[1], &font->fonts[2], &font->fonts[3]);
|
||||
}
|
||||
|
||||
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
{
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
{
|
||||
ffStrbufAppendS(&result->error, "Font isn't supported in TTY");
|
||||
return;
|
||||
}
|
||||
|
||||
FFfont qt;
|
||||
ffFontInitQt(&qt, ffDetectQt(instance)->font.chars);
|
||||
ffStrbufAppend(&result->fonts[0], &qt.pretty);
|
||||
@@ -24,4 +53,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
ffFontInitPango(>k4, ffDetectGTK4(instance)->font.chars);
|
||||
ffStrbufAppend(&result->fonts[3], >k4.pretty);
|
||||
ffFontDestroy(>k4);
|
||||
|
||||
generateString(result);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
#include "font.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <winuser.h>
|
||||
#include <windows.h>
|
||||
|
||||
static void generateString(FFFontResult* font)
|
||||
{
|
||||
const char* types[] = { "Caption", "Menu", "Message", "Status" };
|
||||
for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i)
|
||||
{
|
||||
if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i]))
|
||||
{
|
||||
if(i > 0)
|
||||
ffStrbufAppendS(&font->display, "], ");
|
||||
ffStrbufAppendF(&font->display, "%s [%s", font->fonts[i].chars, types[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendS(&font->display, " / ");
|
||||
ffStrbufAppendS(&font->display, types[i]);
|
||||
}
|
||||
}
|
||||
ffStrbufAppendC(&font->display, ']');
|
||||
}
|
||||
|
||||
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
{
|
||||
@@ -19,4 +39,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
if(fonts[i]->lfHeight < 0)
|
||||
ffStrbufAppendF(&result->fonts[i], " (%dpt)", (int)-fonts[i]->lfHeight);
|
||||
}
|
||||
|
||||
generateString(result);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_gamepad_gamepad
|
||||
#define FF_INCLUDED_detection_gamepad_gamepad
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFGamepadDevice
|
||||
{
|
||||
FFstrbuf identifier;
|
||||
FFstrbuf name;
|
||||
} FFGamepadDevice;
|
||||
|
||||
const char* ffDetectGamepad(const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "gamepad.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
static void enumSet(const void* value, void *context)
|
||||
{
|
||||
CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey));
|
||||
CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey));
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context);
|
||||
ffStrbufInit(&device->identifier);
|
||||
ffCfStrGetString(serialNumber, &device->identifier);
|
||||
ffStrbufInit(&device->name);
|
||||
ffCfStrGetString(product, &device->name);
|
||||
}
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
|
||||
return "IOHIDManagerOpen() failed";
|
||||
|
||||
CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop);
|
||||
CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad);
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
CFSTR(kIOHIDDeviceUsageKey)
|
||||
}, (const void **)(CFNumberRef[]){
|
||||
genericDesktop,
|
||||
gamePad
|
||||
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
IOHIDManagerSetDeviceMatching(manager, matching);
|
||||
|
||||
CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
|
||||
if (set)
|
||||
CFSetApplyFunction(set, &enumSet, devices);
|
||||
IOHIDManagerClose(manager, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "gamepad.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
DIR* dirp = opendir("/sys/class/input/");
|
||||
if(dirp == NULL)
|
||||
return "opendir(\"/sys/class/input/\") == NULL";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path;
|
||||
ffStrbufInitS(&path, "/sys/class/input/");
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(strncmp(entry->d_name, "js", 2) != 0)
|
||||
continue;
|
||||
if(!isdigit(entry->d_name[2]))
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
ffStrbufAppendS(&path, "/device/name");
|
||||
|
||||
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitS(&device->identifier, entry->d_name);
|
||||
ffStrbufInit(&device->name);
|
||||
ffAppendFileBuffer(path.chars, &device->name);
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "gamepad.h"
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
#include "gamepad.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
|
||||
{
|
||||
switch (vendorId)
|
||||
{
|
||||
// Nintendo
|
||||
case 0x057E:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x2006: return "Nintendo Switch Joycon L";
|
||||
case 0x2007: return "Nintendo Switch Joycon R";
|
||||
case 0x2009: return "Nintendo Switch Pro Controller";
|
||||
case 0x200E: return "Nintendo Switch Charging Grip";
|
||||
case 0x2017: return "Nintendo Switch SNES Controller";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Sony
|
||||
case 0x054C:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x0268: return "Sony Playstation 3 Controller";
|
||||
|
||||
case 0x05C4: return "Sony DualShock 4 Gen1";
|
||||
case 0x09CC: return "Sony DualShock 4 Gen2";
|
||||
case 0x0BA0: return "Sony PS4 Controller USB receiver";
|
||||
|
||||
case 0x0CE6: return "Sony DualSense";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Microsoft
|
||||
case 0x045E:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
|
||||
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
|
||||
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
|
||||
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
|
||||
|
||||
case 0x028E: return "Microsoft XBox 360";
|
||||
case 0x028F: return "Microsoft XBox 360 v2";
|
||||
case 0x02A1: return "Microsoft XBox 360";
|
||||
case 0x0291: return "Microsoft XBox 360 USB receiver";
|
||||
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
|
||||
case 0x02DD: return "Microsoft XBox One";
|
||||
case 0xB326: return "Microsoft XBox One Firmware 2015";
|
||||
case 0x02E3: return "Microsoft XBox One Elite";
|
||||
case 0x02FF: return "Microsoft XBox One Elite";
|
||||
case 0x02EA: return "Microsoft XBox One S";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Logitech
|
||||
case 0x046D:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0xC216: return "Logitech F310, DirectInput";
|
||||
case 0xC218: return "Logitech F510, DirectInput";
|
||||
case 0xC219: return "Logitech F710, DirectInput";
|
||||
case 0xC21D: return "Logitech F310";
|
||||
case 0xC21E: return "Logitech F510";
|
||||
case 0xC21F: return "Logitech F710";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
UINT nDevices = 0;
|
||||
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)))
|
||||
return "GetRawInputDeviceList(NULL) failed";
|
||||
if (nDevices == 0)
|
||||
return "No HID devices found";
|
||||
RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);
|
||||
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
|
||||
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
|
||||
|
||||
for (UINT i = 0; i < nDevices; ++i) {
|
||||
if (pRawInputDeviceList[i].dwType != 2) continue;
|
||||
|
||||
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
|
||||
|
||||
RID_DEVICE_INFO rdi;
|
||||
UINT rdiSize = sizeof(rdi);
|
||||
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1)
|
||||
continue;
|
||||
|
||||
if (rdi.hid.usUsagePage != 1 || rdi.hid.usUsage != 5) // Gamepad
|
||||
continue;
|
||||
|
||||
WCHAR devName[MAX_PATH] = L"";
|
||||
UINT nameSize = MAX_PATH;
|
||||
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1)
|
||||
continue;
|
||||
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitWS(&device->identifier, devName);
|
||||
ffStrbufInit(&device->name);
|
||||
|
||||
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
if (knownGamepad)
|
||||
ffStrbufSetS(&device->name, knownGamepad);
|
||||
else
|
||||
{
|
||||
wchar_t displayName[126];
|
||||
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
|
||||
ffStrbufSetWS(&device->name, displayName);
|
||||
else
|
||||
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+31
-5
@@ -1,16 +1,42 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/internal.h"
|
||||
#include "detection/vulkan.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
|
||||
|
||||
const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
|
||||
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
|
||||
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
|
||||
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
|
||||
|
||||
static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsigned length)
|
||||
{
|
||||
for (unsigned i = 0; i < length; ++i)
|
||||
{
|
||||
if (arr[i] == vendorId)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffGetGPUVendorString(unsigned vendorId)
|
||||
{
|
||||
if(vendorId == 0x106b)
|
||||
return FF_GPU_VENDOR_NAME_APPLE;
|
||||
if(arrayContains((const unsigned[]) {0x1002, 0x1022}, vendorId, 2))
|
||||
return FF_GPU_VENDOR_NAME_AMD;
|
||||
else if(arrayContains((const unsigned[]) {0x03e7, 0x8086, 0x8087}, vendorId, 3))
|
||||
return FF_GPU_VENDOR_NAME_INTEL;
|
||||
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
|
||||
return FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FFlist* ffDetectGPU(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFlist,
|
||||
ffListInit(&result, sizeof(FFGPUResult));
|
||||
ffDetectGPUImpl(&result, instance);
|
||||
|
||||
if(result.length == 0)
|
||||
if(instance->config.gpuForceVulkan || ffDetectGPUImpl(&result, instance) != NULL)
|
||||
{
|
||||
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
|
||||
result = vulkan->gpus;
|
||||
|
||||
+17
-5
@@ -7,19 +7,26 @@
|
||||
|
||||
#define FF_GPU_TEMP_UNSET (0/0.0)
|
||||
#define FF_GPU_CORE_COUNT_UNSET -1
|
||||
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1)
|
||||
|
||||
#define FF_GPU_VENDOR_NAME_APPLE "Apple"
|
||||
#define FF_GPU_VENDOR_NAME_AMD "AMD"
|
||||
#define FF_GPU_VENDOR_NAME_INTEL "Intel"
|
||||
#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA"
|
||||
extern const char* FF_GPU_VENDOR_NAME_APPLE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_AMD;
|
||||
extern const char* FF_GPU_VENDOR_NAME_INTEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
|
||||
typedef enum FFGpuType
|
||||
{
|
||||
FF_GPU_TYPE_UNKNOWN,
|
||||
FF_GPU_TYPE_INTEGRATED,
|
||||
FF_GPU_TYPE_DISCRETE,
|
||||
FF_GPU_TYPE_UNKNOWN
|
||||
} FFGpuType;
|
||||
|
||||
typedef struct FFGPUMemory
|
||||
{
|
||||
uint64_t total;
|
||||
uint64_t used;
|
||||
} FFGPUMemory;
|
||||
|
||||
typedef struct FFGPUResult
|
||||
{
|
||||
FFGpuType type;
|
||||
@@ -28,8 +35,13 @@ typedef struct FFGPUResult
|
||||
FFstrbuf driver;
|
||||
double temperature;
|
||||
int coreCount;
|
||||
FFGPUMemory dedicated;
|
||||
FFGPUMemory shared;
|
||||
uint32_t vulkanDeviceId; // Only used for vulkan
|
||||
} FFGPUResult;
|
||||
|
||||
const FFlist* ffDetectGPU(const FFinstance* instance);
|
||||
|
||||
const char* ffGetGPUVendorString(unsigned vendorId);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -60,32 +60,19 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(gpus);
|
||||
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
int vendorId;
|
||||
if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId))
|
||||
{
|
||||
if(vendorId == 0x106b)
|
||||
{
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
|
||||
ffStrbufAppendS(&gpu->vendor, vendorStr);
|
||||
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL)
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
else if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2))
|
||||
{
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE; // Apple never used AMD CPUs
|
||||
}
|
||||
else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3))
|
||||
{
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3))
|
||||
{
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD)
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/vulkan.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#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>
|
||||
|
||||
typedef struct PCIData
|
||||
{
|
||||
@@ -23,25 +25,9 @@ typedef struct PCIData
|
||||
#endif
|
||||
} PCIData;
|
||||
|
||||
static bool pciIDsContains(u16 searched, const u16* ids)
|
||||
{
|
||||
while(*ids != 0)
|
||||
{
|
||||
if(*ids == searched)
|
||||
return true;
|
||||
ids++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
if(pciIDsContains(device->vendor_id, (const u16[]) {0x1002, 0x1022, 0}))
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x03e7, 0x8086, 0x8087, 0}))
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x0955, 0x10de, 0x12d2, 0}))
|
||||
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
@@ -50,11 +36,11 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
|
||||
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id);
|
||||
ffStrbufRecalculateLength(&gpu->vendor);
|
||||
|
||||
if(ffStrbufFirstIndexS(&gpu->vendor, "AMD") < gpu->vendor.length || ffStrbufFirstIndexS(&gpu->vendor, "ATI") < gpu->vendor.length)
|
||||
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufFirstIndexS(&gpu->vendor, "Intel") < gpu->vendor.length)
|
||||
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufFirstIndexS(&gpu->vendor, "NVIDIA") < gpu->vendor.length)
|
||||
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
}
|
||||
|
||||
@@ -214,6 +200,8 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
pciDetectVendorName(gpu, pci, device);
|
||||
|
||||
@@ -232,6 +220,30 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
|
||||
pciDetectTemperatur(gpu, device);
|
||||
}
|
||||
|
||||
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 FFinstance* instance, FFlist* gpus)
|
||||
{
|
||||
PCIData pci;
|
||||
@@ -252,7 +264,14 @@ static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
|
||||
#endif
|
||||
|
||||
pci.access = ffpci_alloc();
|
||||
ffpci_init(pci.access);
|
||||
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;
|
||||
@@ -263,17 +282,17 @@ static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
|
||||
}
|
||||
|
||||
ffpci_cleanup(pci.access);
|
||||
dlclose(libpci);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
pciDetectGPUs(instance, gpus);
|
||||
return pciDetectGPUs(instance, gpus);
|
||||
#else
|
||||
FF_UNUSED(gpus, instance);
|
||||
return "fastfetch is built without libpci support";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "gpu.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance)
|
||||
{
|
||||
DISPLAY_DEVICEW displayDevice = {.cb = sizeof(displayDevice) };
|
||||
wchar_t regKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
|
||||
const uint32_t regKeyPrefixLength = strlen("SYSTEM\\CurrentControlSet\\Control\\Video\\{");
|
||||
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\{");
|
||||
|
||||
for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i)
|
||||
{
|
||||
if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue;
|
||||
|
||||
const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey);
|
||||
if (wmemcmp(&displayDevice.DeviceKey[deviceKeyLength - 4], L"0000", 4) != 0) continue;
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInitWS(&gpu->name, displayDevice.DeviceString);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
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;
|
||||
|
||||
if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{')
|
||||
{
|
||||
wmemcpy(regKey + regKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, 100 - regKeyPrefixLength + 1);
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regKey, &hKey, NULL)) continue;
|
||||
|
||||
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
|
||||
ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL);
|
||||
|
||||
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
|
||||
if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
|
||||
{
|
||||
uint32_t vmem = 0;
|
||||
if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL))
|
||||
gpu->dedicated.total = vmem;
|
||||
}
|
||||
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
extern "C" {
|
||||
#include "gpu.h"
|
||||
#include "util/windows/unicode.h"
|
||||
}
|
||||
|
||||
#ifdef FF_USE_WIN_GPU_DXGI
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
static const char* detectWithDxgi(FFlist* gpus)
|
||||
{
|
||||
IDXGIFactory1* pFactory;
|
||||
if(FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory))))
|
||||
return "CreateDXGIFactory1() failed";
|
||||
|
||||
for(unsigned iAdapter = 0;; ++iAdapter)
|
||||
{
|
||||
IDXGIAdapter1* adapter;
|
||||
if(FAILED(pFactory->EnumAdapters1(iAdapter, &adapter)))
|
||||
break;
|
||||
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
if(FAILED(adapter->GetDesc1(&desc)) || (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE))
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
|
||||
if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)desc.VendorId, 2))
|
||||
ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)desc.VendorId, 3))
|
||||
ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)desc.VendorId, 3))
|
||||
ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
else
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufSetWS(&gpu->name, desc.Description);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
|
||||
gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
|
||||
adapter->Release();
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
}
|
||||
|
||||
pFactory->Release();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
static const char* detectWithWmi(FFlist* gpus)
|
||||
{
|
||||
FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr);
|
||||
if(!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
while(FFWmiRecord record = query.next())
|
||||
{
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
record.getString(L"AdapterCompatibility", &gpu->vendor);
|
||||
if(ffStrbufStartsWithS(&gpu->vendor, "Intel "))
|
||||
{
|
||||
//Intel returns "Intel Corporation", not sure about AMD
|
||||
ffStrbufSetS(&gpu->vendor, "Intel");
|
||||
}
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
record.getString(L"Name", &gpu->name);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
record.getString(L"DriverVersion", &gpu->driver);
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
#ifdef FF_USE_WIN_GPU_DXGI
|
||||
return detectWithDxgi(gpus);
|
||||
#else
|
||||
return detectWithWmi(gpus);
|
||||
#endif
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/settings.h"
|
||||
@@ -13,7 +13,7 @@ static inline bool allPropertiesSet(FFGTKResult* result)
|
||||
result->font.length > 0;
|
||||
}
|
||||
|
||||
static inline void applyGTKSettings(FFGTKResult* result, const char* themeName, const char* iconsName, const char* fontName, const char* cursorTheme, int cursorSize)
|
||||
static inline void applyGTKSettings(FFGTKResult* result, const char* themeName, const char* iconsName, const char* fontName, const char* cursorTheme, int cursorSize, const char* wallpaper)
|
||||
{
|
||||
if(result->theme.length == 0)
|
||||
ffStrbufAppendS(&result->theme, themeName);
|
||||
@@ -29,6 +29,9 @@ static inline void applyGTKSettings(FFGTKResult* result, const char* themeName,
|
||||
|
||||
if(result->cursorSize.length == 0 && cursorSize > 0)
|
||||
ffStrbufAppendF(&result->cursorSize, "%i", cursorSize);
|
||||
|
||||
if(result->wallpaper.length == 0)
|
||||
ffStrbufAppendS(&result->wallpaper, wallpaper);
|
||||
}
|
||||
|
||||
static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* result)
|
||||
@@ -40,6 +43,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
|
||||
static const char* fontName = NULL;
|
||||
static const char* cursorTheme = NULL;
|
||||
static int cursorSize = 0;
|
||||
static const char* wallpaper = NULL;
|
||||
|
||||
static bool init = false;
|
||||
|
||||
@@ -48,7 +52,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
|
||||
if(init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,15 +60,16 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Xfce") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Xfce4") == 0)
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4) == 0)
|
||||
{
|
||||
themeName = ffSettingsGetXFConf(instance, "xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetXFConf(instance, "xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetXFConf(instance, "xfce4-desktop", "/backdrop/screen0/monitor0/workspace0/last-image", FF_VARIANT_TYPE_STRING).strValue;
|
||||
}
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON) == 0)
|
||||
{
|
||||
themeName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
@@ -72,7 +77,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
|
||||
cursorTheme = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
}
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_MATE) == 0)
|
||||
{
|
||||
themeName = ffSettingsGet(instance, "/org/mate/interface/gtk-theme", "org.mate.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGet(instance, "/org/mate/interface/icon-theme", "org.mate.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
@@ -81,19 +86,21 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
|
||||
cursorSize = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
}
|
||||
else if(
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) == 0
|
||||
) {
|
||||
themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGet(instance, "/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
// TODO: support other DEs for wallpaper
|
||||
}
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
|
||||
}
|
||||
|
||||
static void detectGTKFromConfigFile(const char* filename, FFGTKResult* result)
|
||||
@@ -184,6 +191,7 @@ static void detectGTK(const FFinstance* instance, const char* version, FFGTKResu
|
||||
ffStrbufInit(&result.font); \
|
||||
ffStrbufInit(&result.cursor); \
|
||||
ffStrbufInit(&result.cursorSize); \
|
||||
ffStrbufInit(&result.wallpaper); \
|
||||
detectGTK(instance, #version, &result); \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &result;
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_gtk
|
||||
#define FF_INCLUDED_detection_gtk
|
||||
#ifndef FF_INCLUDED_detection_gtkqt_gtkqt
|
||||
#define FF_INCLUDED_detection_gtkqt_gtkqt
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
@@ -12,10 +12,20 @@ typedef struct FFGTKResult
|
||||
FFstrbuf font;
|
||||
FFstrbuf cursor;
|
||||
FFstrbuf cursorSize;
|
||||
FFstrbuf wallpaper;
|
||||
} FFGTKResult;
|
||||
|
||||
typedef struct FFQtResult
|
||||
{
|
||||
FFstrbuf widgetStyle;
|
||||
FFstrbuf colorScheme;
|
||||
FFstrbuf icons;
|
||||
FFstrbuf font;
|
||||
} FFQtResult;
|
||||
|
||||
const FFGTKResult* ffDetectGTK2(const FFinstance* instance);
|
||||
const FFGTKResult* ffDetectGTK4(const FFinstance* instance);
|
||||
const FFGTKResult* ffDetectGTK3(const FFinstance* instance);
|
||||
const FFQtResult* ffDetectQt(const FFinstance* instance);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/qt.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/thread.h"
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -152,9 +152,9 @@ const FFQtResult* ffDetectQt(const FFinstance* instance)
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0)
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
|
||||
detectPlasma(instance, &result);
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "LXQt") == 0)
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT) == 0)
|
||||
detectLXQt(instance, &result);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
@@ -8,7 +8,13 @@ static inline bool strEqual(const char* a, const char* b)
|
||||
|
||||
static const char* getProductName(const FFstrbuf* hwModel)
|
||||
{
|
||||
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L1386
|
||||
// Macbook Pro: https://support.apple.com/en-us/HT201300
|
||||
// Macbook Air: https://support.apple.com/en-us/HT201862
|
||||
// Mac mini: https://support.apple.com/en-us/HT201894
|
||||
// iMac: https://support.apple.com/en-us/HT201634
|
||||
// Mac Pro: https://support.apple.com/en-us/HT202888
|
||||
// Mac Studio: https://support.apple.com/en-us/HT213073
|
||||
|
||||
if(ffStrbufStartsWithS(hwModel, "MacBookPro"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBookPro");
|
||||
@@ -106,20 +112,26 @@ static const char* getProductName(const FFstrbuf* hwModel)
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Mac");
|
||||
if(strEqual(version, "14,6") ||
|
||||
strEqual(version, "14,10")) return "MacBook Pro (16-inch, 2023)";
|
||||
if(strEqual(version, "14,5") ||
|
||||
strEqual(version, "14,9")) return "MacBook Pro (14-inch, 2023)";
|
||||
if(strEqual(version, "14,3")) return "Mac mini (M2, 2023, Two Thunderbolt 4 ports)";
|
||||
if(strEqual(version, "14,12")) return "Mac mini (M2, 2023, Four Thunderbolt 4 ports)";
|
||||
if(strEqual(version, "14,7")) return "MacBook Pro (13-inch, M2, 2022)";
|
||||
if(strEqual(version, "14,2")) return "MacBook Air (M2, 2022)";
|
||||
if(strEqual(version, "13,1")) return "Mac Studio (2022, Two USB-C front ports)";
|
||||
if(strEqual(version, "13,2")) return "Mac Studio (2022, Two Thunderbolt 4 front ports)";
|
||||
if(strEqual(version, "13,1")) return "Mac Studio (M1 Max, 2022, Two USB-C front ports)";
|
||||
if(strEqual(version, "13,2")) return "Mac Studio (M1 Ultra, 2022, Two Thunderbolt 4 front ports)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "iMac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("iMac");
|
||||
if(strEqual(version, "21,1") ||
|
||||
strEqual(version, "21,2")) return "iMac (24-inch, M1, 2021)";
|
||||
if(strEqual(version, "21,1")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(strEqual(version, "21,2")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports)";
|
||||
if(strEqual(version, "20,1") ||
|
||||
strEqual(version, "20,2")) return "iMac (Retina 5K, 27-inch, 2020)";
|
||||
if(strEqual(version, "19,1") ||
|
||||
strEqual(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(strEqual(version, "19,1")) return "iMac (Retina 5K, 27-inch, 2019)";
|
||||
if(strEqual(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(strEqual(version, "Pro1,1")) return "iMac Pro (2017)";
|
||||
if(strEqual(version, "18,3")) return "iMac (Retina 5K, 27-inch, 2017)";
|
||||
if(strEqual(version, "18,2")) return "iMac (Retina 4K, 21.5-inch, 2017)";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "host.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_icons
|
||||
#define FF_INCLUDED_detection_icons
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
const char* ffDetectIcons(const FFinstance* instance, FFstrbuf* result);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "icons.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
const char* ffDetectIcons(const FFinstance* instance, FFstrbuf* result)
|
||||
{
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
return "Icons aren't supported in TTY";
|
||||
|
||||
const FFstrbuf* plasma = &ffDetectQt(instance)->icons;
|
||||
const FFstrbuf* gtk2 = &ffDetectGTK2(instance)->icons;
|
||||
const FFstrbuf* gtk3 = &ffDetectGTK3(instance)->icons;
|
||||
const FFstrbuf* gtk4 = &ffDetectGTK4(instance)->icons;
|
||||
|
||||
if(plasma->length == 0 && gtk2->length == 0 && gtk3->length == 0 && gtk4->length == 0)
|
||||
return "No icons could be found";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY gtkPretty;
|
||||
ffStrbufInit(>kPretty);
|
||||
ffParseGTK(>kPretty, gtk2, gtk3, gtk4);
|
||||
|
||||
if(plasma->length > 0)
|
||||
{
|
||||
ffStrbufAppend(result, plasma);
|
||||
ffStrbufAppendS(result, " [QT]");
|
||||
|
||||
if(gtkPretty.length > 0)
|
||||
ffStrbufAppendS(result, ", ");
|
||||
}
|
||||
ffStrbufAppend(result, >kPretty);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "icons.h"
|
||||
|
||||
const char* ffDetectIcons(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFstrbuf* result)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "icons.h"
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
const char* ffDetectIcons(FF_MAYBE_UNUSED const FFinstance* instance, FFstrbuf* result)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu) failed";
|
||||
|
||||
// Whether these icons are hidden
|
||||
uint32_t ThisPC = 0, UsersFiles = 0, RemoteNetwork = 0, RecycleBin = 0, ControlPanel = 0;
|
||||
ffRegReadUint(hKey, L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", &ThisPC, NULL);
|
||||
ffRegReadUint(hKey, L"{59031a47-3f72-44a7-89c5-5595fe6b30ee}", &UsersFiles, NULL);
|
||||
ffRegReadUint(hKey, L"{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}", &RemoteNetwork, NULL);
|
||||
ffRegReadUint(hKey, L"{645FF040-5081-101B-9F08-00AA002F954E}", &RecycleBin, NULL);
|
||||
ffRegReadUint(hKey, L"{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}", &ControlPanel, NULL);
|
||||
|
||||
if (!ThisPC)
|
||||
ffStrbufAppendS(result, "This PC, ");
|
||||
if (!UsersFiles)
|
||||
ffStrbufAppendS(result, "User's Files, ");
|
||||
if (!RemoteNetwork)
|
||||
ffStrbufAppendS(result, "Remote Network, ");
|
||||
if (!RecycleBin)
|
||||
ffStrbufAppendS(result, "Recycle Bin, ");
|
||||
if (!ControlPanel)
|
||||
ffStrbufAppendS(result, "Control Panel");
|
||||
|
||||
ffStrbufTrimRight(result, ' ');
|
||||
ffStrbufTrimRight(result, ',');
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
|
||||
__attribute__((__unused__))
|
||||
FF_MAYBE_UNUSED
|
||||
static void getLocaleFromEnv(FFstrbuf* locale)
|
||||
{
|
||||
ffStrbufAppendS(locale, getenv("LANG"));
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
typedef struct FFLocalIpResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf addr;
|
||||
bool ipv6;
|
||||
FFstrbuf ipv4;
|
||||
FFstrbuf ipv6;
|
||||
FFstrbuf mac;
|
||||
} FFLocalIpResult;
|
||||
|
||||
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results);
|
||||
|
||||
@@ -2,21 +2,48 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/socket.h> // FreeBSD needs this for AF_INET
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <net/if_dl.h>
|
||||
#else
|
||||
#include <linux/if_packet.h>
|
||||
#endif
|
||||
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, bool ipv6)
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, int type)
|
||||
{
|
||||
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
ffStrbufInitS(&ip->name, name);
|
||||
ffStrbufInitS(&ip->addr, addr);
|
||||
ip->ipv6 = ipv6;
|
||||
FFLocalIpResult* ip = NULL;
|
||||
|
||||
FF_LIST_FOR_EACH(FFLocalIpResult, temp, *list)
|
||||
{
|
||||
if (!ffStrbufEqualS(&temp->name, name)) continue;
|
||||
ip = temp;
|
||||
break;
|
||||
}
|
||||
if (!ip)
|
||||
{
|
||||
ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
ffStrbufInitS(&ip->name, name);
|
||||
ffStrbufInit(&ip->ipv4);
|
||||
ffStrbufInit(&ip->ipv6);
|
||||
ffStrbufInit(&ip->mac);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AF_INET:
|
||||
ffStrbufSetS(&ip->ipv4, addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ffStrbufSetS(&ip->ipv6, addr);
|
||||
break;
|
||||
case -1:
|
||||
ffStrbufSetS(&ip->mac, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
@@ -30,8 +57,7 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
// loop back
|
||||
if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop)
|
||||
if ((ifa->ifa_flags & IFF_LOOPBACK) && !(instance->config.localIpShowType & FF_LOCALIP_TYPE_LOOP_BIT))
|
||||
continue;
|
||||
|
||||
if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
|
||||
@@ -39,26 +65,49 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
// IPv4
|
||||
if (!instance->config.localIpShowIpV4)
|
||||
if (!(instance->config.localIpShowType & FF_LOCALIP_TYPE_IPV4_BIT))
|
||||
continue;
|
||||
|
||||
struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, false);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET);
|
||||
}
|
||||
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
// IPv6
|
||||
if (!instance->config.localIpShowIpV6)
|
||||
if (!(instance->config.localIpShowType & FF_LOCALIP_TYPE_IPV6_BIT))
|
||||
continue;
|
||||
|
||||
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, true);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6);
|
||||
}
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
else if (ifa->ifa_addr->sa_family == AF_LINK)
|
||||
{
|
||||
if (!(instance->config.localIpShowType & FF_LOCALIP_TYPE_MAC_BIT))
|
||||
continue;
|
||||
|
||||
char addressBuffer[32];
|
||||
uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr);
|
||||
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, -1);
|
||||
}
|
||||
#else
|
||||
else if (ifa->ifa_addr->sa_family == AF_PACKET)
|
||||
{
|
||||
if (!(instance->config.localIpShowType & FF_LOCALIP_TYPE_MAC_BIT))
|
||||
continue;
|
||||
|
||||
char addressBuffer[32];
|
||||
uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr;
|
||||
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, -1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
|
||||
|
||||
@@ -1,21 +1,45 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "localip.h"
|
||||
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, bool ipv6)
|
||||
static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp)
|
||||
{
|
||||
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
ffStrbufInitS(&ip->name, name);
|
||||
ffStrbufInitS(&ip->addr, addr);
|
||||
ip->ipv6 = ipv6;
|
||||
FFLocalIpResult* ip = NULL;
|
||||
|
||||
if (newIp)
|
||||
{
|
||||
ip = (FFLocalIpResult*) ffListAdd(list);
|
||||
ffStrbufInitS(&ip->name, name);
|
||||
ffStrbufInit(&ip->ipv4);
|
||||
ffStrbufInit(&ip->ipv6);
|
||||
ffStrbufInit(&ip->mac);
|
||||
}
|
||||
else
|
||||
{
|
||||
ip = ffListGet(list, list->length - 1);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AF_INET:
|
||||
ffStrbufSetS(&ip->ipv4, value);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ffStrbufSetS(&ip->ipv6, value);
|
||||
break;
|
||||
case -1:
|
||||
ffStrbufSetS(&ip->mac, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
{
|
||||
IP_ADAPTER_ADDRESSES* adapter_addresses = NULL;
|
||||
IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL;
|
||||
|
||||
// Start with a 16 KB buffer and resize if needed -
|
||||
// multiple attempts in case interfaces change while
|
||||
@@ -27,11 +51,10 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
assert(adapter_addresses);
|
||||
|
||||
DWORD error = GetAdaptersAddresses(
|
||||
AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
instance->config.localIpShowType & FF_LOCALIP_TYPE_IPV4_BIT
|
||||
? instance->config.localIpShowType & FF_LOCALIP_TYPE_IPV6_BIT ? AF_UNSPEC : AF_INET
|
||||
: AF_INET6,
|
||||
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
|
||||
NULL,
|
||||
adapter_addresses,
|
||||
&adapter_addresses_buffer_size);
|
||||
@@ -47,41 +70,47 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
|
||||
// Iterate through all of the adapters
|
||||
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
|
||||
{
|
||||
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK && !instance->config.localIpShowLoop)
|
||||
bool isLoop = adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK;
|
||||
if (isLoop && !(instance->config.localIpShowType & FF_LOCALIP_TYPE_LOOP_BIT))
|
||||
continue;
|
||||
|
||||
bool newIp = true;
|
||||
|
||||
char name[128];
|
||||
WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL);
|
||||
if (instance->config.localIpNamePrefix.length && strncmp(name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
if (instance->config.localIpShowType & FF_LOCALIP_TYPE_MAC_BIT && adapter->PhysicalAddressLength == 6)
|
||||
{
|
||||
char addressBuffer[32];
|
||||
uint8_t* ptr = adapter->PhysicalAddress;
|
||||
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||
addNewIp(results, name, addressBuffer, -1, newIp);
|
||||
newIp = false;
|
||||
}
|
||||
|
||||
for (IP_ADAPTER_UNICAST_ADDRESS* ifa = adapter->FirstUnicastAddress; ifa; ifa = ifa->Next)
|
||||
{
|
||||
if (ifa->Address.lpSockaddr->sa_family == AF_INET)
|
||||
{
|
||||
// IPv4
|
||||
if (!instance->config.localIpShowIpV4)
|
||||
continue;
|
||||
|
||||
SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, name, addressBuffer, false);
|
||||
addNewIp(results, name, addressBuffer, AF_INET, newIp);
|
||||
newIp = false;
|
||||
}
|
||||
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
|
||||
{
|
||||
// IPv6
|
||||
if (!instance->config.localIpShowIpV6)
|
||||
continue;
|
||||
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, name, addressBuffer, false);
|
||||
addNewIp(results, name, addressBuffer, AF_INET6, newIp);
|
||||
newIp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(adapter_addresses);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const FFMediaResult* ffDetectMedia(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFMediaResult,
|
||||
ffStrbufInitA(&result.error, 0);
|
||||
ffStrbufInit(&result.busNameShort);
|
||||
ffStrbufInit(&result.playerId);
|
||||
ffStrbufInit(&result.player);
|
||||
ffStrbufInit(&result.song);
|
||||
ffStrbufInit(&result.artist);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
typedef struct FFMediaResult
|
||||
{
|
||||
FFstrbuf error;
|
||||
FFstrbuf busNameShort; //e.g. plasma-browser-integration
|
||||
FFstrbuf playerId; // Bus name on Linux, app bundle name on macOS. e.g. plasma-browser-integration
|
||||
FFstrbuf player; // e.g. Google Chrome
|
||||
FFstrbuf song;
|
||||
FFstrbuf artist;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user