mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f6702d83d0 | |||
| b1a779c178 | |||
| cc1260ee3c | |||
| 92b1788825 | |||
| efdbeb585b | |||
| 304f171d38 | |||
| 9a3909f8ba | |||
| 6ca4b5391b | |||
| cabd36d078 | |||
| 64bacd2572 | |||
| 47be29b89c | |||
| 6407bf6a1f | |||
| e2d145cf31 | |||
| b634c70f80 | |||
| e29169711c | |||
| 662ddac050 | |||
| b90d543afc | |||
| f05d134aa7 | |||
| 74a68aa626 | |||
| fcc5170a10 | |||
| 3a9403a2f1 | |||
| ff170caff6 | |||
| 532b493c42 | |||
| 51cc87e0db | |||
| 878d4608b1 | |||
| 03d1c62787 | |||
| 5c46271898 | |||
| 9a7c732555 | |||
| 8ffe6fda9b | |||
| e563417166 | |||
| ec3f9acd76 | |||
| 6c22fd6902 | |||
| 82b10a527b | |||
| 92c744d971 | |||
| 7a691a4286 | |||
| e98489a74b | |||
| 7a5da23b0c | |||
| edf4837ed6 | |||
| 749bd8db0e | |||
| d2460d8e85 | |||
| eead4cf70e | |||
| 291f88b1e4 | |||
| 93f1a44d0f | |||
| 550e107683 | |||
| 7a8b94b6d4 | |||
| 2005b396fa | |||
| 2a80b5ed36 | |||
| 47a32c725d | |||
| fc26acd0ab | |||
| e57f7d378a | |||
| 6de74587bd | |||
| 6e5e7851d4 | |||
| 84ccda45b0 | |||
| ec3cd6cc68 | |||
| cae9fee30a | |||
| f0111a8037 | |||
| 8fad590f8b | |||
| 2ae5a9d725 | |||
| 8153c8b82c | |||
| 159f4a3a3c | |||
| 3dbfff57e7 | |||
| a063cd4feb | |||
| dc5da3c3b3 | |||
| 79c9c19b1a | |||
| b49b583e64 | |||
| 0b8e8ad4f2 | |||
| 7fc2c4dcf1 | |||
| a74cbc5781 | |||
| 619ec921ee | |||
| 1b23c9a030 | |||
| d4c11b9a1f | |||
| 55da030e2a | |||
| c64f306550 | |||
| 7ee4a648d0 | |||
| 78ca4e7c87 | |||
| 7a2826358b | |||
| df84721b55 | |||
| f53a1f785d | |||
| 4f3b9776ae | |||
| 39f47d65a9 | |||
| a92e6b6d91 | |||
| 00e044c431 | |||
| 7132762c9c | |||
| 2476b44300 | |||
| d36e827ec9 | |||
| a37115cb00 | |||
| 7dc73c61ab | |||
| a14ef06d14 | |||
| 212e7aa47e | |||
| ebe26eddf0 | |||
| 517e3fcff9 | |||
| 679162c762 | |||
| e4973b3262 | |||
| a1ea7804f3 | |||
| 2c51d55ba2 | |||
| 3b0e1a5833 | |||
| 9bb6d8fd6e | |||
| 4afba798ba | |||
| f4cefe955b | |||
| 1c38ebb551 | |||
| 14dcafe2ca | |||
| cf78216d78 | |||
| 0c256e2908 | |||
| 00fc3f1a1d | |||
| 672e309d89 | |||
| b0c19256f0 | |||
| 205e664b4d | |||
| cb466aec08 | |||
| 33f3744a63 | |||
| 7adb1606f1 | |||
| 184ada6ae8 | |||
| 856c9d58b8 | |||
| f3fba8a389 | |||
| 10468a559a | |||
| c4c9f02433 | |||
| f2dd288a0d | |||
| aa36a83182 | |||
| dd9047c4e9 | |||
| 11634b9a67 | |||
| d832324306 | |||
| a7af5c4f66 | |||
| 0f2022bd40 | |||
| e598598ca8 | |||
| 85599fcf53 | |||
| 6961488d38 | |||
| 209d0c98d9 | |||
| d718cc997c | |||
| 4967d0a222 | |||
| 17ebd5cea8 | |||
| 25e81b39f9 | |||
| 4b253aa4cf | |||
| d7b84bed9f | |||
| 298d091e2e | |||
| ebe30394f2 | |||
| 4c7d479e93 | |||
| d6d204ae5f | |||
| ed23eb0fde |
+104
-26
@@ -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/*
|
||||
|
||||
@@ -1,3 +1,45 @@
|
||||
# 1.10.0
|
||||
|
||||
Notable Changes:
|
||||
|
||||
* With the support of Win32 platform, original Windows 64bit artifact file is renamed to Win64 to avoid possible confusion
|
||||
|
||||
Features:
|
||||
* Bluetooth module
|
||||
* Sound module
|
||||
* Gamepad module
|
||||
* Support colored percentage numbers output (#409)
|
||||
* Support `--localip-compact-type` option (#408)
|
||||
* Terminator terminal font detection (@Zerogiven, #415)
|
||||
* Windows 32bit compatibility
|
||||
* Support global configuration in MSYS2 environment (Windows)
|
||||
* Support GPU driver version detection on Windows 11
|
||||
* Support scaled resolution detection for wayland (Linux)
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix build with older libnm versions
|
||||
* Fix a rare case that fails to detect terminal
|
||||
* Fix Muffin detection (@Zerogiven, #411)
|
||||
* Fix IPv6 detection (Windows)
|
||||
* Fix scoop package count detection when scoop is installed in non-default path (Windows, #417)
|
||||
* Fix UB reported by clang
|
||||
* Honor $SCOOP when detecting scoop packages (#417)
|
||||
|
||||
Other:
|
||||
|
||||
* Simplified wmtheme output format (Windows)
|
||||
* Improved GPU detection performance on Windows 11
|
||||
* Lastest Mac model identifier support (macOS)
|
||||
|
||||
# 1.9.1
|
||||
|
||||
Bugfixes:
|
||||
|
||||
* Fix builds on s390x (@jonathanspw, #402)
|
||||
* Fix zero refresh rate on some monitors (macOS)
|
||||
* Fix default formatting of Wifi module
|
||||
|
||||
# 1.9.0
|
||||
|
||||
Notable Changes:
|
||||
|
||||
+46
-14
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 1.9.0
|
||||
VERSION 1.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,33 +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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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: {}
|
||||
|
||||
@@ -47,3 +47,53 @@ void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent,
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
// if (green < yellow)
|
||||
// [0, green]: print green
|
||||
// (green, yellow]: print yellow
|
||||
// (yellow, 100]: print red
|
||||
//
|
||||
// if (green > yellow)
|
||||
// [green, 100]: print green
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): PRINT RED
|
||||
void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses)
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
bool colored = !!(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
|
||||
if (colored && !instance->config.pipe)
|
||||
{
|
||||
if(green < yellow)
|
||||
{
|
||||
if (percent <= green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
else if (percent <= yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (percent >= green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
else if (percent >= yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%u%%", (unsigned) percent);
|
||||
|
||||
if (colored && !instance->config.pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, ')');
|
||||
}
|
||||
|
||||
+5
-3
@@ -7,11 +7,13 @@
|
||||
|
||||
enum
|
||||
{
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 2,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 4,
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
};
|
||||
|
||||
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||
void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
#include "dbus.h"
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
|
||||
#include "common/thread.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib)
|
||||
{
|
||||
FF_LIBRARY_LOAD(dbus, &instance->config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_has_next, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false)
|
||||
dbus = NULL; // don't auto dlclose
|
||||
return true;
|
||||
}
|
||||
|
||||
static const FFDBusLibrary* loadLib(const FFinstance* instance)
|
||||
{
|
||||
static FFDBusLibrary lib;
|
||||
static bool loaded = false;
|
||||
static bool loadSuccess = false;
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
if(!loaded)
|
||||
{
|
||||
loaded = true;
|
||||
loadSuccess = loadLibSymbols(instance, &lib);
|
||||
}
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return loadSuccess ? &lib : NULL;
|
||||
}
|
||||
|
||||
const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data)
|
||||
{
|
||||
data->lib = loadLib(instance);
|
||||
if(data->lib == NULL)
|
||||
return "Failed to load DBus library";
|
||||
|
||||
data->connection = data->lib->ffdbus_bus_get(busType, NULL);
|
||||
if(data->connection == NULL)
|
||||
return "Failed to connect to DBus";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_STRING)
|
||||
{
|
||||
const char* value = NULL;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
|
||||
if(!ffStrSet(value))
|
||||
return false;
|
||||
|
||||
ffStrbufAppendS(result, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
|
||||
if(argType == DBUS_TYPE_VARIANT)
|
||||
return ffDBusGetValue(dbus, &subIter, result);
|
||||
|
||||
//At this point we have an array
|
||||
|
||||
bool foundAValue = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(ffDBusGetValue(dbus, &subIter, result))
|
||||
{
|
||||
foundAValue = true;
|
||||
ffStrbufAppendS(result, ", ");
|
||||
}
|
||||
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &subIter);
|
||||
}
|
||||
|
||||
if(foundAValue)
|
||||
ffStrbufSubstrBefore(result, result->length - 2);
|
||||
|
||||
return foundAValue;
|
||||
}
|
||||
|
||||
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_BOOLEAN)
|
||||
{
|
||||
dbus_bool_t value = 0;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
*result = value != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
return ffDBusGetBool(dbus, &subIter, result);
|
||||
}
|
||||
|
||||
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_BYTE)
|
||||
{
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
return ffDBusGetByte(dbus, &subIter, result);
|
||||
}
|
||||
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method)
|
||||
{
|
||||
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
|
||||
if(message == NULL)
|
||||
return NULL;
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property)
|
||||
{
|
||||
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
|
||||
if(message == NULL)
|
||||
return NULL;
|
||||
|
||||
DBusMessageIter requestIterator;
|
||||
dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator);
|
||||
|
||||
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result)
|
||||
{
|
||||
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
|
||||
if(reply == NULL)
|
||||
return;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(reply);
|
||||
return;
|
||||
}
|
||||
|
||||
ffDBusGetValue(dbus, &rootIterator, result);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(reply);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_DBUS
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_dbus
|
||||
#define FF_INCLUDED_common_dbus
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
|
||||
|
||||
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
|
||||
{ \
|
||||
if(!(dbus)->lib->ffdbus_message_iter_has_next(iterator)) \
|
||||
break; \
|
||||
(dbus)->lib->ffdbus_message_iter_next(iterator); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
typedef struct FFDBusLibrary
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(dbus_bus_get)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_init)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_init_append)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_recurse)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_has_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_unref)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_flush)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply)
|
||||
FF_LIBRARY_SYMBOL(dbus_pending_call_unref)
|
||||
} FFDBusLibrary;
|
||||
|
||||
typedef struct FFDBusData
|
||||
{
|
||||
const FFDBusLibrary* lib;
|
||||
DBusConnection* connection;
|
||||
} FFDBusData;
|
||||
|
||||
const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success
|
||||
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
|
||||
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
|
||||
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result);
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method);
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
|
||||
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
#endif // FF_INCLUDED_common_dbus
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "common/format.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
+19
-2
@@ -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
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_io
|
||||
#define FF_INCLUDED_common_io
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <sys/stat.h> //mode_t, fstat, stat
|
||||
|
||||
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
|
||||
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer);
|
||||
|
||||
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer);
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
|
||||
#ifdef _WIN32
|
||||
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer);
|
||||
#endif
|
||||
|
||||
bool ffFileExists(const char* fileName, mode_t mode);
|
||||
|
||||
// Not thread safe!
|
||||
void ffSuppressIO(bool suppress);
|
||||
|
||||
FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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,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,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);
|
||||
|
||||
@@ -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
@@ -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,5 +1,6 @@
|
||||
Battery
|
||||
Bios
|
||||
Bluetooth
|
||||
Board
|
||||
Break
|
||||
Chassis
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "battery.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
#include "bios.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth);
|
||||
|
||||
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFBluetoothResult,
|
||||
ffStrbufInit(&result.error);
|
||||
ffListInit(&result.devices, sizeof(FFBluetoothDevice));
|
||||
|
||||
ffDetectBluetoothImpl(instance, &result);
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_bluetooth_bluetooth
|
||||
#define FF_INCLUDED_detection_bluetooth_bluetooth
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBluetoothDevice
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf address;
|
||||
FFstrbuf type;
|
||||
uint8_t battery; // 0-100%
|
||||
bool connected;
|
||||
} FFBluetoothDevice;
|
||||
|
||||
typedef struct FFBluetoothResult
|
||||
{
|
||||
FFstrbuf error;
|
||||
FFlist devices; // List of FFBluetoothDevice
|
||||
} FFBluetoothResult;
|
||||
|
||||
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#import <IOBluetooth/IOBluetooth.h>
|
||||
|
||||
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
|
||||
if(!ioDevices)
|
||||
{
|
||||
ffStrbufAppendS(&bluetooth->error, "IOBluetoothDevice.pairedDevices failed");
|
||||
return;
|
||||
}
|
||||
|
||||
for(IOBluetoothDevice* ioDevice in ioDevices)
|
||||
{
|
||||
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
||||
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
|
||||
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = !!ioDevice.isConnected;
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode)
|
||||
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved1)
|
||||
ffStrbufAppendS(&device->type, "LE audio, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved2)
|
||||
ffStrbufAppendS(&device->type, "Reserved for future use, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorPositioning)
|
||||
ffStrbufAppendS(&device->type, "Positioning, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorNetworking)
|
||||
ffStrbufAppendS(&device->type, "Networking, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorRendering)
|
||||
ffStrbufAppendS(&device->type, "Rendering, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorCapturing)
|
||||
ffStrbufAppendS(&device->type, "Capturing, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorObjectTransfer)
|
||||
ffStrbufAppendS(&device->type, "Object Transfer, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorAudio)
|
||||
ffStrbufAppendS(&device->type, "Audio, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorTelephony)
|
||||
ffStrbufAppendS(&device->type, "Telephony, ");
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorInformation)
|
||||
ffStrbufAppendS(&device->type, "Information, ");
|
||||
|
||||
if(device->type.length == 0)
|
||||
{
|
||||
switch(ioDevice.deviceClassMajor)
|
||||
{
|
||||
case kBluetoothDeviceClassMajorMiscellaneous:
|
||||
ffStrbufAppendS(&device->type, "Miscellaneous");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorComputer:
|
||||
ffStrbufAppendS(&device->type, "Computer");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorPhone:
|
||||
ffStrbufAppendS(&device->type, "Phone");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorLANAccessPoint:
|
||||
ffStrbufAppendS(&device->type, "LAN/Network Access point");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorAudio:
|
||||
ffStrbufAppendS(&device->type, "Audio/Video");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorPeripheral:
|
||||
ffStrbufAppendS(&device->type, "Peripheral");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorImaging:
|
||||
ffStrbufAppendS(&device->type, "Imaging");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorWearable:
|
||||
ffStrbufAppendS(&device->type, "Wearable");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorToy:
|
||||
ffStrbufAppendS(&device->type, "Toy");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorHealth:
|
||||
ffStrbufAppendS(&device->type, "Health");
|
||||
break;
|
||||
case kBluetoothDeviceClassMajorUnclassified:
|
||||
ffStrbufAppendS(&device->type, "Uncategorized");
|
||||
break;
|
||||
default:
|
||||
ffStrbufAppendS(&device->type, "Unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufTrimRight(&device->type, ' ');
|
||||
ffStrbufTrimRight(&device->type, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include "common/dbus.h"
|
||||
|
||||
/* Example dbus reply, striped to only the relevant parts:
|
||||
array [ //root
|
||||
dict entry( //object
|
||||
object path "/org/bluez/hci0/dev_03_21_8B_91_16_4D"
|
||||
array [
|
||||
dict entry( //property
|
||||
string "org.bluez.Device1"
|
||||
array [
|
||||
dict entry( //value
|
||||
string "Address"
|
||||
variant string "03:21:8B:91:16:4D"
|
||||
)
|
||||
dict entry( //value
|
||||
string "Name"
|
||||
variant string "JBL TUNE160BT"
|
||||
)
|
||||
dict entry( //value
|
||||
string "Icon"
|
||||
variant string "audio-headset"
|
||||
)
|
||||
dict entry( //value
|
||||
string "Connected"
|
||||
variant boolean true
|
||||
)
|
||||
]
|
||||
)
|
||||
dict entry( //property
|
||||
string "org.bluez.Battery1"
|
||||
array [
|
||||
dict entry( //value
|
||||
string "Percentage"
|
||||
variant byte 100
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
*/
|
||||
|
||||
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
|
||||
const char* deviceProperty;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(strcmp(deviceProperty, "Address") == 0)
|
||||
ffDBusGetValue(dbus, &dictIter, &device->address);
|
||||
else if(strcmp(deviceProperty, "Name") == 0)
|
||||
ffDBusGetValue(dbus, &dictIter, &device->name);
|
||||
else if(strcmp(deviceProperty, "Icon") == 0)
|
||||
ffDBusGetValue(dbus, &dictIter, &device->type);
|
||||
else if(strcmp(deviceProperty, "Percentage") == 0)
|
||||
ffDBusGetByte(dbus, &dictIter, &device->battery);
|
||||
else if(strcmp(deviceProperty, "Connected") == 0)
|
||||
ffDBusGetBool(dbus, &dictIter, &device->connected);
|
||||
}
|
||||
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
|
||||
const char* propertyType;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
|
||||
|
||||
if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL)
|
||||
return; //We don't care about other properties
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothValue(dbus, &arrayIter, device);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
}
|
||||
|
||||
static void detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
|
||||
return;
|
||||
|
||||
const char* objectPath;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
|
||||
|
||||
//We don't want adapter objects
|
||||
if(strstr(objectPath, "dev_") == NULL)
|
||||
return;
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothProperty(dbus, &arrayIter, device);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
|
||||
if(device->name.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
ffStrbufDestroy(&device->address);
|
||||
ffStrbufDestroy(&device->type);
|
||||
--bluetooth->devices.length;
|
||||
}
|
||||
}
|
||||
|
||||
static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
|
||||
|
||||
while(true)
|
||||
{
|
||||
detectBluetoothObject(bluetooth, dbus, &arrayIter);
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* detectBluetooth(const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
FFDBusData dbus;
|
||||
const char* error = ffDBusLoadData(instance, DBUS_BUS_SYSTEM, &dbus);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
|
||||
if(!managedObjects)
|
||||
return "Failed to call GetManagedObjects";
|
||||
|
||||
DBusMessageIter rootIter;
|
||||
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return "Failed to get root iterator of GetManagedObjects";
|
||||
}
|
||||
|
||||
detectBluetoothRoot(bluetooth, &dbus, &rootIter);
|
||||
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
ffStrbufAppendS(&bluetooth->error, detectBluetooth(instance, bluetooth));
|
||||
#else
|
||||
FF_UNUSED(instance);
|
||||
ffStrbufAppendS(&bluetooth->error, "Fastfetch was compiled without DBus support");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
|
||||
{
|
||||
ffStrbufAppendS(&bluetooth->error, "Bluetooth not supported on this platform");
|
||||
}
|
||||
@@ -0,0 +1,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,5 +1,5 @@
|
||||
#include "board.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "brightness.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "chassis.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "cpu.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
|
||||
@@ -131,7 +131,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
|
||||
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
|
||||
if(ffFileExists(BP, S_IFDIR))
|
||||
if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY))
|
||||
{
|
||||
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
|
||||
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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, ¤tPos);
|
||||
|
||||
if(!isPhysicalDevice(device))
|
||||
{
|
||||
ffStrbufDestroy(device);
|
||||
devices.length--;
|
||||
continue;
|
||||
}
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(&disks->disks);
|
||||
|
||||
//detect mountpoint
|
||||
ffStrbufInit(&disk->mountpoint);
|
||||
appendNextEntry(&disk->mountpoint, ¤tPos);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <CoreGraphics/CGDirectDisplay.h>
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
|
||||
static void detectDisplays(FFDisplayServerResult* ds)
|
||||
{
|
||||
@@ -20,10 +21,25 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen);
|
||||
if(mode)
|
||||
{
|
||||
//https://github.com/glfw/glfw/commit/aab08712dd8142b642e2042e7b7ba563acd07a45
|
||||
double refreshRate = CGDisplayModeGetRefreshRate(mode);
|
||||
|
||||
if (refreshRate == 0)
|
||||
{
|
||||
CVDisplayLinkRef link;
|
||||
if(CVDisplayLinkCreateWithCGDisplay(screen, &link) == kCVReturnSuccess)
|
||||
{
|
||||
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
||||
if (!(time.flags & kCVTimeIsIndefinite))
|
||||
refreshRate = time.timeScale / (double) time.timeValue + 0.5; //59.97...
|
||||
CVDisplayLinkRelease(link);
|
||||
}
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(ds,
|
||||
(uint32_t)CGDisplayModeGetPixelWidth(mode),
|
||||
(uint32_t)CGDisplayModeGetPixelHeight(mode),
|
||||
(uint32_t)CGDisplayModeGetRefreshRate(mode),
|
||||
(uint32_t)refreshRate,
|
||||
(uint32_t)CGDisplayModeGetWidth(mode),
|
||||
(uint32_t)CGDisplayModeGetHeight(mode)
|
||||
);
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
@@ -5,20 +5,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)) ®istry_listener, &data);
|
||||
ffwl_display_dispatch(display);
|
||||
ffwl_display_roundtrip(display);
|
||||
ffwl_display_dispatch(data.display);
|
||||
data.ffwl_display_roundtrip(data.display);
|
||||
|
||||
data.ffwl_proxy_destroy(registry);
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
ffwl_display_disconnect(data.display);
|
||||
|
||||
//We successfully connected to wayland and detected the display.
|
||||
//So we can set set the session type to wayland.
|
||||
//This is used as an indicator that we are running wayland by the x11 backends.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -187,5 +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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
#include "common/font.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "font.h"
|
||||
|
||||
#import <AppKit/NSFont.h>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_gamepad_gamepad
|
||||
#define FF_INCLUDED_detection_gamepad_gamepad
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFGamepadDevice
|
||||
{
|
||||
FFstrbuf identifier;
|
||||
FFstrbuf name;
|
||||
} FFGamepadDevice;
|
||||
|
||||
const char* ffDetectGamepad(const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "gamepad.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
static void enumSet(const void* value, void *context)
|
||||
{
|
||||
CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey));
|
||||
CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey));
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context);
|
||||
ffStrbufInit(&device->identifier);
|
||||
ffCfStrGetString(serialNumber, &device->identifier);
|
||||
ffStrbufInit(&device->name);
|
||||
ffCfStrGetString(product, &device->name);
|
||||
}
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
|
||||
return "IOHIDManagerOpen() failed";
|
||||
|
||||
CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop);
|
||||
CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad);
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
CFSTR(kIOHIDDeviceUsageKey)
|
||||
}, (const void **)(CFNumberRef[]){
|
||||
genericDesktop,
|
||||
gamePad
|
||||
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
IOHIDManagerSetDeviceMatching(manager, matching);
|
||||
|
||||
CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
|
||||
if (set)
|
||||
CFSetApplyFunction(set, &enumSet, devices);
|
||||
IOHIDManagerClose(manager, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "gamepad.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
DIR* dirp = opendir("/sys/class/input/");
|
||||
if(dirp == NULL)
|
||||
return "opendir(\"/sys/class/input/\") == NULL";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path;
|
||||
ffStrbufInitS(&path, "/sys/class/input/");
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(strncmp(entry->d_name, "js", 2) != 0)
|
||||
continue;
|
||||
if(!isdigit(entry->d_name[2]))
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
ffStrbufAppendS(&path, "/device/name");
|
||||
|
||||
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
|
||||
{
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitS(&device->identifier, entry->d_name);
|
||||
ffStrbufInit(&device->name);
|
||||
ffAppendFileBuffer(path.chars, &device->name);
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "gamepad.h"
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -8,7 +8,13 @@ static inline bool strEqual(const char* a, const char* b)
|
||||
|
||||
static const char* getProductName(const FFstrbuf* hwModel)
|
||||
{
|
||||
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L1386
|
||||
// Macbook Pro: https://support.apple.com/en-us/HT201300
|
||||
// Macbook Air: https://support.apple.com/en-us/HT201862
|
||||
// Mac mini: https://support.apple.com/en-us/HT201894
|
||||
// iMac: https://support.apple.com/en-us/HT201634
|
||||
// Mac Pro: https://support.apple.com/en-us/HT202888
|
||||
// Mac Studio: https://support.apple.com/en-us/HT213073
|
||||
|
||||
if(ffStrbufStartsWithS(hwModel, "MacBookPro"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("MacBookPro");
|
||||
@@ -106,20 +112,26 @@ static const char* getProductName(const FFstrbuf* hwModel)
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Mac");
|
||||
if(strEqual(version, "14,6") ||
|
||||
strEqual(version, "14,10")) return "MacBook Pro (16-inch, 2023)";
|
||||
if(strEqual(version, "14,5") ||
|
||||
strEqual(version, "14,9")) return "MacBook Pro (14-inch, 2023)";
|
||||
if(strEqual(version, "14,3")) return "Mac mini (M2, 2023, Two Thunderbolt 4 ports)";
|
||||
if(strEqual(version, "14,12")) return "Mac mini (M2, 2023, Four Thunderbolt 4 ports)";
|
||||
if(strEqual(version, "14,7")) return "MacBook Pro (13-inch, M2, 2022)";
|
||||
if(strEqual(version, "14,2")) return "MacBook Air (M2, 2022)";
|
||||
if(strEqual(version, "13,1")) return "Mac Studio (2022, Two USB-C front ports)";
|
||||
if(strEqual(version, "13,2")) return "Mac Studio (2022, Two Thunderbolt 4 front ports)";
|
||||
if(strEqual(version, "13,1")) return "Mac Studio (M1 Max, 2022, Two USB-C front ports)";
|
||||
if(strEqual(version, "13,2")) return "Mac Studio (M1 Ultra, 2022, Two Thunderbolt 4 front ports)";
|
||||
}
|
||||
else if(ffStrbufStartsWithS(hwModel, "iMac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("iMac");
|
||||
if(strEqual(version, "21,1") ||
|
||||
strEqual(version, "21,2")) return "iMac (24-inch, M1, 2021)";
|
||||
if(strEqual(version, "21,1")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
if(strEqual(version, "21,2")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports)";
|
||||
if(strEqual(version, "20,1") ||
|
||||
strEqual(version, "20,2")) return "iMac (Retina 5K, 27-inch, 2020)";
|
||||
if(strEqual(version, "19,1") ||
|
||||
strEqual(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(strEqual(version, "19,1")) return "iMac (Retina 5K, 27-inch, 2019)";
|
||||
if(strEqual(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(strEqual(version, "Pro1,1")) return "iMac Pro (2017)";
|
||||
if(strEqual(version, "18,3")) return "iMac (Retina 5K, 27-inch, 2017)";
|
||||
if(strEqual(version, "18,2")) return "iMac (Retina 4K, 21.5-inch, 2017)";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "host.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
|
||||
__attribute__((__unused__))
|
||||
FF_MAYBE_UNUSED
|
||||
static void getLocaleFromEnv(FFstrbuf* locale)
|
||||
{
|
||||
ffStrbufAppendS(locale, getenv("LANG"));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
@@ -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,6 +1,7 @@
|
||||
#include "os.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -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,5 +1,6 @@
|
||||
#include "packages.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/thread.h"
|
||||
#include "temps_linux.h"
|
||||
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user