Compare commits

...

130 Commits

Author SHA1 Message Date
Carter Li f6702d83d0 Merge pull request #422 from LinusDierheimer/dev
Release 1.10.0
2023-02-21 18:48:33 +08:00
李通洲 b1a779c178 Release: 1.10.0; update changelog 2023-02-21 15:54:12 +08:00
李通洲 cc1260ee3c FFvaluestore: fix UB reported by clang 2023-02-21 10:21:07 +08:00
李通洲 92b1788825 Platform: refactor; remove extra / 2023-02-21 10:02:04 +08:00
李通洲 efdbeb585b Battery (Android): add temperature 2023-02-21 09:43:22 +08:00
李通洲 304f171d38 Battery / Wifi (Android): add more debug messages 2023-02-21 09:42:41 +08:00
李通洲 9a3909f8ba Memory (Windows): check for error cases 2023-02-16 17:19:43 +08:00
李通洲 6ca4b5391b Library: refactor FF_LIBRARY_LOAD to use __cleanup__ 2023-02-15 14:51:04 +08:00
李通洲 cabd36d078 CpuUsage (apple): simplify implementation 2023-02-14 19:24:29 +08:00
李通洲 64bacd2572 Vulkan: refactor directory structures 2023-02-14 17:52:58 +08:00
李通洲 47be29b89c DateTime: refactor directory structures 2023-02-14 17:49:23 +08:00
李通洲 6407bf6a1f GTK / QT: refactor directory structures 2023-02-14 17:47:39 +08:00
李通洲 e2d145cf31 Memory (Apple): use sysctl instead of sysctlbyname 2023-02-14 17:31:07 +08:00
李通洲 b634c70f80 Temp (Apple): support memory temperature detection for future use 2023-02-14 17:29:21 +08:00
李通洲 e29169711c TerminalShell (Linux): tidy 2023-02-14 16:33:58 +08:00
李通洲 662ddac050 Vulkan: detect vmem (#416) 2023-02-11 16:05:54 +08:00
李通洲 b90d543afc GPU (Windows): support vmem total / usage detection #416
vmem usage detection is guarded behind `--allow-slow-operations`
because it's really slow sometimes
2023-02-11 16:05:54 +08:00
李通洲 f05d134aa7 OpenCL: tidy 2023-02-10 11:20:27 +08:00
李通洲 74a68aa626 CMake: remove unused options 2023-02-10 11:08:05 +08:00
Linus Dierheimer fcc5170a10 Disk(Linux): Better detection of physical drives 2023-02-09 11:20:40 +01:00
李通洲 3a9403a2f1 Packages (Windows): optimise 2023-02-09 09:51:51 +08:00
李通洲 ff170caff6 GPU (Windows): fix duplicated entries. 2023-02-09 09:46:53 +08:00
李通洲 532b493c42 Doc: update changelog 2023-02-09 00:19:19 +08:00
李通洲 51cc87e0db GPU (Windows): keep WMI query as a slow operation for accurate results 2023-02-09 00:17:13 +08:00
李通洲 878d4608b1 Packages (Windows): fix scoop packages count in non-default install path 2023-02-09 00:15:35 +08:00
李通洲 03d1c62787 Packages (Windows): honor $SCOOP when detecting scoop packages
Fix #417
2023-02-08 22:49:30 +08:00
李通洲 5c46271898 GPU (Windows): fix driver version detection 2023-02-08 21:23:45 +08:00
李通洲 9a7c732555 OpenCL: fix Windows support
They changed the dll file name in the latest release
2023-02-08 21:07:36 +08:00
李通洲 8ffe6fda9b Battery: drop powrprof.dll dependency 2023-02-08 15:11:50 +08:00
Linus Dierheimer e563417166 Build test: Build as release with debug info 2023-02-07 12:21:47 +01:00
Linus Dierheimer ec3f9acd76 Cmake debug: change to exe linker only 2023-02-07 12:18:30 +01:00
李通洲 6c22fd6902 Host: update newest product name data (macOS) 2023-02-07 14:35:50 +08:00
李通洲 82b10a527b GPU: support driver version detection 2023-02-07 11:17:46 +08:00
李通洲 92c744d971 Windows: support for global config path in MSYS2 environment 2023-02-06 22:53:47 +08:00
李通洲 7a691a4286 Windows: add 32bit support 2023-02-06 16:03:38 +08:00
李通洲 e98489a74b Locale: tweaks 2023-02-06 14:55:57 +08:00
李通洲 7a5da23b0c Bluetooth: silense compiler warnings 2023-02-06 14:55:57 +08:00
李通洲 edf4837ed6 GPU: refactor vendor detection code 2023-02-06 14:55:57 +08:00
李通洲 749bd8db0e Gamepad (Windows): display attached controllers only 2023-02-05 21:42:59 +08:00
李通洲 d2460d8e85 GPU (Windows): try improving performance 2023-02-05 18:59:20 +08:00
Linus Dierheimer eead4cf70e Revert "Pipeline: debug"
This reverts commit 291f88b1e4.
2023-02-03 18:53:52 +01:00
Linus Dierheimer 291f88b1e4 Pipeline: debug 2023-02-03 18:48:40 +01:00
Linus Dierheimer 93f1a44d0f Revert "Pipeline: debug"
This reverts commit 550e107683.
2023-02-03 18:43:15 +01:00
Linus Dierheimer 550e107683 Pipeline: debug 2023-02-03 18:41:08 +01:00
Linus Dierheimer 7a8b94b6d4 Fix build with older libnm versions 2023-02-03 14:20:15 +01:00
Linus Dierheimer 2005b396fa Add missing comma 2023-02-03 13:38:37 +01:00
Linus Dierheimer 2a80b5ed36 Pipeline(Linux): Build on Ubuntu 20.04 2023-02-03 13:37:15 +01:00
Linus Dierheimer 47a32c725d X11: init scaled resolution with normal resolution 2023-02-03 11:22:34 +01:00
李通洲 fc26acd0ab DisplayServer: fix scaled resolution detection (Linux) 2023-02-03 10:34:17 +08:00
Linus Dierheimer e57f7d378a Wayland: support basic scale factors
#414
2023-02-02 18:16:56 +01:00
Linus Dierheimer 6de74587bd Update terminator font detection 2023-02-02 17:14:53 +01:00
Linus Dierheimer 6e5e7851d4 Merge pull request #415 from CSoellinger/feat/add-terminator-terminal-support
Add terminator terminal support
2023-02-02 17:01:59 +01:00
CSoellinger 84ccda45b0 feat: simplify parse prop file config 2023-02-02 16:16:24 +01:00
李通洲 ec3cd6cc68 LocalIP: support multiline compact mode 2023-02-02 22:25:31 +08:00
李通洲 cae9fee30a LocalIP (Windows): fix ipv6 detection 2023-02-02 21:01:50 +08:00
李通洲 f0111a8037 Windows: silense compiler warnings 2023-02-02 19:17:51 +08:00
CSoellinger 8fad590f8b feat: add terminator terminal support 2023-02-02 11:40:37 +01:00
CSoellinger 2ae5a9d725 Merge pull request #1 from LinusDierheimer/dev
Update dev
2023-02-02 11:25:06 +01:00
李通洲 8153c8b82c LocalIP: support --localip-compact-type option (#408) 2023-02-02 17:50:22 +08:00
Linus Dierheimer 159f4a3a3c Fix build on apple 2023-02-01 18:35:06 +01:00
Linus Dierheimer 3dbfff57e7 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-02-01 15:56:32 +01:00
Linus Dierheimer a063cd4feb Correctly handle zfs pools
#413
2023-02-01 15:56:25 +01:00
李通洲 dc5da3c3b3 Flashfetch: add missing modules 2023-02-01 21:54:45 +08:00
李通洲 79c9c19b1a Doc: document gamepad module support 2023-02-01 21:47:35 +08:00
李通洲 b49b583e64 Gamepad (Linux): add support 2023-02-01 21:46:23 +08:00
李通洲 0b8e8ad4f2 Gamepad (macOS): add support 2023-02-01 21:46:23 +08:00
李通洲 7fc2c4dcf1 Gamepad: init support for Windows 2023-02-01 21:46:23 +08:00
李通洲 a74cbc5781 Sound: fix memleak, update config file 2023-02-01 20:28:55 +08:00
Linus Dierheimer 619ec921ee Update changelog 2023-02-01 11:16:01 +01:00
Linus Dierheimer 1b23c9a030 Update changelog 2023-02-01 11:14:54 +01:00
Linus Dierheimer d4c11b9a1f Merge pull request #411 from CSoellinger/fix/detect-wm-mutter
fix: add another mutter detection for linux mint 21.1 (cinnamon)
2023-02-01 11:11:00 +01:00
CSoellinger 55da030e2a fix: move mutter(muffin) detection to get FF_WM_PRETTY_MUFFIN back 2023-02-01 10:50:31 +01:00
Linus Dierheimer c64f306550 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-02-01 10:43:32 +01:00
Linus Dierheimer 7ee4a648d0 Small fix to muffin theme detection 2023-02-01 10:43:24 +01:00
Linus Dierheimer 78ca4e7c87 Merge pull request #412 from CSoellinger/fix/spell-correction
fix: spell correction
2023-02-01 10:30:59 +01:00
CSoellinger 7a2826358b fix: spell correction 2023-02-01 10:08:08 +01:00
CSoellinger df84721b55 fix: add another mutter detection for linux mint 21.1 (cinnamon) 2023-02-01 10:01:47 +01:00
李通洲 f53a1f785d Doc: update changelog 2023-01-31 23:32:49 +08:00
李通洲 4f3b9776ae WmTheme (Windows): align output format to winfetch
Ref: https://github.com/lptstr/winfetch/commit/0358deea5e3ca03086be4984b905a0a534f8d1a5
2023-01-31 23:26:50 +08:00
李通洲 39f47d65a9 Sound: remove manufacturer detection
as it's only implemented on macOS
2023-01-31 22:39:27 +08:00
李通洲 a92e6b6d91 Sound (macOS): fix active device detection; fix memleaks; don't use deprecated properties 2023-01-31 22:37:48 +08:00
李通洲 00e044c431 Sound: change option --sound-show-all to --sound-type 2023-01-31 21:12:47 +08:00
李通洲 7132762c9c Sound (Linux): small fixes
1. treat PA_PORT_AVAILABLE_UNKNOWN as active so that the default speaker is active now
2. load `libpulse.so` as suggested in `config_user.txt`
2023-01-31 20:55:01 +08:00
李通洲 2476b44300 Global: add support for colored percentage numbers output 2023-01-31 19:42:11 +08:00
李通洲 d36e827ec9 Fastfetch: remove --nocache which has been deprecated for a while 2023-01-31 17:15:45 +08:00
Linus Dierheimer a37115cb00 Fix build on windows 2023-01-30 23:23:14 +01:00
Linus Dierheimer 7dc73c61ab WMDE: avoid the use of magick strings across the project
There are probably more, but those are all i found for now.
2023-01-30 18:46:39 +01:00
李通洲 a14ef06d14 TerminalShell (Windows): fix a rare case that fails to detect terminal 2023-01-29 23:29:53 +08:00
李通洲 212e7aa47e CI: test for memleaks 2023-01-29 13:12:50 +08:00
李通洲 ebe26eddf0 Windows: minify included headers 2023-01-29 10:21:23 +08:00
李通洲 517e3fcff9 WMI: add timeout to prevent CI from hanging
Hard coded 5 seconds
2023-01-29 10:10:31 +08:00
Linus Dierheimer 679162c762 --list-logos: list custom logos too 2023-01-28 17:19:45 +01:00
李通洲 e4973b3262 IO: fix Windows part; silense warnings 2023-01-28 22:46:59 +08:00
Linus Dierheimer a1ea7804f3 IO: Separate platform specific implementations 2023-01-28 12:40:12 +01:00
Linus Dierheimer 2c51d55ba2 IO: don't require posix specific stuff for ffPathExists 2023-01-28 11:52:23 +01:00
Linus Dierheimer 3b0e1a5833 Image: Use correct cache dir 2023-01-28 11:28:05 +01:00
Linus Dierheimer 9bb6d8fd6e Allow loading images from data dirs too
#375
2023-01-28 11:14:16 +01:00
李通洲 4afba798ba Sound: add missing command helpers 2023-01-28 13:46:40 +08:00
李通洲 f4cefe955b Sound: always initialize identifier and destroy it to avoid memleaks 2023-01-28 13:46:40 +08:00
李通洲 1c38ebb551 Parsing: only disable warning when necessary 2023-01-28 13:46:40 +08:00
Linus Dierheimer 14dcafe2ca Bluetooth(Linux): Refactor code a bit 2023-01-27 18:21:42 +01:00
Linus Dierheimer cf78216d78 Sound(Linux): Don't abuse manufactor 2023-01-27 18:03:57 +01:00
Linus Dierheimer 0c256e2908 Just try with all on and all of 2023-01-27 13:01:24 +01:00
Linus Dierheimer 00fc3f1a1d Add a workflow that tests different build config combinations 2023-01-27 12:56:36 +01:00
Linus Dierheimer 672e309d89 Small fixes 2023-01-27 11:21:01 +01:00
李通洲 b0c19256f0 Bluetooth: silense warnings 2023-01-27 13:10:06 +08:00
李通洲 205e664b4d Sound (Windows): show more detailed information 2023-01-27 13:08:07 +08:00
Linus Dierheimer cb466aec08 Linux: Fix build without dbus
#405
2023-01-26 22:08:55 +01:00
Linus Dierheimer 33f3744a63 Sound(Linux): Treat default port as always active
This fixes no shown sound devices when no audio is currently played
2023-01-26 17:25:14 +01:00
Linus Dierheimer 7adb1606f1 GH Actions: build with libpulse 2023-01-26 15:50:35 +01:00
Linus Dierheimer 184ada6ae8 Sound(linux): Implement using libpulse
Also differentiate between active and main device(s)
2023-01-26 15:48:28 +01:00
李通洲 856c9d58b8 TerminalFont: tweaks 2023-01-26 01:15:33 +08:00
李通洲 f3fba8a389 CI: build with alsa enabled 2023-01-26 01:14:22 +08:00
李通洲 10468a559a Doc: document Sound module support 2023-01-26 01:14:22 +08:00
李通洲 c4c9f02433 Sound (Linux): add dirty support 2023-01-26 01:14:22 +08:00
李通洲 f2dd288a0d Sound: don't leak memory 2023-01-26 00:36:45 +08:00
李通洲 aa36a83182 Windows: silense some warnings 2023-01-25 17:25:05 +08:00
李通洲 dd9047c4e9 Sound (Windows): add support 2023-01-25 17:17:31 +08:00
李通洲 11634b9a67 Windows: add com helper 2023-01-25 17:17:19 +08:00
李通洲 d832324306 Sound (macOS): new module 2023-01-25 14:28:13 +08:00
Linus Dierheimer a7af5c4f66 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-25 00:03:01 +01:00
Linus Dierheimer 0f2022bd40 Bluetooth: Don't leak memory 2023-01-25 00:02:54 +01:00
李通洲 e598598ca8 Bluetooth (macOS): add support
Limitation: no battery level
2023-01-24 22:13:53 +08:00
李通洲 85599fcf53 Bluetooth (Windows): add support
Limitation: no HLE devices, no battery level
2023-01-24 21:01:21 +08:00
Linus Dierheimer 6961488d38 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-24 12:02:47 +01:00
Linus Dierheimer 209d0c98d9 Bluetooth: Support multiple devices 2023-01-24 12:02:20 +01:00
Linus Dierheimer d718cc997c Merge pull request #404 from LinusDierheimer/master
Master
2023-01-24 10:51:03 +01:00
Linus Dierheimer 4967d0a222 Bluetooth: Build on unsupported platforms 2023-01-24 10:46:00 +01:00
Linus Dierheimer 17ebd5cea8 Merge 2023-01-24 10:40:29 +01:00
Linus Dierheimer 25e81b39f9 Bluetooth module 2023-01-24 10:39:33 +01:00
147 changed files with 3652 additions and 1404 deletions
+104 -26
View File
@@ -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 libcjson-dev libnm-dev libpulse-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_LIBCJSON=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ 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 libcjson-dev libnm-dev libpulse-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
@@ -153,22 +188,6 @@ jobs:
- 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-cjson mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd
- 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/*
+34
View File
@@ -1,3 +1,37 @@
# 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:
+45 -14
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 1.9.1
VERSION 1.10.0
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
@@ -70,10 +70,10 @@ cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32"
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_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" 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 +117,7 @@ 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} -rdynamic")
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
include(CheckIPOSupported)
@@ -226,15 +226,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
@@ -246,7 +246,7 @@ set(LIBFASTFETCH_SRC
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 +254,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 +273,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 +289,7 @@ set(LIBFASTFETCH_SRC
src/modules/display.c
src/modules/separator.c
src/modules/shell.c
src/modules/sound.c
src/modules/media.c
src/modules/terminal.c
src/modules/terminalfont.c
@@ -304,10 +307,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 +324,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 +333,10 @@ 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/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,7 +344,8 @@ 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
@@ -349,10 +358,12 @@ if(LINUX)
)
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
@@ -365,6 +376,7 @@ elseif(ANDROID)
src/detection/gpu/gpu_nosupport.c
src/detection/host/host_android.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,6 +384,7 @@ 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
@@ -384,11 +397,14 @@ elseif(ANDROID)
)
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 +419,10 @@ 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/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,7 +430,8 @@ 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
@@ -426,11 +444,13 @@ elseif(BSD)
)
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
@@ -444,6 +464,7 @@ elseif(APPLE)
src/detection/gpu/gpu_apple.c
src/detection/host/host_apple.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,6 +472,7 @@ 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
@@ -465,10 +487,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
@@ -481,6 +505,7 @@ elseif(WIN32)
src/detection/gpu/gpu_windows.cpp
src/detection/host/host_windows.c
src/detection/localip/localip_windows.c
src/detection/gamepad/gamepad_windows.cpp
src/detection/media/media_nosupport.c
src/detection/memory/memory_windows.c
src/detection/opengl/opengl_windows.c
@@ -488,6 +513,7 @@ elseif(WIN32)
src/detection/packages/packages_windows.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_windows.cpp
src/detection/sound/sound_windows.cpp
src/detection/swap/swap_windows.cpp
src/detection/terminalfont/terminalfont_windows.c
src/detection/terminalshell/terminalshell_windows.cpp
@@ -496,6 +522,7 @@ elseif(WIN32)
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
@@ -646,6 +673,10 @@ ff_lib_enable(FREETYPE
"freetype2"
"FreeType2"
)
ff_lib_enable(PULSE
"libpulse"
"Pulse"
)
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
@@ -666,34 +697,34 @@ if(APPLE)
PRIVATE "-framework OpenCL"
PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreWLAN"
PRIVATE "-framework CoreAudio"
PRIVATE "-framework CoreVideo"
PRIVATE "-framework IOBluetooth"
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
PRIVATE "-weak_framework DisplayServices -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 "dinput8"
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
+5 -4
View File
@@ -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
@@ -88,7 +89,7 @@ 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, Wifi, WM, WMTheme
```
##### Builtin logos
@@ -113,7 +114,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, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal
```
## Building
+7
View File
@@ -42,6 +42,7 @@ __fastfetch_complete_help()
"vulkan-format"
"opengl-format"
"opencl-format"
"bluetooth-format"
)
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
}
@@ -185,6 +186,7 @@ __fastfetch_completion()
"--localip-show-ipv6"
"--localip-show-loop"
"--localip-name-prefix"
"--localip-compact-type"
"--escape-bedrock"
"--pipe"
"--title-fqdn"
@@ -198,6 +200,7 @@ __fastfetch_completion()
"--gpu-hide-integrated"
"--gpu-hide-discrete"
"--disk-show-unknown"
"--bluetooth-show-disconnected"
)
local FF_OPTIONS_STRING=(
@@ -349,6 +352,9 @@ __fastfetch_completion()
"--users-key"
"--users-format"
"--users-error"
"--bluetooth-key"
"--bluetooth-format"
"--bluetooth-error"
)
local FF_OPTIONS_PATH=(
@@ -374,6 +380,7 @@ __fastfetch_completion()
"--lib-glx"
"--lib-osmesa"
"--lib-opencl"
"--lib-pulse"
"--battery-dir"
)
+1 -1
View File
@@ -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: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
+3 -2
View File
@@ -5,7 +5,7 @@
--processes-format Count: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; 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: {}
+50
View File
@@ -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
View File
@@ -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
+206
View File
@@ -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
+57
View File
@@ -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
+1
View File
@@ -2,6 +2,7 @@
#include "common/format.h"
#include "common/parsing.h"
#include "util/textModifier.h"
#include "util/stringUtils.h"
#include <inttypes.h>
+19 -2
View File
@@ -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"
@@ -115,6 +113,9 @@ static void defaultConfig(FFinstance* instance)
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,6 +139,7 @@ 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);
@@ -159,6 +161,10 @@ static void defaultConfig(FFinstance* instance)
instance->config.diskShowUnknown = false;
instance->config.diskShowSubvolumes = false;
instance->config.bluetoothShowDisconnected = false;
instance->config.soundType = FF_SOUND_TYPE_MAIN;
ffStrbufInitA(&instance->config.batteryDir, 0);
ffStrbufInitA(&instance->config.separatorString, 0);
@@ -166,7 +172,9 @@ static void defaultConfig(FFinstance* instance)
instance->config.localIpShowIpV4 = true;
instance->config.localIpShowIpV6 = false;
instance->config.localIpShowLoop = false;
instance->config.localIpV6First = false;
ffStrbufInit(&instance->config.localIpNamePrefix);
instance->config.localIpCompactType = FF_LOCALIP_COMPACT_TYPE_NONE;
instance->config.publicIpTimeout = 0;
ffStrbufInit(&instance->config.publicIpUrl);
@@ -210,6 +218,8 @@ FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*)
#if !(defined(__APPLE__) || defined(_WIN32))
#include "detection/gtk_qt/gtk_qt.h"
#define FF_DETECT_QT_GTK 1
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*)
@@ -377,6 +387,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 +413,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);
@@ -505,6 +519,9 @@ void ffListFeatures()
#ifdef FF_HAVE_FREETYPE
"freetype\n"
#endif
#ifdef FF_HAVE_PULSE
"libpulse\n"
#endif
#ifdef FF_HAVE_LIBNM
"libnm\n"
#endif
-30
View File
@@ -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
+104
View File
@@ -0,0 +1,104 @@
#pragma once
#ifndef FF_INCLUDED_common_io_io
#define FF_INCLUDED_common_io_io
#include "util/FFstrbuf.h"
#ifdef _WIN32
#include <fileapi.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);
#endif // FF_INCLUDED_common_io_io
+97 -144
View File
@@ -1,15 +1,10 @@
#include "fastfetch.h"
#include "common/io.h"
#include "io.h"
#include <unistd.h>
#include <fcntl.h>
#ifdef _WIN32
#include <fileapi.h>
#else
#include <termios.h>
#include <poll.h>
#endif
#include <sys/stat.h>
#include <termios.h>
#include <poll.h>
#include <dirent.h>
static void createSubfolders(const char* fileName)
{
@@ -20,41 +15,15 @@ static void createSubfolders(const char* fileName)
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
{
mkdir(path.chars
#ifndef WIN32
, S_IRWXU | S_IRGRP | S_IROTH
#endif
);
}
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
++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;
@@ -70,52 +39,10 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
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;
@@ -150,40 +77,19 @@ bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
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);
ssize_t readed = ffReadFDData(fd, dataSize, data);
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;
@@ -191,55 +97,32 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
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)
bool ffPathExists(const char* path, FFPathType type)
{
struct stat fileStat;
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
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, ...)
{
#ifndef WIN32
struct termios oldTerm, newTerm;
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
@@ -278,8 +161,78 @@ void ffGetTerminalResponse(const char* request, const char* format, ...)
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
#else
//Unimplemented
FF_UNUSED(request, format);
#endif
}
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);
}
+163
View File
@@ -0,0 +1,163 @@
#include "io.h"
static void createSubfolders(const char* fileName)
{
FFstrbuf path;
ffStrbufInit(&path);
while(*fileName != '\0')
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
CreateDirectoryA(path.chars, NULL);
++fileName;
}
ffStrbufDestroy(&path);
}
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
{
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);
return ret;
}
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 handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return -1;
ssize_t readed = ffReadFDData(handle, dataSize, data);
CloseHandle(handle);
return readed;
}
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
{
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 = ffAppendFDBuffer(handle, buffer);
CloseHandle(handle);
return ret;
}
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
View File
@@ -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);
+10
View File
@@ -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)
@@ -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
+1 -1
View File
@@ -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>
+2 -2
View File
@@ -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>
@@ -309,7 +309,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);
+24 -1
View File
@@ -247,10 +247,22 @@
# 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
# 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:
@@ -295,6 +307,9 @@
#--opengl-key OpenGL
#--opencl-key OpenCL
#--users-key Users
#--bluetooth-key Bluetooth
#--sound-key Sound
#--gamepad-key Gamepad
# Format options:
# Sets the format string for module values.
@@ -339,6 +354,9 @@
#--opengl-format
#--opencl-format
#--users-format
#--bluetooth-format
#--sound-format
#--gamepad-format
# Error options:
# Sets the format string to use if an error occured
@@ -383,6 +401,9 @@
#--opengl-error
#--opencl-error
#--users-error
#--bluetooth-error
#--sound-error
#--gamepad-error
# Library options:
# Sets an user specific path to a library to load.
@@ -408,4 +429,6 @@
#--lib-osmesa /usr/lib/libOSMesa.so
#--lib-opencl /usr/lib/libOpenCL.so
#--lib-cjson /usr/lib/libcjson.so
#--lib-cjson /usr/lib/libasound.so
#--lib-freetype /data/data/com.termux/files/usr/lib
#--lib-pulse /usr/lib/libpulse.so
+36 -30
View File
@@ -98,38 +98,44 @@ 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-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
--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-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
--localip-compact-type <str>: Show IPs in one line. Should be either none, oneline, multiline. Default is none
--localip-v6first <?value>: Set if ipv6 should be printed first. Default is false
--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, 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
View File
@@ -1,5 +1,6 @@
Battery
Bios
Bluetooth
Board
Break
Chassis
+20 -3
View File
@@ -4,16 +4,22 @@
#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
}))
return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " BatteryStatus` failed";
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
if(buffer.length == 0)
return "`" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` prints empty";
BatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
@@ -28,6 +34,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 -1
View File
@@ -1,5 +1,5 @@
#include "fastfetch.h"
#include "common/io.h"
#include "common/io/io.h"
#include "battery.h"
#include <dirent.h>
+13
View File
@@ -8,6 +8,19 @@
#include <winternl.h>
#include <powrprof.h>
#ifdef FF_USE_WIN_NTAPI
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPowerInformation(
IN POWER_INFORMATION_LEVEL InformationLevel,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength);
#define CallNtPowerInformation NtPowerInformation
#endif
static inline void wrapCloseHandle(HANDLE* handle)
{
if(*handle)
+1 -1
View File
@@ -1,5 +1,5 @@
#include "bios.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
+15
View File
@@ -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);
)
}
+25
View File
@@ -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
+93
View File
@@ -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, ',');
}
}
}
+203
View File
@@ -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");
}
+114
View File
@@ -0,0 +1,114 @@
#include "bluetooth.h"
#include "util/windows/unicode.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 -1
View File
@@ -1,5 +1,5 @@
#include "board.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
+1 -1
View File
@@ -1,5 +1,5 @@
#include "brightness.h"
#include "common/io.h"
#include "common/io/io.h"
#include <dirent.h>
+1 -1
View File
@@ -1,5 +1,5 @@
#include "chassis.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
+2 -2
View File
@@ -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");
+10 -15
View File
@@ -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;
}
+6 -5
View File
@@ -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,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"
+39 -16
View File
@@ -1,5 +1,7 @@
#include "disk.h"
#include "util/stringUtils.h"
#include <limits.h>
#include <ctype.h>
#include <dirent.h>
@@ -13,24 +15,35 @@
#define readdir readdir64
#endif
static bool isPhysicalDevice(const char* device)
static bool isPhysicalDevice(FFstrbuf* device)
{
struct stat deviceStat;
if(stat(device->chars, &deviceStat) != 0)
return false;
//Ignore all devices that are not block devices
if(!S_ISBLK(deviceStat.st_mode))
return false;
//Ignore all devices that are not physical devices
//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;
//ZFS root pool. The format is rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>
if(ffStrbufStartsWithS(device, "rpool/"))
return true;
//Pseudo filesystems don't have a device in /dev
const char* devPrefix = "/dev/";
if(strncmp(device, devPrefix, strlen(devPrefix)) != 0)
if(!ffStrbufStartsWithS(device, "/dev/"))
return false;
//Skip /dev/ prefix
device += strlen(devPrefix);
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;
@@ -141,6 +154,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,6 +163,11 @@ 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;
}
@@ -196,12 +215,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 +223,16 @@ void ffDetectDisksImpl(FFDiskResult* disks)
ffStrbufInit(device);
appendNextEntry(device, &currentPos);
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, &currentPos);
@@ -5,6 +5,35 @@
#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 struct FFDisplayResult
{
uint32_t width;
@@ -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);
+86 -54
View File
@@ -5,20 +5,30 @@
#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;
} WaylandData;
typedef struct WaylandDisplay
{
int32_t width;
int32_t height;
int32_t refreshRate;
int32_t scale;
} WaylandDisplay;
#ifndef __FreeBSD__
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
{
@@ -49,25 +59,76 @@ static void stubListener(void* data, ...)
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
{
WaylandData* wldata = data;
FF_UNUSED(output);
wldata->ffwl_proxy_destroy((struct wl_proxy*) output);
if(!(flags & WL_OUTPUT_MODE_CURRENT))
return;
if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0)
WaylandDisplay* display = data;
display->width = width;
display->height = height;
display->refreshRate = refreshRate;
}
#if WAYLAND_VERSION_MINOR >= 2
static void waylandOutputScaleListener(void* data, struct wl_output* output, int32_t scale)
{
FF_UNUSED(output);
WaylandDisplay* display = data;
display->scale = scale;
}
#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 = {
.width = 0,
.height = 0,
.refreshRate = 0,
.scale = 1,
};
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 = waylandOutputScaleListener,
#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, &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);
ffdsAppendDisplay(wldata->result,
(uint32_t) display.width,
(uint32_t) display.height,
ffdsParseRefreshRate(display.refreshRate / 1000),
(uint32_t) (display.width / display.scale),
(uint32_t) (display.height / display.scale)
);
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 +136,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 +146,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 +155,23 @@ 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);
waylandDetectWM(ffwl_display_get_fd(data.display), result);
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
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 +179,16 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
};
data.ffwl_proxy_add_listener(registry, (void(**)(void)) &registry_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 +219,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);
}
+30 -26
View File
@@ -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,21 @@ 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);
}
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 +192,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 +213,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 +245,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 +311,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 +323,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 +412,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();
+13 -21
View File
@@ -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));
@@ -120,18 +117,17 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* 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
);
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
@@ -187,8 +183,8 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
0,
0
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height
);
}
@@ -224,8 +220,8 @@ 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
);
free(crtcInfoReply);
@@ -269,8 +265,8 @@ 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
);
}
@@ -329,8 +325,8 @@ 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
);
}
@@ -368,10 +364,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 +380,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
+16 -23
View File
@@ -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);
@@ -81,20 +79,19 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
Screen* screen = ScreenOfDisplay(display, i);
ffdsAppendDisplay(
result,
(uint32_t) screen->width,
(uint32_t) screen->height,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
0,
0,
0
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen)
);
}
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
@@ -145,8 +142,8 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
0,
0
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height
);
}
@@ -176,8 +173,8 @@ 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
);
data->ffXRRFreeCrtcInfo(crtcInfo);
@@ -212,8 +209,8 @@ 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
);
}
@@ -266,8 +263,8 @@ 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)
);
}
@@ -297,10 +294,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 +305,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
+1 -1
View File
@@ -1,5 +1,5 @@
#include "common/font.h"
#include "common/io.h"
#include "common/io/io.h"
#include "font.h"
#import <AppKit/NSFont.h>
+1 -2
View File
@@ -1,6 +1,5 @@
#include "detection/qt.h"
#include "detection/gtk.h"
#include "common/font.h"
#include "detection/gtk_qt/gtk_qt.h"
#include "font.h"
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
+16
View File
@@ -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
+41
View File
@@ -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;
}
+42
View File
@@ -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";
}
+32
View File
@@ -0,0 +1,32 @@
extern "C" {
#include "gamepad.h"
}
#include <initguid.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
CALLBACK BOOL DIEnumDevicesCallback(LPCDIDEVICEINSTANCEA lpddi, LPVOID pvRef)
{
FFlist* devices = (FFlist*) pvRef;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitF(&device->identifier, "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
lpddi->guidInstance.Data1, lpddi->guidInstance.Data2, lpddi->guidInstance.Data3,
lpddi->guidInstance.Data4[0], lpddi->guidInstance.Data4[1], lpddi->guidInstance.Data4[2], lpddi->guidInstance.Data4[3],
lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]);
ffStrbufInitS(&device->name, lpddi->tszInstanceName);
return DIENUM_CONTINUE;
}
extern "C"
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
{
IDirectInput8A* dinput;
if (!SUCCEEDED(DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8A, (void**)&dinput, NULL)))
return "DirectInput8Create() failed";
dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, devices, DIEDFL_ATTACHEDONLY);
dinput->Release();
return NULL;
}
+31 -5
View File
@@ -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(ffDetectGPUImpl(&result, instance) != NULL)
{
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
result = vulkan->gpus;
+17 -5
View File
@@ -7,29 +7,41 @@
#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
{
uint64_t id;
FFGpuType type;
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
double temperature;
int coreCount;
FFGPUMemory dedicated;
FFGPUMemory shared;
} FFGPUResult;
const FFlist* ffDetectGPU(const FFinstance* instance);
const char* ffGetGPUVendorString(unsigned vendorId);
#endif
+6 -18
View File
@@ -60,32 +60,20 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
FFGPUResult* gpu = ffListAdd(gpus);
gpu->id = 0;
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);
+10 -22
View File
@@ -1,11 +1,12 @@
#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>
@@ -23,25 +24,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;
@@ -214,6 +199,9 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
FFGPUResult* gpu = ffListAdd(results);
gpu->id = 0;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
ffStrbufInit(&gpu->vendor);
pciDetectVendorName(gpu, pci, device);
@@ -263,17 +251,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
}
+110 -43
View File
@@ -1,12 +1,89 @@
extern "C" {
#include "gpu.h"
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
}
#ifdef FF_USE_WIN_GPU_DXGI
#include "util/windows/wmi.hpp"
#include <dxgi.h>
#include <wchar.h>
#include <inttypes.h>
static const char* detectWithRegistry(FFlist* gpus)
{
// Ref: https://github.com/lptstr/winfetch/pull/155
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\DirectX", &hKey, nullptr))
return "Open \"HKLM\\SOFTWARE\\Microsoft\\DirectX\" failed";
uint64_t lastSeen;
if(!ffRegReadUint64(hKey, L"LastSeen", &lastSeen, nullptr))
return "Read \"HKLM\\SOFTWARE\\Microsoft\\DirectX\\LastSeen\" failed";
DWORD index = 0;
wchar_t subKeyName[64];
while(true)
{
DWORD subKeySize = sizeof(subKeyName) / sizeof(*subKeyName);
if(RegEnumKeyExW(hKey, index++, subKeyName, &subKeySize, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS)
break;
FF_HKEY_AUTO_DESTROY hSubKey = NULL;
if(!ffRegOpenKeyForRead(hKey, subKeyName, &hSubKey, nullptr))
continue;
uint64_t adapterLastSeen;
if(!ffRegReadUint64(hSubKey, L"LastSeen", &adapterLastSeen, nullptr) || lastSeen != adapterLastSeen)
continue;
uint32_t softwareAdapter;
if(!ffRegReadUint(hSubKey, L"SoftwareAdapter", &softwareAdapter, nullptr) || softwareAdapter)
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->id = 0;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
ffRegReadUint64(hSubKey, L"AdapterLuid", &gpu->id, nullptr);
ffRegReadStrbuf(hSubKey, L"Description", &gpu->name, nullptr);
uint32_t vendorId;
if(ffRegReadUint(hSubKey, L"VendorId", &vendorId, nullptr))
ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(vendorId));
uint64_t dedicatedVideoMemory = 0;
if(ffRegReadUint64(hSubKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, nullptr))
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
uint64_t dedicatedSystemMemory, sharedSystemMemory;
if(ffRegReadUint64(hSubKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, nullptr) &&
ffRegReadUint64(hSubKey, L"SharedSystemMemory", &sharedSystemMemory, nullptr))
{
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
gpu->shared.total = sharedSystemMemory;
}
uint64_t driverVersion;
if(ffRegReadUint64(hSubKey, L"DriverVersion", &driverVersion, nullptr))
{
ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64 ".%" PRIu64 ".%" PRIu64,
(driverVersion >> 48) & 0xFFFF,
(driverVersion >> 32) & 0xFFFF,
(driverVersion >> 16) & 0xFFFF,
(driverVersion >> 0) & 0xFFFF);
}
}
return nullptr;
}
static const char* detectWithDxgi(FFlist* gpus)
{
@@ -25,15 +102,12 @@ static const char* detectWithDxgi(FFlist* gpus)
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
gpu->dedicated.total = gpu->dedicated.total = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
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->vendor);
ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(desc.VendorId));
gpu->id = (uint64_t&)desc.AdapterLuid;
ffStrbufInit(&gpu->name);
ffStrbufSetWS(&gpu->name, desc.Description);
@@ -41,6 +115,8 @@ static const char* detectWithDxgi(FFlist* gpus)
ffStrbufInit(&gpu->driver);
gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
gpu->dedicated.total = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory;
gpu->shared.total = desc.SharedSystemMemory;
adapter->Release();
@@ -50,56 +126,47 @@ static const char* detectWithDxgi(FFlist* gpus)
pFactory->Release();
return NULL;
return nullptr;
}
#else
#include "util/windows/wmi.hpp"
static const char* detectWithWmi(FFlist* gpus)
static const char* detectMemoryUsage(FFlist* gpus)
{
FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr);
FFWmiQuery query(L"SELECT Name, DedicatedUsage, SharedUsage FROM Win32_PerfRawData_GPUPerformanceCounters_GPUAdapterMemory", nullptr);
if(!query)
return "Query WMI service failed";
FF_STRBUF_AUTO_DESTROY name;
ffStrbufInit(&name);
while(FFWmiRecord record = query.next())
{
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
record.getString(L"Name", &name); // luid_0x00000000_0x000146E8_phys_0
assert(name.length == strlen("luid_0x00000000_0x000146E8_phys_0"));
ffStrbufSubstrBefore(&name, strlen("luid_0x00000000_0x000146E8")); // luid_0x00000000_0x000146E8
ffStrbufSubstrAfter(&name, strlen("luid_0x00000000_0x") - 1); // 000146E8
uint64_t luid = strtoull(name.chars, nullptr, 16);
gpu->type = FF_GPU_TYPE_UNKNOWN;
ffStrbufInit(&gpu->vendor);
record.getString(L"AdapterCompatibility", &gpu->vendor);
if(ffStrbufStartsWithS(&gpu->vendor, "Intel "))
FF_LIST_FOR_EACH(FFGPUResult, gpu, *gpus)
{
//Intel returns "Intel Corporation", not sure about AMD
ffStrbufSetS(&gpu->vendor, "Intel");
if (gpu->id != luid) continue;
record.getUnsigned(L"DedicatedUsage", &gpu->dedicated.used);
record.getUnsigned(L"SharedUsage", &gpu->shared.used);
break;
}
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)
const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance)
{
FF_UNUSED(instance);
const char* error = detectWithRegistry(gpus);
if (error)
error = detectWithDxgi(gpus);
#ifdef FF_USE_WIN_GPU_DXGI
return detectWithDxgi(gpus);
#else
return detectWithWmi(gpus);
#endif
if (!error && gpus->length > 0 && instance->config.allowSlowOperations)
detectMemoryUsage(gpus);
return error;
}
@@ -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"
@@ -56,7 +56,7 @@ 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;
@@ -64,7 +64,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul
cursorTheme = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue;
cursorSize = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
}
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 +72,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,9 +81,9 @@ 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;
@@ -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"
@@ -14,8 +14,17 @@ typedef struct FFGTKResult
FFstrbuf cursorSize;
} 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);
+19 -7
View File
@@ -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 -1
View File
@@ -1,5 +1,5 @@
#include "host.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/processing.h"
#include <stdlib.h>
+1 -1
View File
@@ -5,7 +5,7 @@
#include <stdlib.h>
#include <locale.h>
__attribute__((__unused__))
FF_MAYBE_UNUSED
static void getLocaleFromEnv(FFstrbuf* locale)
{
ffStrbufAppendS(locale, getenv("LANG"));
+1 -1
View File
@@ -77,7 +77,7 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
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, true);
}
}
}
+51 -211
View File
@@ -8,208 +8,75 @@
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/library.h"
#include "common/parsing.h"
#include <dbus/dbus.h>
#define FF_DBUS_ITER_CONTINUE(iterator) \
{ \
if(!data->ffdbus_message_iter_has_next(&iterator)) \
break; \
data->ffdbus_message_iter_next(&iterator); \
continue; \
}
typedef struct DBusData
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
{
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)
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)
DBusConnection *connection;
} DBusData;
static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
{
int argType = data->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_STRING)
{
const char* value = NULL;
data->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;
data->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
return getValue(&subIter, result, data);
//At this point we have an array
bool foundAValue = false;
while(true)
{
if(getValue(&subIter, result, data))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(subIter);
}
if(foundAValue)
ffStrbufSubstrBefore(result, result->length - 2);
return foundAValue;
}
static DBusMessage* getReply(DBusMessage* request, DBusData* data)
{
DBusPendingCall* pendingCall = NULL;
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, FF_DBUS_TIMEOUT_MILLISECONDS);
data->ffdbus_message_unref(request);
if(!succesfull || pendingCall == NULL)
return NULL;
data->ffdbus_connection_flush(data->connection);
data->ffdbus_pending_call_block(pendingCall);
DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pendingCall);
data->ffdbus_pending_call_unref(pendingCall);
return reply;
}
static DBusMessage* getProperty(const char* busName, const char* objectPath, const char* interface, const char* property, DBusData* data)
{
DBusMessage* message = data->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
if(message == NULL)
return NULL;
DBusMessageIter requestIterator;
data->ffdbus_message_iter_init_append(message, &requestIterator);
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
data->ffdbus_message_unref(message);
return NULL;
}
if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
data->ffdbus_message_unref(message);
return NULL;
}
return getReply(message, data);
}
static void getPropertyString(const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, objectPath, interface, property, data);
if(reply == NULL)
return;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
return;
}
getValue(&rootIterator, result, data);
data->ffdbus_message_unref(reply);
}
static bool getBusProperties(const char* busName, FFMediaResult* result, DBusData* data)
{
DBusMessage* reply = getProperty(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata", data);
DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata");
if(reply == NULL)
return false;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator))
if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
data->ffdbus_message_unref(reply);
data->lib->ffdbus_message_unref(reply);
return false;
}
if(data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
if(data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT)
{
data->ffdbus_message_unref(reply);
data->lib->ffdbus_message_unref(reply);
return false;
}
DBusMessageIter variantIterator;
data->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
if(data->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
data->lib->ffdbus_message_iter_recurse(&rootIterator, &variantIterator);
if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY)
{
data->ffdbus_message_unref(reply);
data->lib->ffdbus_message_unref(reply);
return false;
}
DBusMessageIter arrayIterator;
data->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator);
while(true)
{
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
DBusMessageIter dictIterator;
data->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
data->lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
if(data->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(data->lib->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
if(!data->ffdbus_message_iter_has_next(&dictIterator))
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(!data->lib->ffdbus_message_iter_has_next(&dictIterator))
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
const char* key;
data->ffdbus_message_iter_get_basic(&dictIterator, &key);
data->lib->ffdbus_message_iter_get_basic(&dictIterator, &key);
data->ffdbus_message_iter_next(&dictIterator);
data->lib->ffdbus_message_iter_next(&dictIterator);
if(strcmp(key, "xesam:title") == 0)
getValue(&dictIterator, &result->song, data);
ffDBusGetValue(data, &dictIterator, &result->song);
else if(strcmp(key, "xesam:album") == 0)
getValue(&dictIterator, &result->album, data);
ffDBusGetValue(data, &dictIterator, &result->album);
else if(strcmp(key, "xesam:artist") == 0)
getValue(&dictIterator, &result->artist, data);
ffDBusGetValue(data, &dictIterator, &result->artist);
else if(strcmp(key, "xesam:url") == 0)
getValue(&dictIterator, &result->url, data);
ffDBusGetValue(data, &dictIterator, &result->url);
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0)
break;
FF_DBUS_ITER_CONTINUE(arrayIterator)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
}
data->ffdbus_message_unref(reply);
data->lib->ffdbus_message_unref(reply);
if(result->song.length == 0)
{
@@ -223,20 +90,20 @@ static bool getBusProperties(const char* busName, FFMediaResult* result, DBusDat
ffStrbufAppendS(&result->busNameShort, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
//We found a song, get the player name
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player, data);
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player);
if(result->player.length == 0)
getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player, data);
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player);
if(result->player.length == 0)
ffStrbufAppend(&result->player, &result->busNameShort);
return true;
}
static void getCustomBus(const FFinstance* instance, FFMediaResult* result, DBusData* data)
static void getCustomBus(FFDBusData* data, const FFinstance* instance, FFMediaResult* result)
{
if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX))
{
getBusProperties(instance->config.playerName.chars, result, data);
getBusProperties(data, instance->config.playerName.chars, result);
return;
}
@@ -244,88 +111,61 @@ static void getCustomBus(const FFinstance* instance, FFMediaResult* result, DBus
ffStrbufInit(&busName);
ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX);
ffStrbufAppend(&busName, &instance->config.playerName);
getBusProperties(busName.chars, result, data);
getBusProperties(data, busName.chars, result);
ffStrbufDestroy(&busName);
}
static void getBestBus(FFMediaResult* result, DBusData* data)
static void getBestBus(FFDBusData* data, FFMediaResult* result)
{
if(
getBusProperties(FF_DBUS_MPRIS_PREFIX"spotify", result, data) ||
getBusProperties(FF_DBUS_MPRIS_PREFIX"vlc", result, data) ||
getBusProperties(FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result, data)
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"spotify", result) ||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"vlc", result) ||
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result)
) return;
DBusMessage* message = data->ffdbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
if(message == NULL)
return;
DBusMessage* reply = getReply(message, data);
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
if(reply == NULL)
return;
DBusMessageIter rootIterator;
if(!data->ffdbus_message_iter_init(reply, &rootIterator) || data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator) || data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIterator;
data->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
while(true)
{
if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(arrayIterator)
if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
const char* busName;
data->ffdbus_message_iter_get_basic(&arrayIterator, &busName);
data->lib->ffdbus_message_iter_get_basic(&arrayIterator, &busName);
if(strncmp(busName, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0)
FF_DBUS_ITER_CONTINUE(arrayIterator)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
if(getBusProperties(busName, result, data))
if(getBusProperties(data, busName, result))
break;
FF_DBUS_ITER_CONTINUE(arrayIterator)
FF_DBUS_ITER_CONTINUE(data, &arrayIterator)
}
data->ffdbus_message_unref(reply);
data->lib->ffdbus_message_unref(reply);
}
static const char* getMedia(const FFinstance* instance, FFMediaResult* result)
{
DBusData data;
FF_LIBRARY_LOAD(dbus, &instance->config.libDBus, "dlopen dbus failed", "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dbus, dbus_bus_get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_new_method_call)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_init)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_init_append)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_append_basic)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_get_arg_type)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_get_basic)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_recurse)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_has_next)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_next)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_unref)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_connection_send_with_reply)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_connection_flush)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_pending_call_block)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_pending_call_steal_reply)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_pending_call_unref)
data.connection = ffdbus_bus_get(DBUS_BUS_SESSION, NULL);
if(data.connection == NULL)
{
dlclose(dbus);
return "Failed to connect to session dbus";
}
FFDBusData data;
const char* error = ffDBusLoadData(instance, DBUS_BUS_SESSION, &data);
if(error != NULL)
return error;
if(instance->config.playerName.length > 0)
getCustomBus(instance, result, &data);
getCustomBus(&data, instance, result);
else
getBestBus(result, &data);
getBestBus(&data, result);
dlclose(dbus);
return NULL;
}
+10 -9
View File
@@ -1,30 +1,31 @@
#include "memory.h"
#include "common/sysctl.h"
#include <string.h>
#include <mach/mach.h>
#include <sys/sysctl.h>
void ffDetectMemory(FFMemoryStorage* ram)
{
ram->bytesTotal = (uint64_t) ffSysctlGetInt64("hw.memsize", 0);
if(ram->bytesTotal == 0)
size_t length = sizeof(ram->bytesTotal);
if (sysctl((int[]){ CTL_HW, HW_MEMSIZE }, 2, &ram->bytesTotal, &length, NULL, 0))
{
ffStrbufAppendS(&ram->error, "Failed to read hw.memsize");
return;
}
uint32_t pagesize = (uint32_t) ffSysctlGetInt("hw.pagesize", 0);
if(pagesize == 0)
uint32_t pagesize;
length = sizeof(pagesize);
if (sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &pagesize, &length, NULL, 0))
{
ffStrbufAppendS(&ram->error, "Failed to read hw.pagesize");
return;
}
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
vm_statistics_data_t vmstat;
if(host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) (&vmstat), &count) != KERN_SUCCESS)
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
vm_statistics64_data_t vmstat;
if(host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) (&vmstat), &count) != KERN_SUCCESS)
{
ffStrbufAppendS(&ram->error, "Failed to read vm statistics");
ffStrbufAppendS(&ram->error, "Failed to read host_statistics64");
return;
}
+5 -1
View File
@@ -5,7 +5,11 @@ void ffDetectMemory(FFMemoryStorage* ram)
MEMORYSTATUSEX statex = {
.dwLength = sizeof(statex),
};
GlobalMemoryStatusEx(&statex);
if (!GlobalMemoryStatusEx(&statex))
{
ffStrbufAppendS(&ram->error, "GlobalMemoryStatusEx() failed");
return;
}
ram->bytesTotal = statex.ullTotalPhys;
ram->bytesUsed = statex.ullTotalPhys - statex.ullAvailPhys;
}
+3 -9
View File
@@ -133,9 +133,7 @@ static const char* eglPrint(FFinstance* instance, FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
const char* error = eglHandleData(result, &eglData);
dlclose(egl);
return error;
return eglHandleData(result, &eglData);
}
#endif //FF_HAVE_EGL
@@ -252,9 +250,7 @@ static const char* glxPrint(FFinstance* instance, FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCloseDisplay);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFree);
const char* error = glxHandleData(result, &data);
dlclose(glx);
return error;
return glxHandleData(result, &data);
}
#endif //FF_HAVE_GLX
@@ -310,9 +306,7 @@ static const char* osMesaPrint(FFinstance* instance, FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaDestroyContext);
const char* error = osMesaHandleData(result, &data);
dlclose(osmesa);
return error;
return osMesaHandleData(result, &data);
}
#endif //FF_HAVE_OSMESA
+1
View File
@@ -1,6 +1,7 @@
#include "os.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "util/stringUtils.h"
#include <string.h>
#include <stdlib.h>
+1 -1
View File
@@ -31,7 +31,7 @@ static const char* getOsNameByWinbrand(FFstrbuf* osName)
//https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string
if(HMODULE __attribute__((__cleanup__(wrapFreeLibrary))) hWinbrand = LoadLibraryW(L"winbrand.dll"))
{
auto BrandingFormatString = (PWSTR(WINAPI*)(PCWSTR))GetProcAddress(hWinbrand, "BrandingFormatString");
auto BrandingFormatString = (PWSTR(WINAPI*)(PCWSTR))(void*)GetProcAddress(hWinbrand, "BrandingFormatString");
if(!BrandingFormatString)
return "GetProcAddress(BrandingFormatString) failed";
+1
View File
@@ -1,5 +1,6 @@
#include "packages.h"
#include "common/parsing.h"
#include "util/stringUtils.h"
#include <dirent.h>
+3 -11
View File
@@ -1,5 +1,5 @@
#include "packages.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/parsing.h"
#include "common/processing.h"
#include "common/properties.h"
@@ -88,7 +88,7 @@ static uint32_t countFilesRecursiveImpl(FFstrbuf* baseDirPath, const char* filen
ffStrbufAppendC(baseDirPath, '/');
ffStrbufAppendS(baseDirPath, filename);
bool exists = ffFileExists(baseDirPath->chars, S_IFREG);
bool exists = ffPathExists(baseDirPath->chars, FF_PATHTYPE_FILE);
ffStrbufSubstrBefore(baseDirPath, baseDirPathLength);
if(exists)
return 1;
@@ -129,7 +129,7 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons
static uint32_t getNixPackagesImpl(char* path)
{
//Nix detection is kinda slow, so we only do it if the dir exists
if(!ffFileExists(path, S_IFDIR))
if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY))
return 0;
FFstrbuf output;
@@ -229,23 +229,16 @@ static uint32_t getRpmFromLibrpm(const FFinstance* instance)
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
if(ffrpmReadConfigFiles(NULL, NULL) != 0)
{
dlclose(rpm);
return 0;
}
rpmts ts = ffrpmtsCreate();
if(ts == NULL)
{
dlclose(rpm);
return 0;
}
rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0);
if(mi == NULL)
{
ffrpmtsFree(ts);
dlclose(rpm);
return 0;
}
@@ -253,7 +246,6 @@ static uint32_t getRpmFromLibrpm(const FFinstance* instance)
ffrpmdbFreeIterator(mi);
ffrpmtsFree(ts);
dlclose(rpm);
return count > 0 ? (uint32_t) count : 0;
}
+27 -13
View File
@@ -1,11 +1,13 @@
#include "packages.h"
#include "util/stringUtils.h"
#include <handleapi.h>
#include <fileapi.h>
static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type)
static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type, const char* ignore)
{
uint32_t counter = 0;
bool flag = ignore == NULL;
WIN32_FIND_DATAA wfd;
HANDLE hFind = FindFirstFileA(searchPath, &wfd);
@@ -13,8 +15,13 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix *
{
do // Managed to locate and create an handle to that folder.
{
if(wfd.dwFileAttributes & type)
counter++;
if(!(wfd.dwFileAttributes & type)) continue;
if(!flag && strcasecmp(ignore, wfd.cFileName) == 0)
{
flag = true;
continue;
}
counter++;
} while (FindNextFileA(hFind, &wfd));
FindClose(hFind);
@@ -27,12 +34,21 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix *
static void detectScoop(const FFinstance* instance, FFPackagesResult* result)
{
char scoopPath[MAX_PATH + 3];
strcpy(scoopPath, instance->state.platform.homeDir.chars);
strncat(scoopPath, "/scoop/apps/*", sizeof(scoopPath) - 1 - strlen(scoopPath));
result->scoop = getNumElements(scoopPath, FILE_ATTRIBUTE_DIRECTORY);
if(result->scoop > 0)
result->scoop--; // scoop
FF_STRBUF_AUTO_DESTROY scoopPath;
ffStrbufInitA(&scoopPath, MAX_PATH + 3);
const char* scoopEnv = getenv("SCOOP");
if(ffStrSet(scoopEnv))
{
ffStrbufAppendS(&scoopPath, scoopEnv);
ffStrbufAppendS(&scoopPath, "/apps/*");
}
else
{
ffStrbufAppendS(&scoopPath, instance->state.platform.homeDir.chars);
ffStrbufAppendS(&scoopPath, "/scoop/apps/*");
}
result->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
}
static void detectChoco(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result)
@@ -44,9 +60,7 @@ static void detectChoco(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesRe
char chocoPath[MAX_PATH + 3];
strcpy(chocoPath, chocoInstall);
strncat(chocoPath, "/lib/*", sizeof(chocoPath) - 1 - strlen(chocoPath));
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY);
if(result->choco > 0)
result->choco--; // choco
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco");
}
static void detectPacman(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result)
@@ -59,7 +73,7 @@ static void detectPacman(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesR
char pacmanPath[MAX_PATH + 3];
strcpy(pacmanPath, msystemPrefix);
strncat(pacmanPath, "/../var/lib/pacman/local/*", sizeof(pacmanPath) - 1 - strlen(pacmanPath));
result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY);
result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL);
}
void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result)
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_qt
#define FF_INCLUDED_detection_qt
#include "fastfetch.h"
typedef struct FFQtResult
{
FFstrbuf widgetStyle;
FFstrbuf colorScheme;
FFstrbuf icons;
FFstrbuf font;
} FFQtResult;
const FFQtResult* ffDetectQt(const FFinstance* instance);
#endif
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#ifndef FF_INCLUDED_detection_sound_sound
#define FF_INCLUDED_detection_sound_sound
#include "fastfetch.h"
typedef struct FFSoundDevice
{
FFstrbuf identifier;
FFstrbuf name;
uint8_t volume; // 0-100%
bool main;
bool active;
} FFSoundDevice;
const char* ffDetectSound(const FFinstance* instance, FFlist* devices /* List of FFSoundDevice */);
#endif
+81
View File
@@ -0,0 +1,81 @@
#include "sound.h"
#include "util/apple/cf_helpers.h"
#include <CoreAudio/CoreAudio.h>
const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFSoundDevice */)
{
AudioDeviceID mainDeviceId;
UInt32 dataSize = sizeof(mainDeviceId);
if(AudioObjectGetPropertyData(kAudioObjectSystemObject, &(AudioObjectPropertyAddress){
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeOutput,
kAudioObjectPropertyElementMain
}, 0, NULL, &dataSize, &mainDeviceId) != kAudioHardwareNoError)
return "AudioObjectGetPropertyData(kAudioHardwarePropertyDefaultOutputDevice) failed";
AudioObjectID deviceIds[32] = {};
dataSize = sizeof(deviceIds);
if(AudioObjectGetPropertyData(kAudioObjectSystemObject, &(AudioObjectPropertyAddress){
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeOutput,
kAudioObjectPropertyElementMain
}, 0, NULL, &dataSize, &deviceIds) != kAudioHardwareNoError)
return "AudioObjectGetPropertyData(kAudioHardwarePropertyDevices) failed";
for(uint32_t index = 0, length = dataSize / sizeof(*deviceIds); index < length; ++index)
{
AudioDeviceID deviceId = deviceIds[index];
uint32_t muted;
dataSize = sizeof(muted);
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
kAudioDevicePropertyMute,
kAudioObjectPropertyScopeOutput,
kAudioObjectPropertyElementMain
}, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError)
continue;
FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices);
device->main = deviceId == mainDeviceId;
device->active = false;
device->volume = 0;
ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId);
ffStrbufInit(&device->name);
uint32_t active;
dataSize = sizeof(active);
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeOutput,
kAudioObjectPropertyElementMain
}, 0, NULL, &dataSize, &active) == kAudioHardwareNoError)
device->active = !!active;
if (!muted)
{
float volume;
dataSize = sizeof(volume);
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
kAudioDevicePropertyVolumeScalar,
kAudioObjectPropertyScopeOutput,
kAudioObjectPropertyElementMain
}, 0, NULL, &dataSize, &volume) == kAudioHardwareNoError)
device->volume = (uint8_t) (volume * 100 + 0.5);
}
CFStringRef name;
dataSize = sizeof(name);
if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){
kAudioObjectPropertyName,
kAudioObjectPropertyScopeOutput,
kAudioObjectPropertyElementMain
}, 0, NULL, &dataSize, &name) == kAudioHardwareNoError)
{
ffCfStrGetString(name, &device->name);
CFRelease(name);
}
}
return NULL;
}
+130
View File
@@ -0,0 +1,130 @@
#include "sound.h"
#ifdef FF_HAVE_PULSE
#include <common/library.h>
#include <pulse/pulseaudio.h>
static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
{
FF_UNUSED(c);
if(eol > 0 || !i)
return;
FFSoundDevice* device = ffListAdd(userdata);
ffStrbufInitS(&device->identifier, i->name);
ffStrbufInitS(&device->name, i->description);
device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM);
device->active = i->active_port && i->active_port->available != PA_PORT_AVAILABLE_NO;
device->main = false;
}
static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *userdata)
{
FF_UNUSED(c);
if(!i)
return;
FF_LIST_FOR_EACH(FFSoundDevice, device, *(FFlist*)userdata)
{
if(ffStrbufEqualS(&device->identifier, i->default_sink_name))
{
device->main = true;
break;
}
}
}
static const char* detectSound(const FFinstance* instance, FFlist* devices)
{
FF_LIBRARY_LOAD(pulse, &instance->config.libPulse, "Failed to load libpulse" FF_LIBRARY_EXTENSION, "libpulse" FF_LIBRARY_EXTENSION, 0)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_new)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_get_api)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_iterate)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_free)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_new)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_connect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_get_state)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_get_sink_info_list)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_get_server_info)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_unref)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_operation_get_state)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_operation_unref)
pa_mainloop* mainloop = ffpa_mainloop_new();
if(!mainloop)
return "Failed to create pulseaudio mainloop";
pa_mainloop_api* mainloopApi = ffpa_mainloop_get_api(mainloop);
if(!mainloopApi)
{
ffpa_mainloop_free(mainloop);
return "Failed to get pulseaudio mainloop api";
}
pa_context* context = ffpa_context_new(mainloopApi, "fastfetch");
if(!context)
{
ffpa_mainloop_free(mainloop);
return "Failed to create pulseaudio context";
}
if(ffpa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0)
{
ffpa_context_unref(context);
ffpa_mainloop_free(mainloop);
return "Failed to connect to pulseaudio context";
}
int state;
while((state = ffpa_context_get_state(context)) != PA_CONTEXT_READY)
{
if(!PA_CONTEXT_IS_GOOD(state))
{
ffpa_context_unref(context);
ffpa_mainloop_free(mainloop);
return "Failed to get pulseaudio context state";
}
ffpa_mainloop_iterate(mainloop, 1, NULL);
}
pa_operation* operation = ffpa_context_get_sink_info_list(context, paSinkInfoCallback, devices);
if(!operation)
{
ffpa_context_unref(context);
ffpa_mainloop_free(mainloop);
return "Failed to get pulseaudio sink info list";
}
while(ffpa_operation_get_state(operation) == PA_OPERATION_RUNNING)
ffpa_mainloop_iterate(mainloop, 1, NULL);
ffpa_operation_unref(operation);
operation = ffpa_context_get_server_info(context, paServerInfoCallback, devices);
if(operation)
{
while(ffpa_operation_get_state(operation) == PA_OPERATION_RUNNING)
ffpa_mainloop_iterate(mainloop, 1, NULL);
ffpa_operation_unref(operation);
}
ffpa_context_unref(context);
ffpa_mainloop_free(mainloop);
return NULL;
}
#endif // FF_HAVE_PULSE
const char* ffDetectSound(const FFinstance* instance, FFlist* devices)
{
#ifdef FF_HAVE_PULSE
return detectSound(instance, devices);
#else
FF_UNUSED(instance, devices);
return "Fastfetch was built without libpulse support";
#endif
}
+6
View File
@@ -0,0 +1,6 @@
#include "sound.h"
const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */)
{
return "Not supported on this platform";
}
+92
View File
@@ -0,0 +1,92 @@
extern "C" {
#include "sound.h"
#include "util/windows/unicode.h"
}
#include "util/windows/com.hpp"
#include <initguid.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <functiondiscoverykeys_devpkey.h>
const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */)
{
const char* error = ffInitCom();
if (error)
return error;
IMMDeviceEnumerator* FF_AUTO_RELEASE_COM_OBJECT pEnum = NULL;
if (FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&pEnum)))
return "CoCreateInstance(__uuidof(MMDeviceEnumerator)) failed";
LPWSTR mainDeviceId = NULL;
{
IMMDevice* FF_AUTO_RELEASE_COM_OBJECT pDefaultDevice = NULL;
if (FAILED(pEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDefaultDevice)))
return "GetDefaultAudioEndpoint() failed";
if (FAILED(pDefaultDevice->GetId(&mainDeviceId)))
return "pDefaultDevice->GetId() failed";
}
IMMDeviceCollection* FF_AUTO_RELEASE_COM_OBJECT pDevices = NULL;
if (FAILED(pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &pDevices)))
return "EnumAudioEndpoints() failed";
uint32_t deviceCount;
if (FAILED(pDevices->GetCount(&deviceCount)))
return "pDevices->GetCount() failed";
for (uint32_t deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx)
{
IMMDevice* FF_AUTO_RELEASE_COM_OBJECT immDevice = NULL;
if (FAILED(pDevices->Item(deviceIdx, &immDevice)))
continue;
LPWSTR immDeviceId = NULL;
if (FAILED(immDevice->GetId(&immDeviceId)))
continue;
IPropertyStore* FF_AUTO_RELEASE_COM_OBJECT immPropStore;
if (FAILED(immDevice->OpenPropertyStore(STGM_READ, &immPropStore)))
continue;
DWORD immState;
if (FAILED(immDevice->GetState(&immState)))
continue;
FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices);
device->main = wcscmp(mainDeviceId, immDeviceId) == 0;
device->active = !!(immState & DEVICE_STATE_ACTIVE);
device->volume = 0;
ffStrbufInit(&device->identifier);
ffStrbufInit(&device->name);
ffStrbufSetWS(&device->identifier, immDeviceId);
{
PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName;
PropVariantInit(&friendlyName);
if (SUCCEEDED(immPropStore->GetValue(PKEY_Device_FriendlyName, &friendlyName)))
ffStrbufSetWS(&device->name, friendlyName.pwszVal);
}
IAudioEndpointVolume* FF_AUTO_RELEASE_COM_OBJECT immEndpointVolume;
if(SUCCEEDED(immDevice->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**) &immEndpointVolume)))
{
BOOL muted;
if (FAILED(immEndpointVolume->GetMute(&muted)) || !muted)
{
FLOAT volume;
if (SUCCEEDED(immEndpointVolume->GetMasterVolumeLevelScalar(&volume)))
device->volume = (uint8_t) (volume * 100 + 0.5);
}
}
}
return NULL;
}
+2 -2
View File
@@ -1,13 +1,13 @@
#include "swap.h"
#include "common/sysctl.h"
#include <mach/mach.h>
#include <sys/sysctl.h>
void ffDetectSwap(FFMemoryStorage* swap)
{
struct xsw_usage xsw;
size_t size = sizeof(xsw);
if(sysctlbyname("vm.swapusage", &xsw, &size, 0, 0) != 0)
if(sysctl((int[]){ CTL_VM, VM_SWAPUSAGE }, 2, &xsw, &size, NULL, 0) != 0)
{
ffStrbufAppendS(&swap->error, "Failed to read vm.swapusage");
return;
+1 -1
View File
@@ -23,7 +23,7 @@ void ffDetectSwap(FFMemoryStorage* swap)
{
if(!(pstart = (SYSTEM_PAGEFILE_INFORMATION*)realloc(pstart, size)))
{
ffStrbufAppendF(&swap->error, "relloc(pstart, %lu) failed", size);
ffStrbufAppendF(&swap->error, "realloc(pstart, %lu) failed", size);
return;
}
}
+4
View File
@@ -397,6 +397,10 @@ const char *ffDetectCoreTemps(enum FFTempType type, FFlist *result)
case FF_TEMP_BATTERY:
detectTemp(conn, "TB1T", "Battery", result);
break;
case FF_TEMP_MEMORY:
detectTemp(conn, "Tm02", "Memory", result);
break;
}
return NULL;
+2
View File
@@ -26,6 +26,8 @@ enum FFTempType
FF_TEMP_GPU_M2X,
FF_TEMP_BATTERY,
FF_TEMP_MEMORY,
};
const char *ffDetectCoreTemps(enum FFTempType type, FFlist *result);
+1 -1
View File
@@ -1,5 +1,5 @@
#include "fastfetch.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/thread.h"
#include "temps_linux.h"
+45 -13
View File
@@ -115,15 +115,15 @@ static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* conten
CJSONData cjsonData;
FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_Parse, cJSON_Parse@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsObject, cJSON_IsObject@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive, cJSON_GetObjectItemCaseSensitive@8)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsString, cJSON_IsString@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_GetStringValue, cJSON_GetStringValue@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsNumber, cJSON_IsNumber@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_GetNumberValue, cJSON_GetNumberValue@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsArray, cJSON_IsArray@4)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_Delete, cJSON_Delete@4)
const char* error = NULL;
@@ -177,12 +177,11 @@ static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* conten
exit:
cjsonData.ffcJSON_Delete(root);
dlclose(libcjson);
return error;
}
#ifdef _WIN32
#include "common/io.h"
#include "common/io/io.h"
#include <shlobj.h>
#endif
@@ -285,7 +284,7 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbu
static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbuf* terminalExe, FFTerminalFontResult* terminalFont)
{
FF_UNUSED(instance, terminalExe, terminalFont);
ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support");
ffStrbufAppendS(&terminalFont->error, "Fastfetch was built without libcjson support");
}
#endif
@@ -320,6 +319,37 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFo
return true;
}
static void detectTerminator(const FFinstance* instance, FFTerminalFontResult* result)
{
FF_STRBUF_AUTO_DESTROY useSystemFont;
ffStrbufInit(&useSystemFont);
FF_STRBUF_AUTO_DESTROY fontName;
ffStrbufInit(&fontName);
FFpropquery fontQuery[] = {
{"use_system_font =", &useSystemFont},
{"font =", &fontName},
};
if(!ffParsePropFileConfigValues(instance, "terminator/config", 2, fontQuery))
{
ffStrbufAppendS(&result->error, "Couldn't read Terminator config file");
return;
}
if(ffStrbufIgnCaseEqualS(&useSystemFont, "True"))
{
ffFontInitCopy(&result->font, "System");
return;
}
if(fontName.length == 0)
ffFontInitValues(&result->font, "mono", "8");
else
ffFontInitPango(&result->font, fontName.chars);
}
static bool detectWezterm(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminalFontResult* result)
{
FF_STRBUF_AUTO_DESTROY fontName;
@@ -354,6 +384,8 @@ static bool detectTerminalFontCommon(const FFinstance* instance, const FFTermina
{
if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "alacritty"))
detectAlacritty(instance, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "terminator"))
detectTerminator(instance, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui"))
detectWezterm(instance, terminalFont);
@@ -385,7 +417,7 @@ const FFTerminalFontResult* ffDetectTerminalFont(const FFinstance* instance)
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell(instance);
if(terminalShell->terminalProcessName.length == 0)
ffStrbufAppendS(&result.error, "Terminal font needs successfull terminal detection");
ffStrbufAppendS(&result.error, "Terminal font needs successful terminal detection");
else if(!detectTerminalFontCommon(instance, terminalShell, &result))
ffDetectTerminalFontPlatform(instance, terminalShell, &result);
@@ -1,7 +1,7 @@
#include "fastfetch.h"
#include "terminalfont.h"
#include "detection/terminalshell/terminalshell.h"
#include "common/io.h"
#include "common/io/io.h"
#ifdef FF_HAVE_FREETYPE
#include "common/library.h"
@@ -42,14 +42,13 @@ const char* detectTermux(const FFinstance* instance, FFTerminalFontResult* termi
exit:
if(face) ffFT_Done_Face(face);
if(library) ffFT_Done_FreeType(library);
dlclose(freetype);
return error;
#else
FF_UNUSED(terminalFont);
return "fastfetch is built without freetype2 support";
return "Fastfetch was built without freetype2 support";
#endif
}
@@ -62,7 +61,7 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh
return;
}
if(!ffFileExists(FF_TERMUX_FONT_PATH, S_IFREG))
if(!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE))
{
ffFontInitCopy(&terminalFont->font, "monospace");
return;
@@ -4,6 +4,7 @@
#include "common/parsing.h"
#include "detection/terminalshell/terminalshell.h"
#include "detection/displayserver/displayserver.h"
#include "util/stringUtils.h"
static const char* getSystemMonospaceFont(const FFinstance* instance)
{
@@ -1,5 +1,5 @@
#include "common/properties.h"
#include "common/io.h"
#include "common/io/io.h"
#include "detection/terminalshell/terminalshell.h"
#include "terminalfont.h"
#include "util/windows/unicode.h"
+1 -1
View File
@@ -1,5 +1,5 @@
#include "fastfetch.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/processing.h"
#include "common/properties.h"
@@ -12,12 +12,14 @@ typedef struct FFTerminalShellResult
const char* shellExeName; //pointer to a char in shellExe
FFstrbuf shellPrettyName;
FFstrbuf shellVersion;
uint32_t shellPid;
FFstrbuf terminalProcessName;
FFstrbuf terminalExe;
FFstrbuf terminalPrettyName;
const char* terminalExeName; //pointer to a char in terminalExe
FFstrbuf terminalVersion;
uint32_t terminalPid;
FFstrbuf userShellExe;
const char* userShellExeName; //pointer to a char in userShellExe
@@ -1,9 +1,9 @@
#include "fastfetch.h"
#include "common/io.h"
#include "terminalshell.h"
#include "common/io/io.h"
#include "common/parsing.h"
#include "common/processing.h"
#include "common/thread.h"
#include "terminalshell.h"
#include "util/stringUtils.h"
#include <ctype.h>
#include <string.h>
@@ -53,7 +53,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex
size_t size = exe->allocated;
if(!sysctl(
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}, 4,
exe->chars, &size,
exe->chars, &size,
NULL, 0
))
exe->length = (uint32_t)size;
@@ -162,6 +162,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
) {
if (result->shellProcessName.length == 0)
{
result->shellPid = (uint32_t) pid;
ffStrbufSetS(&result->shellProcessName, name);
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
}
@@ -170,6 +171,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
return;
}
result->terminalPid = (uint32_t) pid;
ffStrbufSetS(&result->terminalProcessName, name);
getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName);
}
@@ -336,10 +338,12 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
ffStrbufInitA(&result.shellExe, exePathLen);
result.shellExeName = result.shellExe.chars;
ffStrbufInit(&result.shellVersion);
result.shellPid = 0;
ffStrbufInit(&result.terminalProcessName);
ffStrbufInitA(&result.terminalExe, exePathLen);
result.terminalExeName = result.terminalExe.chars;
result.terminalPid = 0;
ffStrbufInit(&result.userShellExe);
result.userShellExeName = result.userShellExe.chars;
@@ -2,6 +2,7 @@ extern "C" {
#include "terminalshell.h"
#include "common/processing.h"
#include "common/thread.h"
#include "util/mallocHelper.h"
}
#include <processthreadsapi.h>
@@ -10,6 +11,7 @@ extern "C" {
#ifdef FF_USE_WIN_NTAPI
#include <ntstatus.h>
#include <winternl.h>
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName)
@@ -54,6 +56,45 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
return true;
}
static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* result, uint32_t ppid)
{
ULONG size = 0;
if(NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
return false;
size += sizeof(SystemProcessInformation) * 5; //What if new processes are created during two syscalls?
SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PROCESS_INFORMATION*)malloc(size);
if(!pstart)
return false;
if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, nullptr)))
return false;
uint32_t currentProcessId = (uint32_t) GetCurrentProcessId();
for (auto ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset))
{
if ((uint32_t)(uintptr_t) ptr->InheritedFromUniqueProcessId != ppid)
continue;
uint32_t pid = (uint32_t)(uintptr_t) ptr->UniqueProcessId;
if (pid == currentProcessId)
continue;
if(!getProcessInfo(pid, nullptr, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName))
return false;
result->terminalPid = pid;
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4);
return true;
}
return false;
}
#else
#include "util/windows/wmi.hpp"
@@ -95,6 +136,33 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
return true;
}
static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* result, uint32_t ppid)
{
wchar_t sql[256] = {};
swprintf(sql, 256, L"SELECT Name, ExecutablePath, ProcessId FROM Win32_Process WHERE ProcessId <> %" PRIu32 " AND ParentProcessId = %" PRIu32,
(uint32_t) GetCurrentProcessId(),
ppid);
FFWmiQuery query(sql);
if(!query)
return false;
if(FFWmiRecord record = query.next())
{
record.getString(L"Name", &result->terminalProcessName);
record.getString(L"ExecutablePath", &result->terminalExe);
result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\') + 1;
uint64_t pid;
record.getUnsigned(L"ProcessId", &pid);
result->terminalPid = (uint32_t) pid;
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4);
return true;
}
return false;
}
#endif
extern "C" bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
@@ -135,6 +203,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult*
if(instance->config.shellVersion)
fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion);
result->shellPid = pid;
if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "pwsh"))
ffStrbufSetS(&result->shellPrettyName, "PowerShell");
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "powershell"))
@@ -154,7 +223,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult*
module.dwSize = sizeof(module);
for(BOOL success = Module32FirstW(snapshot, &module); success; success = Module32NextW(snapshot, &module))
{
if(wcsncmp(module.szModule, L"clink_dll_", wcslen(L"clink_dll_")) == 0)
if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0)
{
ffStrbufAppendS(&result->shellPrettyName, "CMD (with Clink)");
break;
@@ -170,6 +239,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult*
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "explorer"))
{
ffStrbufSetS(&result->shellPrettyName, "Windows Explorer"); // Started without shell
// In this case, terminal process will be created by fastfetch itself.
return 0;
}
@@ -205,6 +275,21 @@ static uint32_t getTerminalInfo(const FFinstance* instance, FFTerminalShellResul
return getTerminalInfo(instance, result, ppid);
}
if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "sihost") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "explorer")
) {
ffStrbufClear(&result->terminalProcessName);
ffStrbufClear(&result->terminalPrettyName);
ffStrbufClear(&result->terminalExe);
result->terminalExeName = "";
// Maybe terminal process is created by shell
if(!getTerminalInfoByEnumeratingChildProcesses(result, result->shellPid))
return 0;
}
else
result->terminalPid = pid;
if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "WindowsTerminal"))
ffStrbufSetS(&result->terminalPrettyName, ffStrbufContainIgnCaseS(&result->terminalExe, ".WindowsTerminalPreview_")
? "Windows Terminal Preview"
@@ -288,11 +373,13 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
result.shellExeName = "";
ffStrbufInit(&result.shellPrettyName);
ffStrbufInit(&result.shellVersion);
result.shellPid = 0;
ffStrbufInit(&result.terminalProcessName);
ffStrbufInitA(&result.terminalExe, 128);
result.terminalExeName = "";
ffStrbufInit(&result.terminalPrettyName);
result.terminalPid = 0;
ffStrbufInit(&result.userShellExe);
result.userShellExeName = "";
@@ -303,7 +390,9 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
goto exit;
ppid = getShellInfo(instance, &result, ppid);
getTerminalInfo(instance, &result, ppid);
if(ppid)
getTerminalInfo(instance, &result, ppid);
if(result.terminalProcessName.length == 0)
getTerminalFromEnv(&result);
@@ -1,12 +1,14 @@
#include "fastfetch.h"
#include "common/thread.h"
#include "detection/vulkan.h"
#include "detection/gpu/gpu.h"
#include "detection/vulkan/vulkan.h"
#ifdef FF_HAVE_VULKAN
#include "common/library.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/parsing.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <vulkan/vulkan.h>
@@ -41,19 +43,20 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed",
#ifdef __APPLE__
"libMoltenVK"FF_LIBRARY_EXTENSION, -1
#elif defined(_WIN32)
"vulkan-1"FF_LIBRARY_EXTENSION, -1
#else
"libvulkan"FF_LIBRARY_EXTENSION, 2, "vulkan-1"FF_LIBRARY_EXTENSION, -1
"libvulkan"FF_LIBRARY_EXTENSION, 2
#endif
)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkCreateInstance)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkDestroyInstance)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkEnumeratePhysicalDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetPhysicalDeviceProperties)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetInstanceProcAddr, vkGetInstanceProcAddr@8)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkCreateInstance, vkCreateInstance@12)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkDestroyInstance, vkDestroyInstance@8)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkEnumeratePhysicalDevices, vkEnumeratePhysicalDevices@12)
//Some drivers (nvdc) print messages to stdout
//and thats the best way i found to disable that
ffSuppressIO(true);
FF_SUPPRESS_IO();
FFVersion instanceVersion = FF_VERSION_INIT;
@@ -73,66 +76,52 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
FASTFETCH_PROJECT_VERSION_PATCH
);
//We need to request 1.2 to get physicalDeviceDriverProperties
uint32_t requestedVkVersion = VK_API_VERSION_1_0;
if(instanceVersion.minor >= 2)
requestedVkVersion = VK_API_VERSION_1_2;
const VkApplicationInfo applicationInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = FASTFETCH_PROJECT_NAME,
.applicationVersion = projectVersion,
.pEngineName = "vulkanPrintGPUs",
.engineVersion = projectVersion,
.apiVersion = requestedVkVersion
};
const VkInstanceCreateInfo instanceCreateInfo = {
VkInstance vkInstance;
if(ffvkCreateInstance(&(VkInstanceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = NULL,
.pApplicationInfo = &applicationInfo,
.pApplicationInfo = &(VkApplicationInfo) {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = FASTFETCH_PROJECT_NAME,
.applicationVersion = projectVersion,
.pEngineName = "vulkanPrintGPUs",
.engineVersion = projectVersion,
// We need to request 1.1 to get physicalDeviceDriverProperties
.apiVersion = instanceVersion.minor >= 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0
},
.enabledLayerCount = 0,
.ppEnabledLayerNames = NULL,
.enabledExtensionCount = 0,
.ppEnabledExtensionNames = NULL,
.flags = 0
};
VkInstance vkInstance;
if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS)
{
dlclose(vulkan);
ffSuppressIO(false);
}, NULL, &vkInstance) != VK_SUCCESS)
return "ffvkCreateInstance() failed";
}
//if instance creation succeeded, but vkEnumerateInstanceVersion didn't, this means we are running against a vulkan 1.0 implementation
//explicitly set this version, if no device is found, so we still have at least this info
if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0)
instanceVersion.major = 1;
uint32_t physicalDeviceCount;
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS)
{
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return "ffvkEnumeratePhysicalDevices() failed";
}
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
VkPhysicalDevice physicalDevices[128];
uint32_t physicalDeviceCount = (uint32_t) (sizeof(physicalDevices) / sizeof(*physicalDevices));
if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS)
{
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return "ffvkEnumeratePhysicalDevices() failed";
}
PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2");
PFN_vkGetPhysicalDeviceProperties ffvkGetPhysicalDeviceProperties = NULL;
PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2"); // 1.1
if(!ffvkGetPhysicalDeviceProperties2)
ffvkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties");
PFN_vkGetPhysicalDeviceMemoryProperties ffvkGetPhysicalDeviceMemoryProperties = NULL;
PFN_vkGetPhysicalDeviceMemoryProperties2 ffvkGetPhysicalDeviceMemoryProperties2 =
instance->config.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1
if(!ffvkGetPhysicalDeviceMemoryProperties2)
ffvkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties");
FFVersion maxDeviceApiVersion = FF_VERSION_INIT;
FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT;
@@ -140,18 +129,16 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
for(uint32_t i = 0; i < physicalDeviceCount; i++)
{
//Get device properties.
//On VK 1.2 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain.
//On VK 1.1 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain.
//This is required to get the driver name and conformance version.
VkPhysicalDeviceDriverProperties driverProperties;
driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
driverProperties.pNext = NULL;
driverProperties.driverName[0] = '\0';
driverProperties.conformanceVersion = (VkConformanceVersion) {0, 0, 0, 0};
VkPhysicalDeviceProperties2 physicalDeviceProperties;
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physicalDeviceProperties.pNext = &driverProperties;
VkPhysicalDeviceDriverProperties driverProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
};
VkPhysicalDeviceProperties2 physicalDeviceProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
.pNext = &driverProperties,
};
if(ffvkGetPhysicalDeviceProperties2 != NULL)
ffvkGetPhysicalDeviceProperties2(physicalDevices[i], &physicalDeviceProperties);
@@ -161,6 +148,7 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
//If the device api version is higher than the current highest device api version, overwrite it
//In this case, also use the current device driver name as the shown driver name
FFVersion deviceAPIVersion = FF_VERSION_INIT;
applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion);
if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0)
@@ -170,14 +158,17 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
}
//If the device conformance version is higher than the current highest device conformance version, overwrite it
if(ffvkGetPhysicalDeviceProperties2)
{
FFVersion deviceConformanceVersion = {
.major = driverProperties.conformanceVersion.major,
.minor = driverProperties.conformanceVersion.minor,
.patch = driverProperties.conformanceVersion.patch,
};
FFVersion deviceConformanceVersion = FF_VERSION_INIT;
deviceConformanceVersion.major = driverProperties.conformanceVersion.major;
deviceConformanceVersion.minor = driverProperties.conformanceVersion.minor;
deviceConformanceVersion.patch = driverProperties.conformanceVersion.patch;
if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0)
maxDeviceConformanceVersion = deviceConformanceVersion;
if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0)
maxDeviceConformanceVersion = deviceConformanceVersion;
}
//Add the device to the list of devices shown by the GPU module
@@ -190,14 +181,39 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
ffStrbufInit(&gpu->name);
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
gpu->type = FF_GPU_TYPE_INTEGRATED;
else
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
gpu->type = FF_GPU_TYPE_DISCRETE;
else
gpu->type = FF_GPU_TYPE_INTEGRATED;
gpu->id = physicalDeviceProperties.properties.deviceID;
ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID));
ffStrbufInitS(&gpu->driver, driverProperties.driverInfo);
VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT,
};
VkPhysicalDeviceMemoryProperties2 memoryProperties2 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
.pNext = &budgetProperties,
};
if(ffvkGetPhysicalDeviceMemoryProperties2)
ffvkGetPhysicalDeviceMemoryProperties2(physicalDevices[i], &memoryProperties2);
else
ffvkGetPhysicalDeviceMemoryProperties(physicalDevices[i], &memoryProperties2.memoryProperties);
gpu->dedicated.total = gpu->shared.total = 0;
gpu->dedicated.used = gpu->shared.used = ffvkGetPhysicalDeviceMemoryProperties2 ? 0 : FF_GPU_VMEM_SIZE_UNSET;
for(uint32_t index = 0; index < memoryProperties2.memoryProperties.memoryHeapCount; ++index)
{
const VkMemoryHeap* heap = &memoryProperties2.memoryProperties.memoryHeaps[index];
FFGPUMemory* vmem = gpu->type == FF_GPU_TYPE_DISCRETE && (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? &gpu->dedicated : &gpu->shared;
vmem->total += heap->size;
if(ffvkGetPhysicalDeviceMemoryProperties2)
vmem->used += heap->size - budgetProperties.heapBudget[index];
}
//No way to detect those using vulkan
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->driver);
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
}
@@ -212,10 +228,7 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu
//Use the highest device conformace version as our conformance version
ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion);
free(physicalDevices);
ffvkDestroyInstance(vkInstance, NULL);
dlclose(vulkan);
ffSuppressIO(false);
return NULL;
}
+8 -2
View File
@@ -3,16 +3,22 @@
#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 "WifiConnectionInfo"
const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result)
{
FF_STRBUF_AUTO_DESTROY buffer;
ffStrbufInit(&buffer);
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api",
FF_TERMUX_API_PATH,
"WifiConnectionInfo"
}))
return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " WifiConnectionInfo` failed";
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
if(buffer.length == 0)
return "`" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` prints empty";
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
ffStrbufInit(&item->inf.description);
+8 -6
View File
@@ -13,6 +13,12 @@
#define NM_NO_INCLUDE_EXTRA_HEADERS 1
#include <NetworkManager.h>
//https://developer-old.gnome.org/libnm/stable/libnm-nm-dbus-interface.html
#ifndef NM_VERSION_1_26
#define NM_802_11_AP_SEC_KEY_MGMT_OWE 0x00000800
#define NM_802_11_AP_SEC_KEY_MGMT_OWE_TM 0x00001000
#endif
static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* result)
{
FF_LIBRARY_LOAD(nm, &instance->config.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0);
@@ -39,10 +45,7 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul
NMClient* client = ffnm_client_new(NULL, NULL);
if(!client)
{
dlclose(nm);
return "Could not create NMClient";
}
/* Get all devices managed by NetworkManager */
const GPtrArray* devices = ffnm_client_get_devices(client);
@@ -193,14 +196,13 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul
}
ffg_object_unref(client);
dlclose(nm);
return NULL;
}
#endif
#include "common/io.h"
#include "common/io/io.h"
#include <net/if.h>
#include <linux/wireless.h>
@@ -219,7 +221,7 @@ static const char* detectWifiWithIoctls(FF_MAYBE_UNUSED const FFinstance* instan
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
{
ffStrbufSetF(&path, "/sys/class/net/%s/phy80211", i->if_name);
if(!ffFileExists(path.chars, S_IFDIR))
if(!ffPathExists(path.chars, FF_PATHTYPE_DIRECTORY))
continue;
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);

Some files were not shown because too many files have changed in this diff Show More