Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8be4921bd0 | |||
| b22bcba220 | |||
| 5ee7ea46e7 | |||
| d93c934269 | |||
| 5c1ac33df2 | |||
| 0b3bf3c273 | |||
| 7fd98829b0 | |||
| 282271a65a | |||
| 9ef4b82cb9 | |||
| 10973dd9d1 | |||
| dfdffec1c9 | |||
| 2283700a99 | |||
| 7b647e09da | |||
| 54cb74c999 | |||
| 0f70cb408f | |||
| c80b1761dd | |||
| a1fde6f922 | |||
| 6a44515cf2 | |||
| cfcc4c8375 | |||
| ea60fd0a0d | |||
| a4e0275263 | |||
| 71779fa4b1 | |||
| 475099696f | |||
| 14670b6144 | |||
| 327b1b142e | |||
| 9d106c6672 | |||
| df0e13b198 | |||
| 6d0675820e | |||
| 08b0bac2b9 | |||
| d387800bda | |||
| 542ad5eab6 | |||
| 99f42d0953 | |||
| 3b316bdd3f | |||
| f011f8851e | |||
| 8f23a52f53 | |||
| 8f53d33f29 | |||
| e6fa269f52 | |||
| ca4a327de4 | |||
| f4e777f3d2 | |||
| 136f73ea0b | |||
| 28270541e6 | |||
| 8197eddea8 | |||
| 23bccc4802 | |||
| 873c7d93b6 | |||
| f4ee8667b1 | |||
| 50d3d4cdf4 | |||
| df048035b5 | |||
| 952989c1e8 | |||
| aa1237b0fd | |||
| b87983c86b |
@@ -1,3 +1,30 @@
|
||||
# 1.7.0
|
||||
|
||||
This release brings support for MacOS!
|
||||
The basics things are working, but it is far from feature parity with Linux.
|
||||
I developed this in a VM, so bugs on real hardware are likely.
|
||||
If you have a Mac and no idea what to do with your free time, i am very happy to accept pull requests / work on issues.
|
||||
|
||||
A lot of things were changed under the hood to make this possible, which should bring better performance and stability on all platforms.
|
||||
|
||||
Besides that, the following things have changed:
|
||||
|
||||
Features:
|
||||
* The binary prefix used can now be configured, and is used consistently across all modules. Set `--binary-prefix` to `iec` (default), `si` or `jedec`.
|
||||
* AMD GPUs now have a much better name, if the file `/usr/share/libdrm/amdgpu.ids` exists. For example my dedicated GPU, which was displayed as `AMD/ATI Radeon RX 5600 OEM/5600 XT / 5700/5700 XT`, is now `AMD Radeon RX 5600M`.
|
||||
|
||||
Logos:
|
||||
* MacOS
|
||||
* CachyOS small (@sirlucjan, #220)
|
||||
* MSYS2 (#219)
|
||||
|
||||
Bugfixes:
|
||||
* the `--file` option, which can be used to display the contents of a file as the logo, is now working again.
|
||||
|
||||
# 1.6.5
|
||||
|
||||
Fixes parsing quoted values in config files
|
||||
|
||||
# 1.6.4
|
||||
|
||||
Releasing this, so fedora can package fastfetch. Thanks to @jonathanspw for doing that!
|
||||
|
||||
@@ -1,38 +1,52 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs
|
||||
|
||||
project(fastfetch
|
||||
VERSION 1.6.4
|
||||
VERSION 1.7.0
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
###################
|
||||
# Target Platform #
|
||||
###################
|
||||
|
||||
if(APPLE OR ANDROID)
|
||||
set(LINUX FALSE CACHE BOOL "...") # Linux true means we have full linux userland, not just the kernel
|
||||
elseif(UNIX)
|
||||
set(LINUX TRUE CACHE BOOL "...")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported platform")
|
||||
endif()
|
||||
|
||||
#####################
|
||||
# Configure options #
|
||||
#####################
|
||||
|
||||
OPTION(ENABLE_LIBPCI "Enable libpci" ON)
|
||||
OPTION(ENABLE_VULKAN "Enable vulkan" ON)
|
||||
OPTION(ENABLE_WAYLAND "Enable wayland-client" ON)
|
||||
OPTION(ENABLE_XCB_RANDR "Enable xcb-randr" ON)
|
||||
OPTION(ENABLE_XCB "Enable xcb" ON)
|
||||
OPTION(ENABLE_XRANDR "Enable xrandr" ON)
|
||||
OPTION(ENABLE_X11 "Enable x11" ON)
|
||||
OPTION(ENABLE_GIO "Enable gio-2.0" ON)
|
||||
OPTION(ENABLE_DCONF "Enable dconf" ON)
|
||||
OPTION(ENABLE_DBUS "Enable dbus-1" ON)
|
||||
OPTION(ENABLE_XFCONF "Enable libxfconf-0" ON)
|
||||
OPTION(ENABLE_SQLITE3 "Enable sqlite3" ON)
|
||||
OPTION(ENABLE_RPM "Enable rpm" ON)
|
||||
OPTION(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON)
|
||||
OPTION(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON)
|
||||
OPTION(ENABLE_ZLIB "Enable zlib" ON)
|
||||
OPTION(ENABLE_CHAFA "Enable chafa" ON)
|
||||
OPTION(ENABLE_EGL "Enable egl" ON)
|
||||
OPTION(ENABLE_GLX "Enable glx" ON)
|
||||
OPTION(ENABLE_OSMESA "Enable osmesa" ON)
|
||||
OPTION(ENABLE_OPENCL "Enable opencl" ON)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
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
|
||||
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_CHAFA" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX" 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
|
||||
|
||||
#############################
|
||||
# Compile time dependencies #
|
||||
@@ -43,6 +57,8 @@ find_package(Threads REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
####################
|
||||
# Compiler options #
|
||||
####################
|
||||
@@ -81,10 +97,12 @@ if(NOT TARGET_DIR_USR)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET_DIR_HOME)
|
||||
if(NOT ANDROID)
|
||||
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/home")
|
||||
else()
|
||||
if(APPLE)
|
||||
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/Users")
|
||||
elseif(ANDROID)
|
||||
set(TARGET_DIR_HOME "/data/data/com.termux/files/home")
|
||||
else()
|
||||
set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/home")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -133,7 +151,7 @@ configure_file(src/fastfetch_config.h.in fastfetch_config.h)
|
||||
# libfastfetch target #
|
||||
#######################
|
||||
|
||||
add_library(libfastfetch OBJECT
|
||||
set(LIBFASTFETCH_SRC
|
||||
src/util/FFstrbuf.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFvaluestore.c
|
||||
@@ -154,7 +172,6 @@ add_library(libfastfetch OBJECT
|
||||
src/logo/image/image.c
|
||||
src/logo/image/im7.c
|
||||
src/logo/image/im6.c
|
||||
src/detection/os.c
|
||||
src/detection/qt.c
|
||||
src/detection/gtk.c
|
||||
src/detection/terminalShell.c
|
||||
@@ -163,11 +180,12 @@ add_library(libfastfetch OBJECT
|
||||
src/detection/datetime.c
|
||||
src/detection/temps.c
|
||||
src/detection/title.c
|
||||
src/detection/displayserver/displayServer.c
|
||||
src/detection/displayserver/wayland.c
|
||||
src/detection/displayserver/xcb.c
|
||||
src/detection/displayserver/xlib.c
|
||||
src/detection/displayserver/wmde.c
|
||||
src/detection/host/host.c
|
||||
src/detection/os/os.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/gpu/gpu.c
|
||||
src/detection/memory/memory.c
|
||||
src/detection/displayserver/displayserver.c
|
||||
src/modules/break.c
|
||||
src/modules/custom.c
|
||||
src/modules/title.c
|
||||
@@ -209,245 +227,91 @@ add_library(libfastfetch OBJECT
|
||||
src/modules/opencl.c
|
||||
)
|
||||
|
||||
if(ENABLE_LIBPCI)
|
||||
pkg_check_modules(LIBPCI libpci)
|
||||
if(LIBPCI_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBPCI=1)
|
||||
else()
|
||||
message(WARNING "Package libpci not found. Building without support.")
|
||||
endif()
|
||||
if(APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/host/host_apple.c
|
||||
src/detection/os/os_apple.c
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/gpu/gpu_apple.c
|
||||
src/detection/memory/memory_apple.c
|
||||
src/detection/displayserver/displayserver_apple.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/host/host_android.c
|
||||
src/detection/os/os_android.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
src/detection/gpu/gpu_android.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/displayserver/displayserver_android.c
|
||||
)
|
||||
else()
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
pkg_check_modules(VULKAN vulkan)
|
||||
if(VULKAN_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_VULKAN=1)
|
||||
else()
|
||||
message(WARNING "Package vulkan not found. Building without support.")
|
||||
endif()
|
||||
add_library(libfastfetch OBJECT
|
||||
${LIBFASTFETCH_SRC}
|
||||
)
|
||||
|
||||
CHECK_INCLUDE_FILE("sys/sysinfo.h" HAVE_SYSINFO_H)
|
||||
if(HAVE_SYSINFO_H)
|
||||
# needs to be public, because changes fastfech.h ABI
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_SYSINFO_H)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WAYLAND)
|
||||
pkg_check_modules (WAYLAND wayland-client)
|
||||
if(WAYLAND_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WAYLAND=1)
|
||||
else()
|
||||
message(WARNING "Package wayland-client not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_XCB_RANDR)
|
||||
pkg_check_modules(XCB_RANDR xcb-randr)
|
||||
if(XCB_RANDR_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XCB_RANDR=1)
|
||||
else()
|
||||
message(WARNING "Package xcb-randr not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_XCB)
|
||||
pkg_check_modules (XCB xcb)
|
||||
if(XCB_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XCB=1)
|
||||
else()
|
||||
message(WARNING "Package xcb not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_XRANDR)
|
||||
pkg_check_modules(XRANDR xrandr)
|
||||
if(XRANDR_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XRANDR=1)
|
||||
else()
|
||||
message(WARNING "Package xrandr not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_X11)
|
||||
pkg_check_modules(X11 x11)
|
||||
if(X11_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_X11=1)
|
||||
else()
|
||||
message(WARNING "Package x11 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_GIO)
|
||||
pkg_check_modules(GIO gio-2.0)
|
||||
if(GIO_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GIO=1)
|
||||
else()
|
||||
message(WARNING "Package gio-2.0 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_DCONF)
|
||||
pkg_check_modules(DCONF dconf)
|
||||
if(DCONF_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_DCONF=1)
|
||||
else()
|
||||
message(WARNING "Package dconf not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_DBUS)
|
||||
pkg_check_modules(DBUS dbus-1)
|
||||
if(DBUS_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_DBUS=1)
|
||||
else()
|
||||
message(WARNING "Package dbus-1 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_XFCONF)
|
||||
pkg_check_modules(XFCONF libxfconf-0)
|
||||
if(XFCONF_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_XFCONF=1)
|
||||
else()
|
||||
message(WARNING "Package libxfconf-0 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_SQLITE3)
|
||||
pkg_check_modules(SQLITE3 sqlite3)
|
||||
if(SQLITE3_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_SQLITE3=1)
|
||||
else()
|
||||
message(WARNING "Package sqlite3 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_RPM)
|
||||
pkg_check_modules(RPM rpm)
|
||||
if(RPM_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_RPM=1)
|
||||
else()
|
||||
message(WARNING "Package rpm not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_IMAGEMAGICK7)
|
||||
pkg_check_modules(IMAGEMAGICK7 MagickCore-7.Q16HDRI)
|
||||
if(NOT IMAGEMAGICK7_FOUND)
|
||||
pkg_check_modules(IMAGEMAGICK7 /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc)
|
||||
endif()
|
||||
if(NOT IMAGEMAGICK7_FOUND)
|
||||
pkg_check_modules(IMAGEMAGICK7 MagickCore-7.Q16)
|
||||
endif()
|
||||
if(NOT IMAGEMAGICK7_FOUND)
|
||||
pkg_check_modules(IMAGEMAGICK7 /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc)
|
||||
function(ff_check_lib VARNAME)
|
||||
if(NOT ENABLE_${VARNAME})
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(IMAGEMAGICK7_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_IMAGEMAGICK7=1)
|
||||
else()
|
||||
message(WARNING "Package MagickCore-7.Q16HDRI or MagickCore-7.Q16 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_IMAGEMAGICK6)
|
||||
pkg_check_modules(IMAGEMAGICK6 MagickCore-6.Q16HDRI)
|
||||
if(NOT IMAGEMAGICK6_FOUND)
|
||||
pkg_check_modules(IMAGEMAGICK6 /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc)
|
||||
endif()
|
||||
if(NOT IMAGEMAGICK6_FOUND)
|
||||
pkg_check_modules(IMAGEMAGICK6 MagickCore-6.Q16)
|
||||
endif()
|
||||
if(NOT IMAGEMAGICK6_FOUND)
|
||||
pkg_check_modules(IMAGEMAGICK6 /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc)
|
||||
endif()
|
||||
|
||||
if(IMAGEMAGICK6_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_IMAGEMAGICK6=1)
|
||||
else()
|
||||
message(WARNING "Package MagickCore-6.Q16HDRI or MagickCore-6.Q16 not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_ZLIB)
|
||||
pkg_check_modules(ZLIB zlib)
|
||||
if(ZLIB_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_ZLIB=1)
|
||||
else()
|
||||
message(WARNING "Package zlib not found. Building without support")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_CHAFA)
|
||||
if(IMAGEMAGICK6_FOUND OR IMAGEMAGICK7_FOUND)
|
||||
pkg_check_modules(CHAFA chafa>=1.10)
|
||||
if(CHAFA_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CHAFA=1)
|
||||
else()
|
||||
message(WARNING "Package chafa>=1.10 not found. Building without support.")
|
||||
foreach(LIBNAME ${ARGN})
|
||||
pkg_check_modules(${VARNAME} ${LIBNAME})
|
||||
if(${VARNAME}_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
|
||||
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
|
||||
return()
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Chafa not enabled, because neither ImageMagick6 nor ImageMagick7 were found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(ENABLE_EGL)
|
||||
pkg_check_modules(EGL egl)
|
||||
if(EGL_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EGL=1)
|
||||
else()
|
||||
message(WARNING "Package egl not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
message(WARNING "Package ${ARGV1} not found, building without support.")
|
||||
endfunction()
|
||||
|
||||
if(ENABLE_GLX)
|
||||
pkg_check_modules(GLX glx)
|
||||
if(GLX_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLX=1)
|
||||
else()
|
||||
message(WARNING "Package glx not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OSMESA)
|
||||
pkg_check_modules(OSMESA osmesa)
|
||||
if(OSMESA_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_OSMESA=1)
|
||||
else()
|
||||
message(WARNING "Package osmesa not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENCL)
|
||||
pkg_check_modules(OPENCL OpenCL)
|
||||
if(OPENCL_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_OPENCL=1)
|
||||
else()
|
||||
message(WARNING "Package opencl not found. Building without support.")
|
||||
endif()
|
||||
endif()
|
||||
ff_check_lib(LIBPCI libpci)
|
||||
ff_check_lib(VULKAN vulkan)
|
||||
ff_check_lib(WAYLAND wayland-client)
|
||||
ff_check_lib(XCB_RANDR xcb-randr)
|
||||
ff_check_lib(XCB xcb)
|
||||
ff_check_lib(XRANDR xrandr)
|
||||
ff_check_lib(X11 x11)
|
||||
ff_check_lib(GIO gio-2.0)
|
||||
ff_check_lib(DCONF dconf)
|
||||
ff_check_lib(DBUS dbus-1)
|
||||
ff_check_lib(XFCONF libxfconf-0)
|
||||
ff_check_lib(SQLITE3 sqlite3)
|
||||
ff_check_lib(RPM rpm)
|
||||
ff_check_lib(IMAGEMAGICK7 MagickCore-7.Q16HDRI MagickCore-7.Q16 /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc)
|
||||
ff_check_lib(IMAGEMAGICK6 MagickCore-6.Q16HDRI MagickCore-6.Q16 /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc)
|
||||
ff_check_lib(ZLIB zlib)
|
||||
ff_check_lib(CHAFA chafa>=1.10)
|
||||
ff_check_lib(EGL egl)
|
||||
ff_check_lib(GLX glx)
|
||||
ff_check_lib(OSMESA osmesa)
|
||||
ff_check_lib(OPENCL OpenCL)
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
PUBLIC ${PROJECT_BINARY_DIR}
|
||||
PUBLIC ${PROJECT_SOURCE_DIR}/src
|
||||
|
||||
PRIVATE ${LIBPCI_INCLUDE_DIRS}
|
||||
PRIVATE ${VULKAN_INCLUDE_DIRS}
|
||||
PRIVATE ${WAYLAND_INCLUDE_DIRS}
|
||||
PRIVATE ${XCB_RANDR_INCLUDE_DIRS}
|
||||
PRIVATE ${XCB_INCLUDE_DIRS}
|
||||
PRIVATE ${XRANDR_INCLUDE_DIRS}
|
||||
PRIVATE ${X11_INCLUDE_DIRS}
|
||||
PRIVATE ${GIO_INCLUDE_DIRS}
|
||||
PRIVATE ${DCONF_INCLUDE_DIRS}
|
||||
PRIVATE ${DBUS_INCLUDE_DIRS}
|
||||
PRIVATE ${XFCONF_INCLUDE_DIRS}
|
||||
PRIVATE ${SQLITE3_INCLUDE_DIRS}
|
||||
PRIVATE ${RPM_INCLUDE_DIRS}
|
||||
PRIVATE ${IMAGEMAGICK7_INCLUDE_DIRS}
|
||||
PRIVATE ${IMAGEMAGICK6_INCLUDE_DIRS}
|
||||
PRIVATE ${ZLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${CHAFA_INCLUDE_DIRS}
|
||||
PRIVATE ${VULKAN_INCLUDE_DIRS}
|
||||
PRIVATE ${EGL_INCLUDE_DIRS}
|
||||
PRIVATE ${GLX_INCLUDE_DIRS}
|
||||
PRIVATE ${OSMESA_INCLUDE_DIRS}
|
||||
PRIVATE ${OPENCL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(libfastfetch
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
# fastfetch
|
||||
# <center> Fastfetch </center>
|
||||
|
||||
fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in c to achieve much better performance, in return only Linux and Android are supported. It also uses mechanisms like multithreading and caching to finish as fast as possible.
|
||||
|
||||
The output on my personal machine with default configurations looks like this:
|
||||
<img src="screenshots/example.png" alt="example output" width="100%"/>
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android and MacOS are supported.
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
<img src="screenshots/example4.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
<img src="screenshots/example2.png" width="48%" align="top" />
|
||||
<img src="screenshots/example3.png" width="48%" align="top" />
|
||||
<img src="screenshots/example5.png" height="15%" align="top" />
|
||||
|
||||
## Customization
|
||||
|
||||
@@ -11,8 +16,8 @@ With customization and speed being two competing goals, this project actually bu
|
||||
The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `~/.config/fastfetch/config.conf`. To view the available options run `fastfetch --help`.
|
||||
The second executable being built is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
|
||||
At the moment the performance difference is measurable, but too small to be human recognizable. But the leap will get bigger with more and more options coming, and on slow machines this might actually make a difference.
|
||||
|
||||
There are some presets defined for fastfech in [`presets`](presets), you can can load them with `--load-config`. They may also serve as a good example for format arguments.
|
||||
|
||||
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -45,12 +50,12 @@ All categories not listed here should work without needing a specific implementa
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Song, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Disk, Battery, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
|
||||
```
|
||||
|
||||
##### Logos
|
||||
```
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Ubuntu, Void, Zorin
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Ubuntu, Void, Zorin
|
||||
```
|
||||
* Most of the logos have a small variant. Access it by appending _small to the logo name.
|
||||
* Some logos have an old variant. Access it by appending _old to the logo name.
|
||||
@@ -60,7 +65,7 @@ AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian,
|
||||
|
||||
##### Package managers
|
||||
```
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, brew
|
||||
```
|
||||
|
||||
##### WM themes
|
||||
|
||||
@@ -158,6 +158,7 @@ __fastfetch_completion()
|
||||
"--set"
|
||||
"--set-keyless"
|
||||
"--gl"
|
||||
"--binary-prefix"
|
||||
"--os-format"
|
||||
"--os-key"
|
||||
"--host-format"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--disable-linewrap false
|
||||
--multithreading false
|
||||
--show-errors true
|
||||
--show-errors
|
||||
--recache
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
--load-config verbose
|
||||
--load-config devinfo
|
||||
--load-config all
|
||||
--load-config verbose
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# Load with --load-config examples/1
|
||||
@@ -0,0 +1,24 @@
|
||||
# Load with --load-config examples/2
|
||||
# Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
--kitty /home/linus/Bilder/Gentoo.png
|
||||
--logo-width 28
|
||||
|
||||
--separator " "
|
||||
|
||||
--set-keyless HardwareStart=┌───────── \e[1mHardware Information\e[0m ─────────┐
|
||||
--set-keyless SoftwareStart=├───────── \e[1mSoftware Information\e[0m ─────────┤
|
||||
--set-keyless InformationEnd=└────────────────────────────────────────┘
|
||||
--set-keyless Colors= \e[38m \e[37m \e[36m \e[35m \e[34m \e[33m \e[32m \e[31m
|
||||
--structure HardwareStart:Host:CPU:GPU:SoftwareStart:OS:Kernel:WM:Shell:Terminal:TerminalFont:Packages:InformationEnd:Colors
|
||||
|
||||
--host-key " "
|
||||
--cpu-key " "
|
||||
--gpu-key " "
|
||||
--os-key " "
|
||||
--kernel-key " "
|
||||
--wm-key " "
|
||||
--shell-key " "
|
||||
--terminal-key " "
|
||||
--terminal-font-key " "
|
||||
--packages-key " "
|
||||
@@ -0,0 +1,7 @@
|
||||
# Load with --load-config example/3
|
||||
|
||||
--logo debian_small
|
||||
--structure Vulkan:OpenGL:OpenCL:Memory:Disk:LocalIP
|
||||
--binary-prefix si
|
||||
--localip-show-loop false
|
||||
--disk-folders /:/home:/boot:/efi
|
||||
@@ -0,0 +1,7 @@
|
||||
# Load with --load-config examples/4
|
||||
|
||||
--color blue
|
||||
--logo arch_small
|
||||
--logo-padding-right 1
|
||||
--separator " "
|
||||
--structure Date:Time:Break:Player:Media
|
||||
@@ -0,0 +1,12 @@
|
||||
# Load with --load-config examples/5
|
||||
|
||||
--logo none
|
||||
--color reset_magenta
|
||||
--structure Theme:Icons:Font:Cursor
|
||||
--theme-key T
|
||||
--theme-format {7}
|
||||
--icons-key I
|
||||
--icons-format {5}
|
||||
--font-key F
|
||||
--font-format {21}
|
||||
--cursor-key C
|
||||
@@ -1,31 +1,29 @@
|
||||
--load-config all
|
||||
|
||||
--os-format "System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}"
|
||||
--host-format "Family: "product_family: {}; product_name: {}; product_version: {}; product_sku: {}; bios_date: {}; bios_release: {}; bios_vendor: {}; bios_version: {}; board_name: {}; board_vendor: {}; board_version: {}; chassis_type: {}; chassis_vendor: {}; chassis_version: {}; sys_vendor: {}"
|
||||
--kernel-format "Sysname: {}; Release: {}; Version: {}"
|
||||
--uptime-format "Days: {}; Hours: {}; Minutes: {}; Seconds: {}"
|
||||
--processes-format "Count: {}"
|
||||
--packages-format "All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; xbps: {}; flatpak: {}; snap: {}"
|
||||
--shell-format "Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}"
|
||||
--resolution-format "Width: {}; Height: {}; Refresh rate: {}"
|
||||
--de-format "Process name: {}; Pretty name: {}; Version: {}"
|
||||
--wm-format "Process name: {}; Pretty name: {}; Protocol: {}"
|
||||
--wm-theme-format "Name: {}"
|
||||
--theme-format "Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}"
|
||||
--icons-format "Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}"
|
||||
--font-format "Plasma raw: {}; Plasma name: {}; Plasma size: {}; Plasma styles: {}; Plasma pretty: {}; GTK2 raw: {}; GTK2 name: {}; GTK2 size: {}; GTK2 styles: {}; GTK2 pretty: {}; GTK3 raw: {}; GTK3 name: {}; GTK3 size: {}; GTK3 styles: {}; GTK3 pretty: {}; GTK4 raw: {}; GTK4 name: {}; GTK4 size: {}; GTK4 styles: {}; GTK4 pretty: {}; GTK: {}"
|
||||
--cursor-format "Theme: {}; Size: {}"
|
||||
--terminal-format "Process: {}; Path: {}; Exe: {}"
|
||||
--terminal-font-format "Raw: {}; Name: {}; Size: {}; Styles: {}; Pretty: {}"
|
||||
--cpu-format "Name: {}; Pretty: {}; Vendor: {}; Logical online: {}; Logical configured: {}; Physical: {}; Cores: {}; temperature: {}; bios: {}; scaling max: {}; scaling min: {}; info max: {}; info min: {}; cpuinfo: {}; frequency: {}"
|
||||
--cpu-usage-format "Percentage: {}"
|
||||
--gpu-format "Vendor: {}; Vendor pretty: {}; Name: {}; Name pretty: {}; Driver: {}; Temperature: {}"
|
||||
--memory-format "Used: {}; Total: {}; Percentage: {}"
|
||||
--disk-format "Used: {}; Total: {}; Files: {}; Percentage: {}"
|
||||
--battery-format "Manufactor: {}; Model: {}; Technology: {}; Capacaty: {}; Status: {}"
|
||||
--player-format "Name: {}"
|
||||
--song-format "Song: {}; Artist: {}; Album: {}"
|
||||
--datetime-format "year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}"
|
||||
--vulkan-format "driver: {}; Api Version: {}; Conformance Version: {}"
|
||||
--opengl-format "version: {}; renderer: {}; vendor: {}"
|
||||
--opencl-format "version: {}; device: {}; vendor: {}"
|
||||
--os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}
|
||||
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; bios_date: {}; bios_release: {}; bios_vendor: {}; bios_version: {}; board_name: {}; board_vendor: {}; board_version: {}; chassis_type: {}; chassis_vendor: {}; chassis_version: {}; sys_vendor: {}
|
||||
--kernel-format Sysname: {}; Release: {}; Version: {}
|
||||
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
|
||||
--processes-format Count: {}
|
||||
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}
|
||||
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
|
||||
--resolution-format Width: {}; Height: {}; Refresh rate: {}
|
||||
--de-format Process name: {}; Pretty name: {}; Version: {}
|
||||
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
|
||||
--wm-theme-format Name: {}
|
||||
--theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||
--icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||
--font-format Plasma raw: {}; Plasma name: {}; Plasma size: {}; Plasma styles: {}; Plasma pretty: {}; GTK2 raw: {}; GTK2 name: {}; GTK2 size: {}; GTK2 styles: {}; GTK2 pretty: {}; GTK3 raw: {}; GTK3 name: {}; GTK3 size: {}; GTK3 styles: {}; GTK3 pretty: {}; GTK4 raw: {}; GTK4 name: {}; GTK4 size: {}; GTK4 styles: {}; GTK4 pretty: {}; GTK: {}
|
||||
--cursor-format Theme: {}; Size: {}
|
||||
--terminal-format Process: {}; Path: {}; Exe: {}
|
||||
--terminal-font-format Raw: {}; Name: {}; Size: {}; Styles: {}; Pretty: {}
|
||||
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
|
||||
--cpu-usage-format Percentage: {}
|
||||
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}
|
||||
--memory-format Used: {}; Total: {}; Percentage: {}
|
||||
--disk-format Used: {}; Total: {}; Files: {}; Percentage: {}
|
||||
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
|
||||
--player-format Name: {}
|
||||
--song-format Song: {}; Artist: {}; Album: {}
|
||||
--datetime-format year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}
|
||||
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
|
||||
--opengl-format version: {}; renderer: {}; vendor: {}
|
||||
--opencl-format version: {}; device: {}; vendor: {}
|
||||
|
||||
|
Before Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 133 KiB |
@@ -5,6 +5,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FF_CACHE_VERSION_NAME "cacheversion"
|
||||
#define FF_CACHE_VERSION_EXTENSION "ffv"
|
||||
|
||||
#define FF_CACHE_VALUE_EXTENSION "ffcv"
|
||||
#define FF_CACHE_SPLIT_EXTENSION "ffcs"
|
||||
|
||||
@@ -44,9 +47,11 @@ void ffCacheValidate(FFinstance* instance)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInit(&content);
|
||||
readCacheFile(instance, "cacheversion", "ffv", &content);
|
||||
readCacheFile(instance, FF_CACHE_VERSION_NAME, FF_CACHE_VERSION_EXTENSION, &content);
|
||||
|
||||
bool isSameVersion = ffStrbufCompS(&content, FASTFETCH_PROJECT_VERSION) == 0;
|
||||
const char exactVersion[] = FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK;
|
||||
|
||||
bool isSameVersion = ffStrbufCompS(&content, exactVersion) == 0;
|
||||
ffStrbufDestroy(&content);
|
||||
if(isSameVersion)
|
||||
return;
|
||||
@@ -54,9 +59,9 @@ void ffCacheValidate(FFinstance* instance)
|
||||
instance->config.recache = true;
|
||||
|
||||
FFstrbuf version;
|
||||
ffStrbufInitA(&version, sizeof(FASTFETCH_PROJECT_VERSION));
|
||||
ffStrbufAppendS(&version, FASTFETCH_PROJECT_VERSION);
|
||||
writeCacheFile(instance, "cacheversion", "ffv", &version);
|
||||
ffStrbufInitA(&version, sizeof(exactVersion));
|
||||
ffStrbufAppendS(&version, exactVersion);
|
||||
writeCacheFile(instance, FF_CACHE_VERSION_NAME, FF_CACHE_VERSION_EXTENSION, &version);
|
||||
ffStrbufDestroy(&version);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/format.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
{
|
||||
@@ -63,11 +64,10 @@ static inline void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placehol
|
||||
static inline bool formatArgSet(const FFformatarg* arg)
|
||||
{
|
||||
return arg->value != NULL && (
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value == *(double*)arg->value) || //NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && *(const char*)arg->value != '\0') ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet(arg->value)) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "common/parsing.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -110,7 +110,10 @@ static void initState(FFstate* state)
|
||||
state->keysHeight = 0;
|
||||
state->passwd = getpwuid(getuid());
|
||||
uname(&state->utsname);
|
||||
sysinfo(&state->sysinfo);
|
||||
|
||||
#if FF_HAVE_SYSINFO_H
|
||||
sysinfo(&state->sysinfo);
|
||||
#endif
|
||||
|
||||
initConfigDirs(state);
|
||||
initCacheDir(state);
|
||||
@@ -146,6 +149,7 @@ static void defaultConfig(FFinstance* instance)
|
||||
instance->config.disableLinewrap = true;
|
||||
instance->config.hideCursor = true;
|
||||
instance->config.escapeBedrock = true;
|
||||
instance->config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
|
||||
instance->config.glType = FF_GL_TYPE_AUTO;
|
||||
instance->config.pipe = false;
|
||||
instance->config.multithreading = true;
|
||||
@@ -291,7 +295,7 @@ void startDetectionThreads(FFinstance* instance)
|
||||
//Android needs none of the things that are detected here
|
||||
//And using gsettings sometimes hangs the program in android for some unknown reason,
|
||||
//and since we don't need it we just never call it.
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ static void createSubfolders(const char* fileName)
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
|
||||
bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
|
||||
{
|
||||
return write(fd, content->chars, content->length) != -1;
|
||||
|
||||
@@ -28,7 +28,7 @@ void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, F
|
||||
{
|
||||
struct timeval timev;
|
||||
timev.tv_sec = 0;
|
||||
timev.tv_usec = timeout * 1000; //milliseconds to microseconds
|
||||
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/parsing.h"
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
bool ffStrSet(const char* str)
|
||||
{
|
||||
if(str == NULL)
|
||||
return false;
|
||||
|
||||
while(*str != '\0')
|
||||
{
|
||||
if(*str != ' ' && *str != '\t' && *str != '\n' && *str != '\r')
|
||||
return true;
|
||||
}
|
||||
while(isspace(*str))
|
||||
str++;
|
||||
|
||||
return false;
|
||||
return *str != '\0';
|
||||
}
|
||||
|
||||
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
|
||||
@@ -66,6 +65,37 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty)
|
||||
ffStrbufAppendF(pretty, ".%u", version->patch);
|
||||
}
|
||||
|
||||
static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, uint8_t prefixesLength, const char** prefixes)
|
||||
{
|
||||
long double size = (long double) bytes;
|
||||
uint8_t counter = 0;
|
||||
|
||||
while(size > base && counter < prefixesLength - 1)
|
||||
{
|
||||
size /= base;
|
||||
counter++;
|
||||
}
|
||||
|
||||
if(counter == 0)
|
||||
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
|
||||
else if(counter < 3 || (counter == 3 && size < 100.0))
|
||||
ffStrbufAppendF(result, "%.2Lf %s", size, prefixes[counter]);
|
||||
else
|
||||
ffStrbufAppendF(result, "%.0Lf %s", size, prefixes[counter]);
|
||||
}
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result)
|
||||
{
|
||||
if(binaryPrefix == FF_BINARY_PREFIX_TYPE_IEC)
|
||||
parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB"});
|
||||
else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_SI)
|
||||
parseSize(result, bytes, 1000, 5, (const char*[]) {"B", "kB", "MB", "GB", "TB"});
|
||||
else if(binaryPrefix == FF_BINARY_PREFIX_TYPE_JEDEC)
|
||||
parseSize(result, bytes, 1024, 5, (const char*[]) {"B", "KB", "MB", "GB", "TB"});
|
||||
else
|
||||
parseSize(result, bytes, 1024, 1, (const char*[]) {"B"});
|
||||
}
|
||||
|
||||
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4)
|
||||
{
|
||||
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
|
||||
|
||||
@@ -21,4 +21,6 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty);
|
||||
int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFBinaryPrefixType binaryPrefix, FFstrbuf* result);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -352,10 +352,44 @@ int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, cons
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/system_properties.h>
|
||||
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
|
||||
uint32_t originalLength = result->length;
|
||||
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
|
||||
ffStrbufEnsureFree(result, PROP_VALUE_MAX);
|
||||
result->length += (uint32_t) __system_property_get(propName, result->chars + result->length);
|
||||
return result->length > originalLength;
|
||||
result->chars[result->length] = '\0';
|
||||
}
|
||||
#endif
|
||||
#endif //__ANDROID__
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
void ffSettingsGetAppleProperty(const char* propName, FFstrbuf* result)
|
||||
{
|
||||
size_t neededLength;
|
||||
if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(result, (uint32_t) neededLength);
|
||||
|
||||
if(sysctlbyname(propName, result->chars + result->length, &neededLength, NULL, 0) == 0)
|
||||
result->length += (uint32_t) neededLength;
|
||||
|
||||
result->chars[result->length] = '\0';
|
||||
}
|
||||
|
||||
int ffSettingsGetAppleInt(const char* propName, int defaultValue)
|
||||
{
|
||||
int result;
|
||||
size_t neededLength = sizeof(result);
|
||||
if(sysctlbyname(propName, &result, &neededLength, NULL, 0) != 0)
|
||||
return defaultValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t ffSettingsGetAppleInt64(const char* propName, int64_t defaultValue)
|
||||
{
|
||||
int64_t result;
|
||||
size_t neededLength = sizeof(result);
|
||||
if(sysctlbyname(propName, &result, &neededLength, NULL, 0) != 0)
|
||||
return defaultValue;
|
||||
return result;
|
||||
}
|
||||
#endif //__APPLE__
|
||||
|
||||
@@ -33,7 +33,13 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
|
||||
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
|
||||
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
void ffSettingsGetAppleProperty(const char* propName, FFstrbuf* result);
|
||||
int ffSettingsGetAppleInt(const char* propName, int defaultValue);
|
||||
int64_t ffSettingsGetAppleInt64(const char* propName, int64_t defaultValue);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Fastfetch system configuration
|
||||
# This file sets the defaults for all users of the system.
|
||||
# This file sets the default config for all users of the system.
|
||||
|
||||
# For more information about configuration files work,
|
||||
# see the file ~/.config/fastfetch/config.conf, generated during first
|
||||
# For more information about how configuration files work,
|
||||
# see ~/.config/fastfetch/config.conf, generated during first run.
|
||||
# All options that can be put there (or passed as argument) can be put here too.
|
||||
|
||||
# This file was shipped with $"FASTFETCH_PROJECT_VERSION$".
|
||||
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf to overwrite this file with the current defaults
|
||||
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf
|
||||
# to overwrite this file with the current default file.
|
||||
|
||||
# User config option
|
||||
# Sets if fastfetch should load user provided configuration.
|
||||
|
||||
@@ -120,6 +120,12 @@
|
||||
# Use "fastfetch --help color" to learn more and see examples.
|
||||
#--color magenta
|
||||
|
||||
# Binary prefix option:
|
||||
# Sets the binary prefix to use.
|
||||
# Must be a IEC, SI or JEDEC.
|
||||
# Default is IEC.
|
||||
#--binary-prefix IEC
|
||||
|
||||
# Title FQDN option:
|
||||
# Sets if the title should use the fully qualified domain name.
|
||||
# Must be true or false.
|
||||
|
||||
@@ -47,6 +47,7 @@ Display options:
|
||||
--show-errors <?value>: print occuring errors
|
||||
--disable-linewrap <?value>: weather to disable linewrap during the run
|
||||
--hide-cursor <?value>: weather to hide the cursor during the run
|
||||
--binary-prefix <value>: sets the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC
|
||||
|
||||
General module options:
|
||||
--<module>-format <format>: Sets the format string to use for each specific module.
|
||||
|
||||
@@ -15,6 +15,7 @@ Icons
|
||||
Kernel
|
||||
Locale
|
||||
LocalIP
|
||||
Media
|
||||
Memory
|
||||
OS
|
||||
OpenCL
|
||||
@@ -26,7 +27,6 @@ PublicIP
|
||||
Resolution
|
||||
Separator
|
||||
Shell
|
||||
Song
|
||||
Terminal
|
||||
TerminalFont
|
||||
Theme
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "cpu.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
void ffDetectCPUImpl(FFCPUResult* cpu);
|
||||
|
||||
const FFCPUResult* ffDetectCPU()
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFCPUResult,
|
||||
ffDetectCPUImpl(&result);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"(R)", "(r)", "(TM)", "(tm)",
|
||||
" CPU", " FPU", " APU", " Processor",
|
||||
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
|
||||
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core",
|
||||
" with Radeon Graphics"
|
||||
};
|
||||
ffStrbufRemoveStringsA(&result.name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||
ffStrbufSubstrBeforeFirstC(&result.name, '@'); //Cut the speed output in the name as we append our own
|
||||
ffStrbufTrimRight(&result.name, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_cpu_cpu
|
||||
#define FF_INCLUDED_detection_cpu_cpu
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_CPU_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct FFCPUResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
|
||||
uint16_t coresPhysical;
|
||||
uint16_t coresLogical;
|
||||
uint16_t coresOnline;
|
||||
|
||||
double frequencyMin;
|
||||
double frequencyMax;
|
||||
|
||||
double temperature;
|
||||
} FFCPUResult;
|
||||
|
||||
const FFCPUResult* ffDetectCPU();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "cpu.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
static double getFrequency(const char* propName)
|
||||
{
|
||||
double herz = (double) ffSettingsGetAppleInt64(propName, 0);
|
||||
if(herz <= 0.0)
|
||||
return herz;
|
||||
|
||||
herz /= 1000.0; //to KHz
|
||||
herz /= 1000.0; //to MHz
|
||||
return herz / 1000.0; //to GHz
|
||||
}
|
||||
|
||||
void ffDetectCPUImpl(FFCPUResult* cpu)
|
||||
{
|
||||
ffStrbufInit(&cpu->name);
|
||||
ffSettingsGetAppleProperty("machdep.cpu.brand_string", &cpu->name);
|
||||
|
||||
ffStrbufInit(&cpu->vendor);
|
||||
ffSettingsGetAppleProperty("machdep.cpu.vendor", &cpu->vendor);
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSettingsGetAppleInt("hw.physicalcpu_max", 1);
|
||||
if(cpu->coresPhysical == 1)
|
||||
cpu->coresPhysical = (uint16_t) ffSettingsGetAppleInt("hw.physicalcpu", 1);
|
||||
|
||||
cpu->coresLogical = (uint16_t) ffSettingsGetAppleInt("hw.logicalcpu_max", 1);
|
||||
if(cpu->coresLogical == 1)
|
||||
cpu->coresLogical = (uint16_t) ffSettingsGetAppleInt("hw.ncpu", 1);
|
||||
|
||||
cpu->coresOnline = (uint16_t) ffSettingsGetAppleInt("hw.logicalcpu", 1);
|
||||
if(cpu->coresOnline == 1)
|
||||
cpu->coresOnline = (uint16_t) ffSettingsGetAppleInt("hw.activecpu", 1);
|
||||
|
||||
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
|
||||
if(cpu->frequencyMax == 0.0)
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency");
|
||||
|
||||
//TODO find a way to detect this
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "cpu.h"
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer)
|
||||
{
|
||||
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if(cpuinfo == NULL)
|
||||
return;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while(getline(&line, &len, cpuinfo) != -1)
|
||||
{
|
||||
//Stop after the first CPU
|
||||
if(cpu->name.length > 0 && (*line == '\0' || *line == '\n'))
|
||||
break;
|
||||
|
||||
(void)(
|
||||
ffParsePropLine(line, "model name :", &cpu->name) ||
|
||||
ffParsePropLine(line, "vendor_id :", &cpu->vendor) ||
|
||||
ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) //For Android devices
|
||||
);
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(cpuinfo);
|
||||
}
|
||||
|
||||
static double getGHz(const char* file)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInit(&content);
|
||||
ffReadFileBuffer(file, &content);
|
||||
double herz = ffStrbufToDouble(&content);
|
||||
ffStrbufDestroy(&content);
|
||||
|
||||
//ffStrbufToDouble failed
|
||||
if(herz != herz)
|
||||
return 0;
|
||||
|
||||
herz /= 1000.0; //to MHz
|
||||
return herz / 1000.0; //to GHz
|
||||
}
|
||||
|
||||
static double getFrequency(const char* info, const char* scaling)
|
||||
{
|
||||
double frequency = getGHz(info);
|
||||
if(frequency > 0.0)
|
||||
return frequency;
|
||||
|
||||
return getGHz(scaling);
|
||||
}
|
||||
|
||||
static double detectCPUTemp()
|
||||
{
|
||||
const FFTempsResult *temps = ffDetectTemps();
|
||||
|
||||
for(uint32_t i = 0; i < temps->values.length; i++)
|
||||
{
|
||||
FFTempValue* value = ffListGet(&temps->values, i);
|
||||
|
||||
if(
|
||||
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
|
||||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
|
||||
ffStrbufCompS(&value->name, "coretemp") == 0
|
||||
) return value->value;
|
||||
}
|
||||
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
void ffDetectCPUImpl(FFCPUResult* cpu)
|
||||
{
|
||||
ffStrbufInit(&cpu->name);
|
||||
ffStrbufInit(&cpu->vendor);
|
||||
|
||||
FFstrbuf physicalCoresBuffer;
|
||||
ffStrbufInit(&physicalCoresBuffer);
|
||||
|
||||
parseCpuInfo(cpu, &physicalCoresBuffer);
|
||||
|
||||
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
|
||||
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
|
||||
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
|
||||
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
|
||||
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
|
||||
|
||||
cpu->temperature = detectCPUTemp();
|
||||
|
||||
ffStrbufDestroy(&physicalCoresBuffer);
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
#include "displayServer.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <dirent.h>
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
|
||||
{
|
||||
if(refreshRate <= 0)
|
||||
return 0;
|
||||
|
||||
int remainder = refreshRate % 5;
|
||||
if(remainder >= 3)
|
||||
refreshRate += (5 - remainder);
|
||||
else
|
||||
refreshRate -= remainder;
|
||||
|
||||
//All other typicall refresh rates are dividable by 5
|
||||
if(refreshRate == 145)
|
||||
refreshRate = 144;
|
||||
|
||||
return (uint32_t) refreshRate;
|
||||
}
|
||||
|
||||
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate)
|
||||
{
|
||||
if(width == 0 || height == 0)
|
||||
return false;
|
||||
|
||||
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
|
||||
resolution->width = width;
|
||||
resolution->height = height;
|
||||
resolution->refreshRate = refreshRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void parseDRM(FFDisplayServerResult* result)
|
||||
{
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
|
||||
DIR* dirp = opendir(drmDirPath);
|
||||
if(dirp == NULL)
|
||||
return;
|
||||
|
||||
FFstrbuf drmDir;
|
||||
ffStrbufInitA(&drmDir, 64);
|
||||
ffStrbufAppendS(&drmDir, drmDirPath);
|
||||
|
||||
uint32_t drmDirLength = drmDir.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
ffStrbufAppendS(&drmDir, "/modes");
|
||||
|
||||
FILE* modeFile = fopen(drmDir.chars, "r");
|
||||
if(modeFile == NULL)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
|
||||
resolution->width = 0;
|
||||
resolution->height = 0;
|
||||
resolution->refreshRate = 0;
|
||||
|
||||
int scanned = fscanf(modeFile, "%ix%i", &resolution->width, &resolution->height);
|
||||
if(scanned < 2 || resolution->width == 0 || resolution->height == 0)
|
||||
--result->resolutions.length;
|
||||
|
||||
fclose(modeFile);
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
ffStrbufDestroy(&drmDir);
|
||||
}
|
||||
|
||||
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance)
|
||||
{
|
||||
static FFDisplayServerResult result;
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.wmProcessName);
|
||||
ffStrbufInit(&result.wmPrettyName);
|
||||
ffStrbufInit(&result.wmProtocolName);
|
||||
ffStrbufInit(&result.deProcessName);
|
||||
ffStrbufInit(&result.dePrettyName);
|
||||
ffStrbufInit(&result.deVersion);
|
||||
ffListInitA(&result.resolutions, sizeof(FFResolutionResult), 4);
|
||||
|
||||
//We try wayland as our prefered display server, as it supports the most features.
|
||||
//This method can't detect the name of our WM / DE
|
||||
ffdsConnectWayland(instance, &result);
|
||||
|
||||
//Try the x11 libs, from most feature rich to least.
|
||||
//We use the resolution list to detect if a connection is needed.
|
||||
//They respect wmProtocolName, and only detect resolution if it is set.
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXcbRandr(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXrandr(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXcb(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXlib(instance, &result);
|
||||
|
||||
//This resolution detection method is display server independent.
|
||||
//Use it if all connections failed
|
||||
if(result.resolutions.length == 0)
|
||||
parseDRM(&result);
|
||||
|
||||
//This fills in missing information about WM / DE by using env vars and iterating processes
|
||||
ffdsDetectWMDE(instance, &result);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "displayserver.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
|
||||
{
|
||||
if(refreshRate <= 0)
|
||||
return 0;
|
||||
|
||||
int remainder = refreshRate % 5;
|
||||
if(remainder >= 3)
|
||||
refreshRate += (5 - remainder);
|
||||
else
|
||||
refreshRate -= remainder;
|
||||
|
||||
//All other typicall refresh rates are dividable by 5
|
||||
if(refreshRate == 145)
|
||||
refreshRate = 144;
|
||||
|
||||
return (uint32_t) refreshRate;
|
||||
}
|
||||
|
||||
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate)
|
||||
{
|
||||
if(width == 0 || height == 0)
|
||||
return false;
|
||||
|
||||
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
|
||||
resolution->width = width;
|
||||
resolution->height = height;
|
||||
resolution->refreshRate = refreshRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance);
|
||||
|
||||
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFDisplayServerResult,
|
||||
ffConnectDisplayServerImpl(&result, instance);
|
||||
);
|
||||
}
|
||||
@@ -25,5 +25,8 @@ typedef struct FFDisplayServerResult
|
||||
|
||||
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance);
|
||||
|
||||
#endif
|
||||
//Used internal
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
|
||||
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "displayserver.h"
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInitA(&ds->wmProcessName, 0);
|
||||
ffStrbufInitA(&ds->wmPrettyName, 0);
|
||||
ffStrbufInitA(&ds->wmProtocolName, 0);
|
||||
ffStrbufInitA(&ds->deProcessName, 0);
|
||||
ffStrbufInitA(&ds->dePrettyName, 0);
|
||||
ffStrbufInitA(&ds->deVersion, 0);
|
||||
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 0);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "displayserver.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
//Resolution code heavily inspired by displayplacer <3
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t rawData[0xDC];
|
||||
struct
|
||||
{
|
||||
uint32_t mode;
|
||||
uint32_t flags; // 0x4
|
||||
uint32_t width; // 0x8
|
||||
uint32_t height; // 0xC
|
||||
uint32_t depth; // 0x10
|
||||
uint32_t dc2[42];
|
||||
uint16_t dc3;
|
||||
uint16_t freq; // 0xBC
|
||||
uint32_t dc4[4];
|
||||
float density; // 0xD0
|
||||
} derived;
|
||||
} modes_D4;
|
||||
|
||||
void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
|
||||
void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID display, int idx, modes_D4* mode, int length);
|
||||
|
||||
static void detectResolution(FFDisplayServerResult* ds)
|
||||
{
|
||||
void* cg = dlopen(FASTFETCH_TARGET_DIR_ROOT"/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics", RTLD_LAZY);
|
||||
if(cg == NULL)
|
||||
return;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(cg, CGGetOnlineDisplayList, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(cg, CGDisplayScreenSize, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(cg, CGSGetCurrentDisplayMode, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(cg, CGSGetDisplayModeDescriptionOfLength, )
|
||||
|
||||
CGDisplayCount screenCount;
|
||||
ffCGGetOnlineDisplayList(INT_MAX, NULL, &screenCount);
|
||||
if(screenCount == 0)
|
||||
{
|
||||
dlclose(cg);
|
||||
return;
|
||||
}
|
||||
|
||||
CGDirectDisplayID* screens = malloc(screenCount * sizeof(CGDirectDisplayID));
|
||||
ffCGGetOnlineDisplayList(INT_MAX, screens, &screenCount);
|
||||
|
||||
for(uint32_t i = 0; i < screenCount; i++)
|
||||
{
|
||||
int modeID;
|
||||
ffCGSGetCurrentDisplayMode(screens[i], &modeID);
|
||||
modes_D4 mode;
|
||||
ffCGSGetDisplayModeDescriptionOfLength(screens[i], modeID, &mode, 0xD4);
|
||||
|
||||
uint32_t refreshRate = ffdsParseRefreshRate(mode.derived.freq);
|
||||
ffdsAppendResolution(ds, mode.derived.width, mode.derived.height, refreshRate);
|
||||
}
|
||||
|
||||
free(screens);
|
||||
dlclose(cg);
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInit(&ds->wmProcessName);
|
||||
ffStrbufAppendS(&ds->wmProcessName, "quartz");
|
||||
|
||||
ffStrbufInit(&ds->wmPrettyName);
|
||||
ffStrbufAppendS(&ds->wmPrettyName, "Quartz Compositor");
|
||||
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufAppendS(&ds->deProcessName, "aqua");
|
||||
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufAppendS(&ds->dePrettyName, "Aqua");
|
||||
|
||||
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
|
||||
detectResolution(ds);
|
||||
|
||||
ffStrbufInitA(&ds->deVersion, 0);
|
||||
ffStrbufInitA(&ds->wmProtocolName, 0);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "displayserver_linux.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static void parseDRM(FFDisplayServerResult* result)
|
||||
{
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
|
||||
DIR* dirp = opendir(drmDirPath);
|
||||
if(dirp == NULL)
|
||||
return;
|
||||
|
||||
FFstrbuf drmDir;
|
||||
ffStrbufInitA(&drmDir, 64);
|
||||
ffStrbufAppendS(&drmDir, drmDirPath);
|
||||
|
||||
uint32_t drmDirLength = drmDir.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
ffStrbufAppendS(&drmDir, "/modes");
|
||||
|
||||
FILE* modeFile = fopen(drmDir.chars, "r");
|
||||
if(modeFile == NULL)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
|
||||
resolution->width = 0;
|
||||
resolution->height = 0;
|
||||
resolution->refreshRate = 0;
|
||||
|
||||
int scanned = fscanf(modeFile, "%ix%i", &resolution->width, &resolution->height);
|
||||
if(scanned < 2 || resolution->width == 0 || resolution->height == 0)
|
||||
--result->resolutions.length;
|
||||
|
||||
fclose(modeFile);
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
ffStrbufDestroy(&drmDir);
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
|
||||
{
|
||||
ffStrbufInit(&ds->wmProcessName);
|
||||
ffStrbufInit(&ds->wmPrettyName);
|
||||
ffStrbufInit(&ds->wmProtocolName);
|
||||
ffStrbufInit(&ds->deProcessName);
|
||||
ffStrbufInit(&ds->dePrettyName);
|
||||
ffStrbufInit(&ds->deVersion);
|
||||
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
|
||||
|
||||
//We try wayland as our prefered display server, as it supports the most features.
|
||||
//This method can't detect the name of our WM / DE
|
||||
ffdsConnectWayland(instance, ds);
|
||||
|
||||
//Try the x11 libs, from most feature rich to least.
|
||||
//We use the resolution list to detect if a connection is needed.
|
||||
//They respect wmProtocolName, and only detect resolution if it is set.
|
||||
|
||||
if(ds->resolutions.length == 0)
|
||||
ffdsConnectXcbRandr(instance, ds);
|
||||
|
||||
if(ds->resolutions.length == 0)
|
||||
ffdsConnectXrandr(instance, ds);
|
||||
|
||||
if(ds->resolutions.length == 0)
|
||||
ffdsConnectXcb(instance, ds);
|
||||
|
||||
if(ds->resolutions.length == 0)
|
||||
ffdsConnectXlib(instance, ds);
|
||||
|
||||
//This resolution detection method is display server independent.
|
||||
//Use it if all connections failed
|
||||
if(ds->resolutions.length == 0)
|
||||
parseDRM(ds);
|
||||
|
||||
//This fills in missing information about WM / DE by using env vars and iterating processes
|
||||
ffdsDetectWMDE(instance, ds);
|
||||
}
|
||||
@@ -3,16 +3,12 @@
|
||||
#ifndef FASTFETCH_INCLUDED_DISPLAYSERVER
|
||||
#define FASTFETCH_INCLUDED_DISPLAYSERVER
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
|
||||
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate);
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
@@ -1,6 +1,6 @@
|
||||
#define _GNU_SOURCE //required for struct ucred
|
||||
|
||||
#include "displayServer.h"
|
||||
#include "displayserver_linux.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "displayServer.h"
|
||||
#include "displayserver_linux.h"
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "displayServer.h"
|
||||
#include "displayserver_linux.h"
|
||||
|
||||
#ifdef FF_HAVE_XCB
|
||||
#include "common/library.h"
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "displayServer.h"
|
||||
#include "displayserver_linux.h"
|
||||
|
||||
#ifdef FF_HAVE_X11
|
||||
#include "common/library.h"
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
|
||||
|
||||
const FFlist* ffDetectGPU(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFlist,
|
||||
ffListInit(&result, sizeof(FFGPUResult));
|
||||
ffDetectGPUImpl(&result, instance);
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_gpu_gpu
|
||||
#define FF_INCLUDED_detection_gpu_gpu
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_GPU_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct FFGPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
FFstrbuf driver;
|
||||
double temperature;
|
||||
} FFGPUResult;
|
||||
|
||||
const FFlist* ffDetectGPU(const FFinstance* instance);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "gpu.h"
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(gpus, instance);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "gpu.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
void* iokit = dlopen(FASTFETCH_TARGET_DIR_ROOT"/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_LAZY);
|
||||
if(iokit == NULL)
|
||||
return;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, IOServiceMatching, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, IOServiceGetMatchingServices, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, kIOMasterPortDefault, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, IOIteratorNext, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, IORegistryEntryCreateCFProperties, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, kCFAllocatorDefault, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFDictionaryGetValue, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFGetTypeID, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFStringCreateWithCStringNoCopy, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFStringGetLength, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFStringGetCString, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFRelease, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, CFDataGetTypeID, )
|
||||
FF_LIBRARY_LOAD_SYMBOL(iokit, IOObjectRelease, )
|
||||
|
||||
CFMutableDictionaryRef matchDict = ffIOServiceMatching(kIOAcceleratorClassName);
|
||||
io_iterator_t iterator;
|
||||
if(ffIOServiceGetMatchingServices(*ffkIOMasterPortDefault, matchDict, &iterator) != kIOReturnSuccess)
|
||||
{
|
||||
dlclose(iokit);
|
||||
return;
|
||||
}
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = ffIOIteratorNext(iterator)) != 0)
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
if(ffIORegistryEntryCreateCFProperties(registryEntry, &properties, *ffkCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
ffIOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
CFStringRef key = ffCFStringCreateWithCStringNoCopy(NULL, "model", kCFStringEncodingUTF8, NULL);
|
||||
CFStringRef model = ffCFDictionaryGetValue(properties, key);
|
||||
if(model == NULL || ffCFGetTypeID(model) != ffCFDataGetTypeID())
|
||||
{
|
||||
ffCFRelease(properties);
|
||||
ffIOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(gpus);
|
||||
|
||||
ffStrbufInitA(&gpu->name, (uint32_t) (ffCFStringGetLength(model) + 1));
|
||||
ffCFStringGetCString(model, gpu->name.chars, ffStrbufGetFree(&gpu->name), kCFStringEncodingUTF8);
|
||||
|
||||
ffStrbufInitA(&gpu->vendor, 0);
|
||||
ffStrbufInitA(&gpu->driver, 0);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
|
||||
ffCFRelease(properties);
|
||||
ffIOObjectRelease(registryEntry);
|
||||
}
|
||||
|
||||
ffIOObjectRelease(iterator);
|
||||
dlclose(iokit);
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/vulkan.h"
|
||||
|
||||
#define FF_GPU_VENDOR_NAME_AMD "AMD"
|
||||
#define FF_GPU_VENDOR_NAME_INTEL "Intel"
|
||||
#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA"
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/temps.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
|
||||
typedef struct PCIData
|
||||
{
|
||||
struct pci_access* access;
|
||||
FF_LIBRARY_SYMBOL(pci_read_byte);
|
||||
FF_LIBRARY_SYMBOL(pci_read_word);
|
||||
FF_LIBRARY_SYMBOL(pci_lookup_name);
|
||||
FF_LIBRARY_SYMBOL(pci_get_param);
|
||||
} 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);
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
|
||||
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) ffStrbufGetFree(&gpu->vendor), PCI_LOOKUP_VENDOR, device->vendor_id);
|
||||
ffStrbufRecalculateLength(&gpu->vendor);
|
||||
|
||||
if(ffStrbufFirstIndexS(&gpu->vendor, "AMD") < gpu->vendor.length || ffStrbufFirstIndexS(&gpu->vendor, "ATI") < gpu->vendor.length)
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufFirstIndexS(&gpu->vendor, "Intel") < gpu->vendor.length)
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufFirstIndexS(&gpu->vendor, "NVIDIA") < gpu->vendor.length)
|
||||
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
}
|
||||
|
||||
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
FFstrbuf query;
|
||||
ffStrbufInit(&query);
|
||||
ffStrbufAppendF(&query, "%X, %X,", device->device_id, pci->ffpci_read_byte(device, PCI_REVISION_ID));
|
||||
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->name);
|
||||
|
||||
ffStrbufDestroy(&query);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"AMD ", "ATI ",
|
||||
" (TM)", "(TM)",
|
||||
" Graphics Adapter", " Graphics", " Series", " Edition"
|
||||
};
|
||||
ffStrbufRemoveStringsA(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||
}
|
||||
|
||||
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
if(ffStrbufCompS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD) == 0)
|
||||
{
|
||||
drmDetectDeviceName(gpu, pci, device);
|
||||
if(gpu->name.length > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
pci->ffpci_lookup_name(pci->access, gpu->name.chars, (int) ffStrbufGetFree(&gpu->name), PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
|
||||
ffStrbufRecalculateLength(&gpu->name);
|
||||
}
|
||||
|
||||
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
|
||||
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
|
||||
{
|
||||
const FFTempsResult* tempsResult = ffDetectTemps();
|
||||
|
||||
for(uint32_t i = 0; i < tempsResult->values.length; i++)
|
||||
{
|
||||
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
|
||||
|
||||
uint32_t tempClass;
|
||||
if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1)
|
||||
continue;
|
||||
|
||||
//The kernel exposes the device class multiplied by 256 for some reason
|
||||
if(tempClass == device->device_class * 256)
|
||||
{
|
||||
gpu->temperature = tempValue->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pciHandleDevice(FFlist* results, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
device->device_class = pci->ffpci_read_word(device, PCI_CLASS_DEVICE);
|
||||
|
||||
char class[1024];
|
||||
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
|
||||
|
||||
if(
|
||||
strcasecmp("VGA compatible controller", class) != 0 &&
|
||||
strcasecmp("3D controller", class) != 0 &&
|
||||
strcasecmp("Display controller", class) != 0
|
||||
) return;
|
||||
|
||||
device->vendor_id = pci->ffpci_read_word(device, PCI_VENDOR_ID);
|
||||
device->device_id = pci->ffpci_read_word(device, PCI_DEVICE_ID);
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
pciDetectVendorName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
pciDetectDeviceName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
pciDetectDriverName(gpu, pci, device);
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
pciDetectTemperatur(gpu, device);
|
||||
}
|
||||
|
||||
static bool pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
|
||||
{
|
||||
PCIData pci;
|
||||
|
||||
FF_LIBRARY_LOAD(libpci, instance->config.libPCI, false, "libpci.so", 4)
|
||||
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_alloc, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_init, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_scan_bus, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(libpci, pci_cleanup, false)
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_read_byte, pci_read_byte, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_read_word, pci_read_word, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_lookup_name, pci_lookup_name, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libpci, pci.ffpci_get_param, pci_get_param, false)
|
||||
|
||||
pci.access = ffpci_alloc();
|
||||
ffpci_init(pci.access);
|
||||
ffpci_scan_bus(pci.access);
|
||||
|
||||
struct pci_dev* device = pci.access->devices;
|
||||
while(device != NULL)
|
||||
{
|
||||
pciHandleDevice(gpus, &pci, device);
|
||||
device = device->next;
|
||||
}
|
||||
|
||||
ffpci_cleanup(pci.access);
|
||||
dlclose(libpci);
|
||||
|
||||
return gpus->length > 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
if(pciDetectGPUs(instance, gpus))
|
||||
return;
|
||||
#endif
|
||||
|
||||
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
|
||||
*gpus = vulkan->gpus;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "detection/gtk.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/settings.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "host.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host);
|
||||
|
||||
const FFHostResult* ffDetectHost()
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFHostResult,
|
||||
ffDetectHostImpl(&result)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_host_host
|
||||
#define FF_INCLUDED_detection_host_host
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux"
|
||||
|
||||
typedef struct FFHostResult
|
||||
{
|
||||
FFstrbuf productFamily;
|
||||
FFstrbuf productName;
|
||||
FFstrbuf productVersion;
|
||||
FFstrbuf productSku;
|
||||
FFstrbuf biosDate;
|
||||
FFstrbuf biosRelease;
|
||||
FFstrbuf biosVendor;
|
||||
FFstrbuf biosVersion;
|
||||
FFstrbuf boardName;
|
||||
FFstrbuf boardVendor;
|
||||
FFstrbuf boardVersion;
|
||||
FFstrbuf chassisType;
|
||||
FFstrbuf chassisVendor;
|
||||
FFstrbuf chassisVersion;
|
||||
FFstrbuf sysVendor;
|
||||
} FFHostResult;
|
||||
|
||||
const FFHostResult* ffDetectHost();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "host.h"
|
||||
#include "common/settings.h"
|
||||
#include <ctype.h>
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
//Family
|
||||
|
||||
ffStrbufInit(&host->productFamily);
|
||||
ffSettingsGetAndroidProperty("ro.product.device", &host->productFamily);
|
||||
|
||||
//Name
|
||||
|
||||
ffStrbufInit(&host->productName);
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.product.brand", &host->productName);
|
||||
if(host->productName.length > 0){
|
||||
host->productName.chars[0] = (char) toupper(host->productName.chars[0]);
|
||||
ffStrbufAppendC(&host->productName, ' ');
|
||||
}
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.product.model", &host->productName);
|
||||
|
||||
ffStrbufTrimRight(&host->productName, ' ');
|
||||
|
||||
//Sys vendor
|
||||
|
||||
ffStrbufInit(&host->sysVendor);
|
||||
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->sysVendor);
|
||||
|
||||
//Not implemented
|
||||
|
||||
ffStrbufInitA(&host->productVersion, 0);
|
||||
ffStrbufInitA(&host->productSku, 0);
|
||||
ffStrbufInitA(&host->biosDate, 0);
|
||||
ffStrbufInitA(&host->biosRelease, 0);
|
||||
ffStrbufInitA(&host->biosVendor, 0);
|
||||
ffStrbufInitA(&host->biosVersion, 0);
|
||||
ffStrbufInitA(&host->boardName, 0);
|
||||
ffStrbufInitA(&host->boardVendor, 0);
|
||||
ffStrbufInitA(&host->boardVersion, 0);
|
||||
ffStrbufInitA(&host->chassisType, 0);
|
||||
ffStrbufInitA(&host->chassisVendor, 0);
|
||||
ffStrbufInitA(&host->chassisVersion, 0);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "host.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->productName);
|
||||
|
||||
ffStrbufInitA(&host->productFamily, 0);
|
||||
ffStrbufInitA(&host->sysVendor, 0);
|
||||
ffStrbufInitA(&host->productVersion, 0);
|
||||
ffStrbufInitA(&host->productSku, 0);
|
||||
ffStrbufInitA(&host->biosDate, 0);
|
||||
ffStrbufInitA(&host->biosRelease, 0);
|
||||
ffStrbufInitA(&host->biosVendor, 0);
|
||||
ffStrbufInitA(&host->biosVersion, 0);
|
||||
ffStrbufInitA(&host->boardName, 0);
|
||||
ffStrbufInitA(&host->boardVendor, 0);
|
||||
ffStrbufInitA(&host->boardVersion, 0);
|
||||
ffStrbufInitA(&host->chassisType, 0);
|
||||
ffStrbufInitA(&host->chassisVendor, 0);
|
||||
ffStrbufInitA(&host->chassisVersion, 0);
|
||||
|
||||
ffSettingsGetAppleProperty("hw.model", &host->productName);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "host.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool hostValueSet(FFstrbuf* value)
|
||||
{
|
||||
return
|
||||
value->length > 0 &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||
;
|
||||
}
|
||||
|
||||
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||
{
|
||||
ffReadFileBuffer(devicesPath, buffer);
|
||||
if(hostValueSet(buffer))
|
||||
return;
|
||||
|
||||
ffReadFileBuffer(classPath, buffer);
|
||||
if(hostValueSet(buffer))
|
||||
return;
|
||||
|
||||
ffStrbufClear(buffer);
|
||||
}
|
||||
|
||||
static void getHostProductName(FFstrbuf* name)
|
||||
{
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name);
|
||||
if(name->length > 0)
|
||||
return;
|
||||
|
||||
ffReadFileBuffer("/sys/firmware/devicetree/base/model", name);
|
||||
if(hostValueSet(name))
|
||||
return;
|
||||
|
||||
//does a clear before the read
|
||||
ffReadFileBuffer("/tmp/sysinfo/model", name);
|
||||
if(hostValueSet(name))
|
||||
return;
|
||||
|
||||
ffStrbufClear(name);
|
||||
}
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->productFamily);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
|
||||
|
||||
ffStrbufInit(&host->productName);
|
||||
getHostProductName(&host->productName);
|
||||
|
||||
ffStrbufInit(&host->productVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion);
|
||||
|
||||
ffStrbufInit(&host->productSku);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
|
||||
|
||||
ffStrbufInit(&host->biosDate);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &host->biosDate);
|
||||
|
||||
ffStrbufInit(&host->biosRelease);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &host->biosRelease);
|
||||
|
||||
ffStrbufInit(&host->biosVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &host->biosVendor);
|
||||
|
||||
ffStrbufInit(&host->biosVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &host->biosVersion);
|
||||
|
||||
ffStrbufInit(&host->boardName);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &host->boardName);
|
||||
|
||||
ffStrbufInit(&host->boardVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &host->boardVendor);
|
||||
|
||||
ffStrbufInit(&host->boardVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &host->boardVersion);
|
||||
|
||||
ffStrbufInit(&host->chassisType);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &host->chassisType);
|
||||
|
||||
ffStrbufInit(&host->chassisVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &host->chassisVendor);
|
||||
|
||||
ffStrbufInit(&host->chassisVersion);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &host->chassisVersion);
|
||||
|
||||
ffStrbufInit(&host->sysVendor);
|
||||
getHostValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor);
|
||||
|
||||
//KVM/Qemu virtual machine
|
||||
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
|
||||
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
|
||||
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(host->productFamily.length == 0 && host->productName.length == 0 && (
|
||||
getenv("WSLENV") != NULL ||
|
||||
getenv("WSL_DISTRO") != NULL ||
|
||||
getenv("WSL_INTEROP") != NULL
|
||||
)) ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_internal
|
||||
#define FF_INCLUDED_detection_internal
|
||||
|
||||
#include "pthread.h"
|
||||
|
||||
#define FF_DETECTION_INTERNAL_GUARD(ResultType, ...) \
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||
static ResultType result; \
|
||||
static bool init = false; \
|
||||
pthread_mutex_lock(&mutex); \
|
||||
if(init) \
|
||||
{ \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
return &result; \
|
||||
} \
|
||||
init = true; \
|
||||
__VA_ARGS__; \
|
||||
pthread_mutex_unlock(&mutex); \
|
||||
return &result; \
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "memory.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
void ffDetectMemoryImpl(FFMemoryResult* memory);
|
||||
|
||||
const FFMemoryResult* ffDetectMemory()
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFMemoryResult,
|
||||
ffDetectMemoryImpl(&result);
|
||||
|
||||
if(result.bytesTotal > 0)
|
||||
result.percentage = (uint8_t) ((result.bytesUsed / (long double) result.bytesTotal) * 100.0);
|
||||
else
|
||||
result.percentage = 0;
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_memory_memory
|
||||
#define FF_INCLUDED_detection_memory_memory
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFMemoryResult
|
||||
{
|
||||
uint64_t bytesUsed;
|
||||
uint64_t bytesTotal;
|
||||
uint8_t percentage;
|
||||
} FFMemoryResult;
|
||||
|
||||
const FFMemoryResult* ffDetectMemory();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "memory.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
void ffDetectMemoryImpl(FFMemoryResult* memory)
|
||||
{
|
||||
memory->bytesTotal = (uint64_t) ffSettingsGetAppleInt64("hw.memsize", 0);
|
||||
|
||||
memory->bytesUsed = 0;
|
||||
|
||||
uint32_t pagesize = (uint32_t) ffSettingsGetAppleInt("hw.pagesize", 0);
|
||||
if(pagesize == 0)
|
||||
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)
|
||||
return;
|
||||
|
||||
memory->bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * pagesize;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "memory.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void ffDetectMemoryImpl(FFMemoryResult* memory)
|
||||
{
|
||||
memory->bytesUsed = 0;
|
||||
memory->bytesTotal = 0;
|
||||
|
||||
FILE* meminfo = fopen("/proc/meminfo", "r");
|
||||
if(meminfo == NULL)
|
||||
return;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
uint32_t memTotal = 0,
|
||||
shmem = 0,
|
||||
memFree = 0,
|
||||
buffers = 0,
|
||||
cached = 0,
|
||||
sReclaimable = 0;
|
||||
|
||||
while (getline(&line, &len, meminfo) != EOF)
|
||||
{
|
||||
sscanf(line, "MemTotal: %u", &memTotal);
|
||||
sscanf(line, "Shmem: %u", &shmem);
|
||||
sscanf(line, "MemFree: %u", &memFree);
|
||||
sscanf(line, "Buffers: %u", &buffers);
|
||||
sscanf(line, "Cached: %u", &cached);
|
||||
sscanf(line, "SReclaimable: %u", &sReclaimable);
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(meminfo);
|
||||
|
||||
memory->bytesTotal = memTotal * (uint64_t) 1024;
|
||||
memory->bytesUsed = (memTotal + shmem - memFree - buffers - cached - sReclaimable) * (uint64_t) 1024;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "os.h"
|
||||
#include "detection/internal.h"
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance);
|
||||
|
||||
const FFOSResult* ffDetectOS(const FFinstance* instance)
|
||||
{
|
||||
FF_DETECTION_INTERNAL_GUARD(FFOSResult,
|
||||
ffDetectOSImpl(&result, instance)
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_os
|
||||
#define FF_INCLUDED_detection_os
|
||||
#ifndef FF_INCLUDED_detection_os_os
|
||||
#define FF_INCLUDED_detection_os_os
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFOSResult
|
||||
{
|
||||
FFstrbuf systemName;
|
||||
FFstrbuf name;
|
||||
FFstrbuf prettyName;
|
||||
FFstrbuf id;
|
||||
@@ -18,6 +17,7 @@ typedef struct FFOSResult
|
||||
FFstrbuf versionID;
|
||||
FFstrbuf codename;
|
||||
FFstrbuf buildID;
|
||||
FFstrbuf systemName;
|
||||
FFstrbuf architecture;
|
||||
} FFOSResult;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "os.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInit(&os->name);
|
||||
ffStrbufSetS(&os->name, "Android");
|
||||
|
||||
ffStrbufInit(&os->prettyName);
|
||||
ffStrbufSetS(&os->prettyName, "Android");
|
||||
|
||||
ffStrbufInit(&os->id);
|
||||
ffStrbufSetS(&os->id, "android");
|
||||
|
||||
ffStrbufInit(&os->version);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &os->version);
|
||||
|
||||
ffStrbufInit(&os->versionID);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &os->versionID);
|
||||
|
||||
ffStrbufInit(&os->codename);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.codename", &os->codename);
|
||||
|
||||
ffStrbufInit(&os->buildID);
|
||||
ffSettingsGetAndroidProperty("ro.build.id", &os->buildID);
|
||||
|
||||
ffStrbufInit(&os->systemName);
|
||||
ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
|
||||
|
||||
ffStrbufInit(&os->architecture);
|
||||
ffStrbufSetS(&os->architecture, instance->state.utsname.machine);
|
||||
|
||||
ffStrbufInitA(&os->idLike, 0);
|
||||
ffStrbufInitA(&os->variant, 0);
|
||||
ffStrbufInitA(&os->variantID, 0);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "os.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/settings.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
typedef enum PListKey
|
||||
{
|
||||
PLIST_KEY_NAME,
|
||||
PLIST_KEY_VERSION,
|
||||
PLIST_KEY_BUILD,
|
||||
PLIST_KEY_OTHER
|
||||
} PListKey;
|
||||
|
||||
static void parseFile(FFOSResult* os)
|
||||
{
|
||||
FILE* plist = fopen("/System/Library/CoreServices/SystemVersion.plist", "r");
|
||||
if(plist == NULL)
|
||||
return;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
PListKey key = PLIST_KEY_OTHER;
|
||||
|
||||
FFstrbuf keyBuffer;
|
||||
ffStrbufInit(&keyBuffer);
|
||||
|
||||
while(getline(&line, &len, plist) != EOF)
|
||||
{
|
||||
if(ffParsePropLine(line, "<key>", &keyBuffer))
|
||||
{
|
||||
if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductName") == 0)
|
||||
key = PLIST_KEY_NAME;
|
||||
else if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductUserVisibleVersion") == 0)
|
||||
key = PLIST_KEY_VERSION;
|
||||
else if(ffStrbufIgnCaseCompS(&keyBuffer, "ProductBuildVersion") == 0)
|
||||
key = PLIST_KEY_BUILD;
|
||||
else
|
||||
key = PLIST_KEY_OTHER;
|
||||
|
||||
ffStrbufClear(&keyBuffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key == PLIST_KEY_NAME)
|
||||
ffParsePropLine(line, "<string>", &os->name);
|
||||
else if(key == PLIST_KEY_VERSION)
|
||||
ffParsePropLine(line, "<string>", &os->version);
|
||||
else if(key == PLIST_KEY_BUILD)
|
||||
ffParsePropLine(line, "<string>", &os->buildID);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&keyBuffer);
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(plist);
|
||||
}
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInit(&os->name);
|
||||
ffStrbufInit(&os->version);
|
||||
ffStrbufInit(&os->buildID);
|
||||
ffStrbufInit(&os->id);
|
||||
ffStrbufInit(&os->prettyName);
|
||||
ffStrbufInit(&os->versionID);
|
||||
ffStrbufInit(&os->systemName);
|
||||
ffStrbufInit(&os->architecture);
|
||||
|
||||
ffStrbufInitA(&os->codename, 0);
|
||||
ffStrbufInitA(&os->idLike, 0);
|
||||
ffStrbufInitA(&os->variant, 0);
|
||||
ffStrbufInitA(&os->variantID, 0);
|
||||
|
||||
parseFile(os);
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS"))
|
||||
ffStrbufAppendS(&os->id, "macos");
|
||||
|
||||
if(os->version.length == 0)
|
||||
ffSettingsGetAppleProperty("kern.osproductversion", &os->version);
|
||||
|
||||
//TODO map version to pretty name
|
||||
ffStrbufAppend(&os->prettyName, &os->name);
|
||||
ffStrbufAppend(&os->versionID, &os->version);
|
||||
ffSettingsGetAppleProperty("kern.ostype", &os->systemName);
|
||||
ffSettingsGetAppleProperty("hw.machine", &os->architecture);
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/os.h"
|
||||
#include "os.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#if __ANDROID__
|
||||
#include "common/settings.h"
|
||||
#else
|
||||
static inline bool allRelevantValuesSet(const FFOSResult* result)
|
||||
{
|
||||
return result->id.length > 0
|
||||
&& result->name.length > 0
|
||||
&& result->prettyName.length > 0
|
||||
;
|
||||
}
|
||||
|
||||
static bool parseFile(const char* fileName, FFOSResult* result)
|
||||
{
|
||||
if(result->id.length > 0 && result->name.length > 0 && result->prettyName.length > 0)
|
||||
return true;
|
||||
|
||||
return ffParsePropFileValues(fileName, 13, (FFpropquery[]) {
|
||||
{"NAME =", &result->name},
|
||||
{"DISTRIB_DESCRIPTION =", &result->prettyName},
|
||||
@@ -94,73 +93,59 @@ static void getUbuntuFlavour(FFOSResult* result)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const FFOSResult* ffDetectOS(const FFinstance* instance)
|
||||
static void detectOS(FFOSResult* os, const FFinstance* instance)
|
||||
{
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static FFOSResult result;
|
||||
static bool init = false;
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.systemName);
|
||||
ffStrbufInit(&result.name);
|
||||
ffStrbufInit(&result.prettyName);
|
||||
ffStrbufInit(&result.id);
|
||||
ffStrbufInit(&result.idLike);
|
||||
ffStrbufInit(&result.variant);
|
||||
ffStrbufInit(&result.variantID);
|
||||
ffStrbufInit(&result.version);
|
||||
ffStrbufInit(&result.versionID);
|
||||
ffStrbufInit(&result.codename);
|
||||
ffStrbufInit(&result.buildID);
|
||||
ffStrbufInit(&result.architecture);
|
||||
|
||||
ffStrbufSetS(&result.systemName, instance->state.utsname.sysname);
|
||||
ffStrbufSetS(&result.architecture, instance->state.utsname.machine);
|
||||
|
||||
#if !__ANDROID__
|
||||
if(instance->config.osFile.length > 0)
|
||||
{
|
||||
parseFile(instance->config.osFile.chars, &result);
|
||||
parseFile(instance->config.osFile.chars, os);
|
||||
return;
|
||||
}
|
||||
else if(instance->config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock/etc/bedrock-release", &result))
|
||||
|
||||
if(instance->config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock/etc/bedrock-release", os))
|
||||
{
|
||||
if(result.id.length == 0)
|
||||
ffStrbufAppendS(&result.id, "bedrock");
|
||||
if(os->id.length == 0)
|
||||
ffStrbufAppendS(&os->id, "bedrock");
|
||||
|
||||
if(result.name.length == 0)
|
||||
ffStrbufAppendS(&result.name, "Bedrock");
|
||||
if(os->name.length == 0)
|
||||
ffStrbufAppendS(&os->name, "Bedrock");
|
||||
|
||||
if(result.prettyName.length == 0)
|
||||
ffStrbufAppendS(&result.prettyName, "Bedrock Linux");
|
||||
}
|
||||
else
|
||||
{
|
||||
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/os-release", &result);
|
||||
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", &result);
|
||||
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/lsb-release", &result);
|
||||
if(os->prettyName.length == 0)
|
||||
ffStrbufAppendS(&os->prettyName, "Bedrock Linux");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&result.id, "ubuntu") == 0)
|
||||
getUbuntuFlavour(&result);
|
||||
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/os-release", os);
|
||||
if(allRelevantValuesSet(os))
|
||||
return;
|
||||
|
||||
#else
|
||||
ffStrbufSetS(&result.name, "Android");
|
||||
ffStrbufSetS(&result.id, "android");
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &result.versionID);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &result.version);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.codename", &result.codename);
|
||||
ffSettingsGetAndroidProperty("ro.build.id", &result.buildID);
|
||||
#endif
|
||||
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", os);
|
||||
if(allRelevantValuesSet(os))
|
||||
return;
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
return &result;
|
||||
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/lsb-release", os);
|
||||
}
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
{
|
||||
ffStrbufInit(&os->name);
|
||||
ffStrbufInit(&os->prettyName);
|
||||
ffStrbufInit(&os->id);
|
||||
ffStrbufInit(&os->idLike);
|
||||
ffStrbufInit(&os->variant);
|
||||
ffStrbufInit(&os->variantID);
|
||||
ffStrbufInit(&os->version);
|
||||
ffStrbufInit(&os->versionID);
|
||||
ffStrbufInit(&os->codename);
|
||||
ffStrbufInit(&os->buildID);
|
||||
ffStrbufInit(&os->systemName);
|
||||
ffStrbufInit(&os->architecture);
|
||||
|
||||
ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
|
||||
ffStrbufSetS(&os->architecture, instance->state.utsname.machine);
|
||||
|
||||
detectOS(os, instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&os->id, "ubuntu") == 0)
|
||||
getUbuntuFlavour(os);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/qt.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -63,10 +63,8 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value)
|
||||
return value->name.length > 0 || value->deviceClass.length > 0;
|
||||
}
|
||||
|
||||
const FFTempsResult* ffDetectTemps(const FFinstance* instance)
|
||||
const FFTempsResult* ffDetectTemps()
|
||||
{
|
||||
FF_UNUSED(instance)
|
||||
|
||||
static FFTempsResult result;
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
|
||||
@@ -17,6 +17,6 @@ typedef struct FFTempsResult
|
||||
FFlist values; //List of FFTempValue
|
||||
} FFTempsResult;
|
||||
|
||||
const FFTempsResult* ffDetectTemps(const FFinstance* instance);
|
||||
const FFTempsResult* ffDetectTemps();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -137,6 +137,10 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
getenv("TMUX_TMPDIR") != NULL
|
||||
)) term = "Termux";
|
||||
|
||||
//MacOS
|
||||
if(!ffStrSet(term))
|
||||
term = getenv("TERM_PROGRAM");
|
||||
|
||||
//Normal Terminal
|
||||
if(!ffStrSet(term))
|
||||
term = getenv("TERM");
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#include <pthread.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#ifndef HOST_NAME_MAX
|
||||
#define HOST_NAME_MAX 64
|
||||
#endif
|
||||
|
||||
const FFTitleResult* ffDetectTitle(const FFinstance* instance)
|
||||
{
|
||||
static FFTitleResult result;
|
||||
@@ -28,6 +32,7 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance)
|
||||
|
||||
ffStrbufInitA(&result.fqdn, HOST_NAME_MAX);
|
||||
|
||||
#ifndef __APPLE__
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
@@ -45,6 +50,7 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance)
|
||||
|
||||
freeaddrinfo(info);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(result.fqdn.length == 0)
|
||||
ffStrbufAppend(&result.fqdn, &result.hostname);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/vulkan.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
@@ -175,12 +176,15 @@ static void detectVulkan(const FFinstance* instance, FFVulkanResult* result)
|
||||
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(&result->devices);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
FFGPUResult* gpu = ffListAdd(&result->gpus);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
gpu->temperature = 0.0 / 0.0; //NaN, no way to detect temperature using vulkan
|
||||
ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName);
|
||||
|
||||
//No way to detect those using vulkan
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
//If the highest device version is lower than the instance version, use it as our vulkan version
|
||||
@@ -218,7 +222,7 @@ const FFVulkanResult* ffDetectVulkan(const FFinstance* instance)
|
||||
ffStrbufInit(&result.driver);
|
||||
ffStrbufInit(&result.apiVersion);
|
||||
ffStrbufInit(&result.conformanceVersion);
|
||||
ffListInit(&result.devices, sizeof(FFGPUResult));
|
||||
ffListInit(&result.gpus, sizeof(FFGPUResult));
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
detectVulkan(instance, &result);
|
||||
|
||||
@@ -5,20 +5,12 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFGPUResult
|
||||
{
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf name;
|
||||
FFstrbuf driver;
|
||||
double temperature;
|
||||
} FFGPUResult;
|
||||
|
||||
typedef struct FFVulkanResult
|
||||
{
|
||||
FFstrbuf driver;
|
||||
FFstrbuf apiVersion;
|
||||
FFstrbuf conformanceVersion;
|
||||
FFlist devices; //List of FFGPUResult
|
||||
FFlist gpus; //List of FFGPUResult, see detection/gpu/gpu.h
|
||||
} FFVulkanResult;
|
||||
|
||||
const FFVulkanResult* ffDetectVulkan(const FFinstance* instance);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "util/FFvaluestore.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
@@ -113,7 +114,7 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "packages-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (flatpak), {13} (snap)", 13,
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (flatpak), {13} (snap), {14} (brew)", 14,
|
||||
"Number of all packages",
|
||||
"Number of pacman packages",
|
||||
"Pacman branch on manjaro",
|
||||
@@ -126,7 +127,8 @@ static inline void printCommandHelp(const char* command)
|
||||
"Number of nix-default packages",
|
||||
"Number of apk packages",
|
||||
"Number of flatpak packages",
|
||||
"Number of snap packages"
|
||||
"Number of snap packages",
|
||||
"Number of brew packages"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "shell-format") == 0)
|
||||
@@ -246,22 +248,15 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "cpu-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("cpu", "{2} ({7}) @ {15}GHz", 15,
|
||||
"CPU name",
|
||||
"Prettified CPU name",
|
||||
"CPU Vendor name (Vendor ID)",
|
||||
"CPU logical core count online",
|
||||
"CPU logical core count configured",
|
||||
"CPU physical core count",
|
||||
"Always set core count",
|
||||
"CPU package temperature",
|
||||
"frequency bios limit",
|
||||
"frequency scaling max",
|
||||
"frequency scaling min",
|
||||
"frequency info max",
|
||||
"frequency info min",
|
||||
"frequeny from /proc/cpuinfo",
|
||||
"most accurate frequeny"
|
||||
constructAndPrintCommandHelpFormat("cpu", "{1} ({5}) @ {7}GHz", 8,
|
||||
"Name",
|
||||
"Vendor",
|
||||
"Physical core count",
|
||||
"Logical core count",
|
||||
"Online core count",
|
||||
"Min frequency",
|
||||
"Max frequency",
|
||||
"Temperature"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "cpu-usage-format") == 0)
|
||||
@@ -272,30 +267,28 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "gpu-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("gpu", "{2} {4}", 6,
|
||||
constructAndPrintCommandHelpFormat("gpu", "{} {}", 4,
|
||||
"GPU vendor",
|
||||
"GPU vendor pretty",
|
||||
"GPU name",
|
||||
"GPU name pretty",
|
||||
"GPU driver",
|
||||
"GPU temperature"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "memory-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("memory", "{}MiB / {}MiB ({}%)", 3,
|
||||
"Used memory",
|
||||
"Total memory",
|
||||
"Used memory percentage"
|
||||
constructAndPrintCommandHelpFormat("memory", "{} / {} ({}%)", 3,
|
||||
"Used size",
|
||||
"Total size",
|
||||
"Percentage used"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "disk-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("disk", "{}GiB / {}GiB ({4}%)", 4,
|
||||
"Used disk space",
|
||||
"Total disk space",
|
||||
"Number of files",
|
||||
"Used disk space percentage"
|
||||
"Used size",
|
||||
"Total size",
|
||||
"Percentage used",
|
||||
"Num files"
|
||||
);
|
||||
}
|
||||
else if(strcasecmp(command, "battery-format") == 0)
|
||||
@@ -452,8 +445,12 @@ static inline void listAvailablePresets(FFinstance* instance)
|
||||
|
||||
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value);
|
||||
|
||||
static void parseConfigFile(FFinstance* instance, FFdata* data, FILE* file)
|
||||
static bool parseConfigFile(FFinstance* instance, FFdata* data, const char* path)
|
||||
{
|
||||
FILE* file = fopen(path, "r");
|
||||
if(file == NULL)
|
||||
return false;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
@@ -497,6 +494,7 @@ static void parseConfigFile(FFinstance* instance, FFdata* data, FILE* file)
|
||||
if((*valueStart == '"' || *valueStart == '\'') && *valueStart == *lineEnd && lineEnd > valueStart)
|
||||
{
|
||||
++valueStart;
|
||||
*lineEnd = '\0';
|
||||
--lineEnd;
|
||||
}
|
||||
|
||||
@@ -505,6 +503,9 @@ static void parseConfigFile(FFinstance* instance, FFdata* data, FILE* file)
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char* key, const char* value)
|
||||
@@ -515,13 +516,12 @@ static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char
|
||||
exit(413);
|
||||
}
|
||||
|
||||
FILE* file = fopen(value, "r");
|
||||
if(file != NULL)
|
||||
{
|
||||
parseConfigFile(instance, data, file);
|
||||
fclose(file);
|
||||
//Try to load as an absolute path
|
||||
|
||||
if(parseConfigFile(instance, data, value))
|
||||
return;
|
||||
}
|
||||
|
||||
//Try to load as an user preset
|
||||
|
||||
FFstrbuf filename;
|
||||
ffStrbufInitA(&filename, 64);
|
||||
@@ -530,26 +530,28 @@ static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char
|
||||
ffStrbufAppendS(&filename, "/.local/share/fastfetch/presets/");
|
||||
ffStrbufAppendS(&filename, value);
|
||||
|
||||
file = fopen(filename.chars, "r");
|
||||
if(file != NULL)
|
||||
if(parseConfigFile(instance, data, filename.chars))
|
||||
{
|
||||
parseConfigFile(instance, data, file);
|
||||
fclose(file);
|
||||
ffStrbufDestroy(&filename);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Try to load as a system preset
|
||||
|
||||
ffStrbufSetS(&filename, FASTFETCH_TARGET_DIR_USR"/share/fastfetch/presets/");
|
||||
ffStrbufAppendS(&filename, value);
|
||||
|
||||
file = fopen(filename.chars, "r");
|
||||
if(file != NULL)
|
||||
if(parseConfigFile(instance, data, filename.chars))
|
||||
{
|
||||
parseConfigFile(instance, data, file);
|
||||
fclose(file);
|
||||
ffStrbufDestroy(&filename);
|
||||
return;
|
||||
}
|
||||
|
||||
//File not found
|
||||
|
||||
fprintf(stderr, "Error: couldn't find config: %s\n", value);
|
||||
ffStrbufDestroy(&filename);
|
||||
exit(414);
|
||||
}
|
||||
|
||||
@@ -701,6 +703,39 @@ static void optionParseCustomValue(FFdata* data, const char* key, const char* va
|
||||
customValue->printKey = printKey;
|
||||
}
|
||||
|
||||
static void optionParseEnum(const char* argumentKey, const char* requestedKey, void* result, ...)
|
||||
{
|
||||
if(requestedKey == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <value>\n", argumentKey);
|
||||
exit(476);
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, result);
|
||||
|
||||
while(true)
|
||||
{
|
||||
const char* key = va_arg(args, const char*);
|
||||
if(key == NULL)
|
||||
break;
|
||||
|
||||
int value = va_arg(args, int); //C standard guarantees that enumeration constants are presented as ints
|
||||
|
||||
if(strcasecmp(requestedKey, key) == 0)
|
||||
{
|
||||
*(int*)result = value;
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "Error: unknown %s value: %s\n", argumentKey, requestedKey);
|
||||
exit(478);
|
||||
}
|
||||
|
||||
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value)
|
||||
{
|
||||
///////////////////////
|
||||
@@ -813,31 +848,16 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
}
|
||||
else if(strcasecmp(key, "--logo-type") == 0)
|
||||
{
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <type>\n", key);
|
||||
exit(476);
|
||||
}
|
||||
|
||||
if(strcasecmp(value, "auto") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_AUTO;
|
||||
else if(strcasecmp(value, "builtin") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_BUILTIN;
|
||||
else if(strcasecmp(value, "file") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_FILE;
|
||||
else if(strcasecmp(value, "raw") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_RAW;
|
||||
else if(strcasecmp(value, "sixel") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_SIXEL;
|
||||
else if(strcasecmp(value, "kitty") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_KITTY;
|
||||
else if(strcasecmp(value, "chafa") == 0)
|
||||
instance->config.logo.type = FF_LOGO_TYPE_CHAFA;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: unknown logo type: %s\n", value);
|
||||
exit(478);
|
||||
}
|
||||
optionParseEnum(key, value, &instance->config.logo.type,
|
||||
"auto", FF_LOGO_TYPE_AUTO,
|
||||
"builtin", FF_LOGO_TYPE_BUILTIN,
|
||||
"file", FF_LOGO_TYPE_FILE,
|
||||
"raw", FF_LOGO_TYPE_RAW,
|
||||
"sixel", FF_LOGO_TYPE_SIXEL,
|
||||
"kitty", FF_LOGO_TYPE_KITTY,
|
||||
"chafa", FF_LOGO_TYPE_CHAFA,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
else if(strncasecmp(key, "--logo-color-", 13) == 0 && key[13] != '\0' && key[14] == '\0') // matches "--logo-color-*"
|
||||
{
|
||||
@@ -881,7 +901,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
}
|
||||
else if(strcasecmp(key, "--file") == 0)
|
||||
{
|
||||
optionCheckString(key, value, &instance->config.logo.source);
|
||||
optionParseString(key, value, &instance->config.logo.source);
|
||||
instance->config.logo.type = FF_LOGO_TYPE_FILE;
|
||||
}
|
||||
else if(strcasecmp(key, "--raw") == 0)
|
||||
@@ -915,6 +935,15 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseCustomValue(data, key, value, true);
|
||||
else if(strcasecmp(key, "--set-keyless") == 0)
|
||||
optionParseCustomValue(data, key, value, false);
|
||||
else if(strcasecmp(key, "--binary-prefix") == 0)
|
||||
{
|
||||
optionParseEnum(key, value, &instance->config.binaryPrefixType,
|
||||
"iec", FF_BINARY_PREFIX_TYPE_IEC,
|
||||
"si", FF_BINARY_PREFIX_TYPE_SI,
|
||||
"jedec", FF_BINARY_PREFIX_TYPE_JEDEC,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//Format + Key + Error options//
|
||||
@@ -1196,25 +1225,13 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
instance->config.publicIpTimeout = optionParseUInt32(key, value);
|
||||
else if(strcasecmp(key, "--gl") == 0)
|
||||
{
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <type>\n", key);
|
||||
exit(491);
|
||||
}
|
||||
|
||||
if(strcasecmp(value, "auto") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_AUTO;
|
||||
else if(strcasecmp(value, "egl") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_EGL;
|
||||
else if(strcasecmp(value, "glx") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_GLX;
|
||||
else if(strcasecmp(value, "osmesa") == 0)
|
||||
instance->config.glType = FF_GL_TYPE_OSMESA;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: unknown gl type: %s\n", value);
|
||||
exit(492);
|
||||
}
|
||||
optionParseEnum(key, value, &instance->config.glType,
|
||||
"auto", FF_GL_TYPE_AUTO,
|
||||
"egl", FF_GL_TYPE_EGL,
|
||||
"glx", FF_GL_TYPE_GLX,
|
||||
"osmesa", FF_GL_TYPE_OSMESA,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////
|
||||
@@ -1230,12 +1247,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
|
||||
static void parseConfigFileSystem(FFinstance* instance, FFdata* data)
|
||||
{
|
||||
FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT"/etc/fastfetch/config.conf", "r");
|
||||
if(file == NULL)
|
||||
return;
|
||||
|
||||
parseConfigFile(instance, data, file);
|
||||
fclose(file);
|
||||
parseConfigFile(instance, data, FASTFETCH_TARGET_DIR_ROOT"/etc/fastfetch/config.conf");
|
||||
}
|
||||
|
||||
static void parseConfigFileUser(FFinstance* instance, FFdata* data)
|
||||
@@ -1246,28 +1258,10 @@ static void parseConfigFileUser(FFinstance* instance, FFdata* data)
|
||||
FFstrbuf* filename = ffListGet(&instance->state.configDirs, 0);
|
||||
uint32_t filenameLength = filename->length;
|
||||
|
||||
mkdir(filename->chars, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a config folder, but who knows
|
||||
ffStrbufAppendS(filename, "/fastfetch/config.conf");
|
||||
|
||||
ffStrbufAppendS(filename, "/fastfetch/");
|
||||
mkdir(filename->chars, S_IRWXU | S_IRGRP | S_IROTH);
|
||||
|
||||
ffStrbufAppendS(filename, "config.conf");
|
||||
|
||||
FILE* file = fopen(filename->chars, "r");
|
||||
if(file != NULL)
|
||||
{
|
||||
parseConfigFile(instance, data, file);
|
||||
fclose(file);
|
||||
ffStrbufSubstrBefore(filename, filenameLength);
|
||||
return;
|
||||
}
|
||||
|
||||
file = fopen(filename->chars, "w");
|
||||
if(file != NULL)
|
||||
{
|
||||
fputs(FASTFETCH_DATATEXT_CONFIG_USER, file);
|
||||
fclose(file);
|
||||
}
|
||||
if(!parseConfigFile(instance, data, filename->chars))
|
||||
ffWriteFileData(filename->chars, sizeof(FASTFETCH_DATATEXT_CONFIG_USER), FASTFETCH_DATATEXT_CONFIG_USER);
|
||||
|
||||
ffStrbufSubstrBefore(filename, filenameLength);
|
||||
}
|
||||
@@ -1362,7 +1356,7 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
|
||||
ffPrintPublicIp(instance);
|
||||
else if(strcasecmp(line, "player") == 0)
|
||||
ffPrintPlayer(instance);
|
||||
else if(strcasecmp(line, "song") == 0)
|
||||
else if(strcasecmp(line, "media") == 0 || strcasecmp(line, "song") == 0)
|
||||
ffPrintSong(instance);
|
||||
else if(strcasecmp(line, "datetime") == 0)
|
||||
ffPrintDateTime(instance);
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
|
||||
#include <pwd.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#if FF_HAVE_SYSINFO_H
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/FFlist.h"
|
||||
@@ -35,6 +38,13 @@ typedef enum FFLogoType
|
||||
FF_LOGO_TYPE_CHAFA //Image file, printed as ascii art using libchafa
|
||||
} FFLogoType;
|
||||
|
||||
typedef enum FFBinaryPrefixType
|
||||
{
|
||||
FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard)
|
||||
FF_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ...
|
||||
FF_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 K = 1 MB, ...
|
||||
} FFBinaryPrefixType;
|
||||
|
||||
typedef enum FFGLType
|
||||
{
|
||||
FF_GL_TYPE_AUTO,
|
||||
@@ -74,6 +84,7 @@ typedef struct FFconfig
|
||||
bool disableLinewrap;
|
||||
bool hideCursor;
|
||||
bool escapeBedrock;
|
||||
FFBinaryPrefixType binaryPrefixType;
|
||||
FFGLType glType;
|
||||
bool pipe; //disables logo and all escape sequences
|
||||
bool multithreading;
|
||||
@@ -161,7 +172,10 @@ typedef struct FFstate
|
||||
|
||||
struct passwd* passwd;
|
||||
struct utsname utsname;
|
||||
struct sysinfo sysinfo;
|
||||
|
||||
#if FF_HAVE_SYSINFO_H
|
||||
struct sysinfo sysinfo;
|
||||
#endif
|
||||
|
||||
FFlist configDirs;
|
||||
FFstrbuf cacheDir;
|
||||
|
||||
@@ -37,7 +37,7 @@ const FFlogo* ffLogoBuiltinGetUnknown()
|
||||
static const FFlogo* getLogoNone()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("none", "empty", "")
|
||||
FF_LOGO_NAMES("none", "empty")
|
||||
FF_LOGO_LINES("")
|
||||
FF_LOGO_COLORS("")
|
||||
FF_LOGO_RETURN
|
||||
@@ -378,6 +378,27 @@ static const FFlogo* getLogoCachyOS()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoCachyOSSmall()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("cachy_small", "cachyos_small", "cachy-linux-small", "cachyos-linux-small")
|
||||
FF_LOGO_LINES(
|
||||
" /''''''''''''/\n"
|
||||
" /''''''''''''/\n"
|
||||
" /''''''/\n"
|
||||
"/''''''/\n"
|
||||
"\\......\\\n"
|
||||
" \\......\\\n"
|
||||
" \\.............../\n"
|
||||
" \\............./\n"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"36" //cyan
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
|
||||
static const FFlogo* getLogoCelOS()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -917,6 +938,39 @@ static const FFlogo* getLogoLinux()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoMacOS()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("macos", "mac", "apple", "darwin", "osx")
|
||||
FF_LOGO_LINES(
|
||||
" $1c.'\n"
|
||||
" ,xNMM.\n"
|
||||
" .OMMMMo\n"
|
||||
" lMM\"\n"
|
||||
" .;loddo:. .olloddol;.\n"
|
||||
" cKMMMMMMMMMMNWMMMMMMMMMM0:\n"
|
||||
" $2.KMMMMMMMMMMMMMMMMMMMMMMMWd.\n"
|
||||
" XMMMMMMMMMMMMMMMMMMMMMMMX.\n"
|
||||
"$3;MMMMMMMMMMMMMMMMMMMMMMMM:\n"
|
||||
":MMMMMMMMMMMMMMMMMMMMMMMM:\n"
|
||||
".MMMMMMMMMMMMMMMMMMMMMMMMX.\n"
|
||||
" kMMMMMMMMMMMMMMMMMMMMMMMMWd.\n"
|
||||
" $4'XMMMMMMMMMMMMMMMMMMMMMMMMMMk\n"
|
||||
" 'XMMMMMMMMMMMMMMMMMMMMMMMMK.\n"
|
||||
" $5kMMMMMMMMMMMMMMMMMMMMMMd\n"
|
||||
" ;KMMMMMMMWXXWMMMMMMMk.\n"
|
||||
" \"cooc*\" \"*coo'\""
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"32", //green
|
||||
"33", //yellow
|
||||
"31", //red
|
||||
"35", //magenta
|
||||
"34" //blue
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoManjaro()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1043,6 +1097,45 @@ static const FFlogo* getLogoMintOld()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoMsys2()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("msys2")
|
||||
FF_LOGO_LINES(
|
||||
"$2 ...\n"
|
||||
" 5GB###GJ. !YPGGGG\n"
|
||||
" 7@@@@@@@B. :G@@@@@@@\n"
|
||||
" 7@@@@@@@@Y ~&@@@@@@@@$3YJYY5YY?L\n"
|
||||
" $2!@@@@@@@@@@^ ^&@@@@@@@$3#PP555555PBY\n"
|
||||
" $2~&@@@@@@@@@@? ^&@@@@@@$3#5YY5YYYYYYYY#7\n"
|
||||
" $2^&@@@@@@@@@@@B :#@@@@@@@$3G5BBYGPYYYYYY#J\n"
|
||||
" $2^#@@@&J#@@@@@@@~ .B@@@@@@@@@@@P $3?#YYYYYPB.\n"
|
||||
" $2:#@@@@7 G@@@@@@@J P@@@#!&@@@@@@G$3.GGYYYYGB^\n"
|
||||
" $2:#@@@@J Y@@@@@@@B 5@@@&:.&@@@@@@&$3BBYYY5B5.\n"
|
||||
" $2:#@@@@Y !@@@@@@@@!Y@@@&~ .#@@@@@@$3GYYYYYBP JP~\n"
|
||||
" $2:#@@@@P :&@@@@@@@@@@@&~ B@@@@@$3#5YYYYYPGPGPGG\n"
|
||||
" $2^#@@@@G. P@@@@@@@@@@@! P@@@@$3GYYYYYYYYYYYYBY\n"
|
||||
" $2^#@@@@B: ^@@@@@@@@@@7 !@@@$3#GGGGGGGPPPP5GB:\n"
|
||||
" $2!&@@@@B: Y@@@@@@@@? P@@@@@@@@@&? $3^PY:\n"
|
||||
" $27&@@@@5. P@@@@@@? P@@@@@@@@@B\n"
|
||||
" Y@@@&P! 5@@@@7 7G@@@@@&P~\n"
|
||||
".JJ?~: ^JY~ ^!5J!^:\n"
|
||||
" $1:@P5#B. #G 7&^ :@P5#B.\n"
|
||||
" !&P^. ?@~ #P !&P^. \n"
|
||||
" .?BG! #G5@~ .?BG! \n"
|
||||
" :.B@. 7@@5 :.B@.\n"
|
||||
" !PYY5Y :&@^ !PYY5Y \n"
|
||||
" ~@Y\n"
|
||||
" !5:"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"35", //magenta
|
||||
"37", //white
|
||||
"31" //red
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoNixOS()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1620,6 +1713,7 @@ GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
getLogoArtixSmall,
|
||||
getLogoBedrock,
|
||||
getLogoCachyOS,
|
||||
getLogoCachyOSSmall,
|
||||
getLogoCelOS,
|
||||
getLogoCentOS,
|
||||
getLogoCentOSSmall,
|
||||
@@ -1640,11 +1734,13 @@ GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
getLogoKubuntu,
|
||||
getLogoLangitKetujuh,
|
||||
getLogoLinux,
|
||||
getLogoMacOS,
|
||||
getLogoManjaro,
|
||||
getLogoManjaroSmall,
|
||||
getLogoMint,
|
||||
getLogoMintSmall,
|
||||
getLogoMintOld,
|
||||
getLogoMsys2,
|
||||
getLogoNixOS,
|
||||
getLogoNixOsOld,
|
||||
getLogoNixOsSmall,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "logo.h"
|
||||
#include "common/io.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/os.h"
|
||||
#include "detection/os/os.h"
|
||||
#include "detection/terminalshell.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -1,213 +1,51 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
#include "detection/temps.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "detection/cpu/cpu.h"
|
||||
|
||||
#define FF_CPU_MODULE_NAME "CPU"
|
||||
#define FF_CPU_NUM_FORMAT_ARGS 15
|
||||
|
||||
static double getGhz(const char* policyFile, const char* cpuFile)
|
||||
{
|
||||
FFstrbuf content;
|
||||
ffStrbufInit(&content);
|
||||
|
||||
ffReadFileBuffer(policyFile, &content);
|
||||
if(content.length == 0)
|
||||
ffReadFileBuffer(cpuFile, &content);
|
||||
|
||||
double herz = ffStrbufToDouble(&content);
|
||||
|
||||
ffStrbufDestroy(&content);
|
||||
|
||||
//ffStrbufToDouble failed
|
||||
if(herz != herz)
|
||||
return 0;
|
||||
|
||||
herz /= 1000.0; //to MHz
|
||||
return herz / 1000.0; //to GHz
|
||||
}
|
||||
|
||||
static double detectCPUTemp(const FFinstance* instance)
|
||||
{
|
||||
const FFTempsResult *temps = ffDetectTemps(instance);
|
||||
|
||||
for(uint32_t i = 0; i < temps->values.length; i++)
|
||||
{
|
||||
FFTempValue* value = ffListGet(&temps->values, i);
|
||||
|
||||
if(
|
||||
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
|
||||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
|
||||
ffStrbufCompS(&value->name, "coretemp") == 0
|
||||
) return value->value;
|
||||
}
|
||||
|
||||
return 0.0 / 0.0; //NaN
|
||||
}
|
||||
#define FF_CPU_NUM_FORMAT_ARGS 8
|
||||
|
||||
void ffPrintCPU(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpu, FF_CPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if(cpuinfo == NULL)
|
||||
const FFCPUResult* cpu = ffDetectCPU();
|
||||
|
||||
if(cpu->vendor.length == 0 && cpu->name.length == 0 && cpu->coresOnline == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpu, "fopen(\"""/proc/cpuinfo\", \"r\") == NULL");
|
||||
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpu, "No CPU detected");
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf name;
|
||||
ffStrbufInitA(&name, 64);
|
||||
FFstrbuf output;
|
||||
ffStrbufInitA(&output, 128);
|
||||
|
||||
FFstrbuf vendor;
|
||||
ffStrbufInitA(&vendor, 64);
|
||||
|
||||
FFstrbuf physicalCoresString;
|
||||
ffStrbufInit(&physicalCoresString);
|
||||
|
||||
FFstrbuf procGhzString;
|
||||
ffStrbufInit(&procGhzString);
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while(getline(&line, &len, cpuinfo) != -1)
|
||||
if(cpu->name.length > 0)
|
||||
ffStrbufAppend(&output, &cpu->name);
|
||||
else if(cpu->vendor.length > 0)
|
||||
{
|
||||
//Stop after the first CPU
|
||||
if(name.length > 0 && (*line == '\0' || *line == '\n'))
|
||||
break;
|
||||
|
||||
(void)(
|
||||
ffParsePropLine(line, "model name :", &name) ||
|
||||
ffParsePropLine(line, "vendor_id :", &vendor) ||
|
||||
ffParsePropLine(line, "cpu cores :", &physicalCoresString) ||
|
||||
ffParsePropLine(line, "cpu MHz :", &procGhzString) ||
|
||||
(name.length == 0 && ffParsePropLine(line, "Hardware :", &name)) //For Android devices
|
||||
);
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(cpuinfo);
|
||||
|
||||
double procGhz = ffStrbufToDouble(&procGhzString);
|
||||
if(procGhz != procGhz)
|
||||
procGhz = 0; //NaN
|
||||
else
|
||||
procGhz /= 1000.0; //To GHz
|
||||
|
||||
ffStrbufDestroy(&procGhzString);
|
||||
|
||||
double biosLimit = getGhz("/sys/devices/system/cpu/cpufreq/policy0/bios_limit", "/sys/devices/system/cpu/cpu0/cpufreq/bios_limit");
|
||||
double scalingMaxFreq = getGhz("/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
|
||||
double scalingMinFreq = getGhz("/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq");
|
||||
double infoMaxFreq = getGhz("/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq", "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
|
||||
double infoMinFreq = getGhz("/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_min_freq", "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq");
|
||||
|
||||
int numProcsOnline = get_nprocs();
|
||||
int numProcsAvailable = get_nprocs_conf();
|
||||
|
||||
int physicalCores = 1;
|
||||
sscanf(physicalCoresString.chars, "%i", &physicalCores);
|
||||
ffStrbufDestroy(&physicalCoresString);
|
||||
|
||||
//The current get_nprocs* returns 1 on failure. It also makes no sense to have a (1) as count
|
||||
int numProcs = numProcsOnline;
|
||||
if(numProcs <= 1)
|
||||
numProcs = numProcsAvailable;
|
||||
if(numProcs <= 1)
|
||||
numProcs = physicalCores;
|
||||
|
||||
double ghz = biosLimit;
|
||||
if(ghz == 0)
|
||||
ghz = scalingMaxFreq;
|
||||
if(ghz == 0)
|
||||
ghz = infoMaxFreq;
|
||||
if(ghz == 0)
|
||||
ghz = procGhz;
|
||||
if(ghz == 0)
|
||||
ghz = scalingMinFreq;
|
||||
if(ghz == 0)
|
||||
ghz = infoMinFreq;
|
||||
|
||||
if(
|
||||
name.length == 0 &&
|
||||
vendor.length == 0 &&
|
||||
numProcs <= 1 &&
|
||||
ghz <= 0
|
||||
) {
|
||||
ffStrbufDestroy(&name);
|
||||
ffStrbufDestroy(&vendor);
|
||||
ffPrintError(instance, FF_CPU_MODULE_NAME, 0, &instance->config.cpu, "No CPU info found in /proc/cpuinfo");
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf namePretty;
|
||||
ffStrbufInitA(&namePretty, 64);
|
||||
ffStrbufAppend(&namePretty, &name);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"(R)", "(r)", "(TM)", "(tm)",
|
||||
" CPU", " FPU", " APU", " Processor",
|
||||
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
|
||||
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core"
|
||||
};
|
||||
|
||||
ffStrbufRemoveStringsA(&namePretty, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||
ffStrbufSubstrBeforeFirstC(&namePretty, '@'); //Cut the speed output in the name as we append our own
|
||||
ffStrbufTrimRight(&namePretty, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||
|
||||
double cpuTemp;
|
||||
if(instance->config.cpu.outputFormat.length > 0)
|
||||
cpuTemp = detectCPUTemp(instance);
|
||||
|
||||
FFstrbuf cpu;
|
||||
ffStrbufInitA(&cpu, 128);
|
||||
|
||||
if(namePretty.length > 0)
|
||||
ffStrbufAppend(&cpu, &namePretty);
|
||||
else if(name.length > 0)
|
||||
ffStrbufAppend(&cpu, &name);
|
||||
else if(vendor.length > 0)
|
||||
{
|
||||
ffStrbufAppend(&cpu, &vendor);
|
||||
ffStrbufAppendS(&cpu, " CPU");
|
||||
ffStrbufAppend(&output, &cpu->vendor);
|
||||
ffStrbufAppendS(&output, " CPU");
|
||||
}
|
||||
else
|
||||
ffStrbufAppendS(&cpu, "CPU");
|
||||
ffStrbufAppendS(&output, "CPU");
|
||||
|
||||
if(numProcs > 1)
|
||||
ffStrbufAppendF(&cpu, " (%i)", numProcs);
|
||||
if(cpu->coresOnline > 1)
|
||||
ffStrbufAppendF(&output, " (%u)", cpu->coresOnline);
|
||||
|
||||
if(ghz > 0)
|
||||
ffStrbufAppendF(&cpu, " @ %.9gGHz", ghz);
|
||||
if(cpu->frequencyMax > 0.0)
|
||||
ffStrbufAppendF(&output, " @ %.9gGHz", cpu->frequencyMax);
|
||||
|
||||
ffPrintAndWriteToCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpu, &cpu, FF_CPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &namePretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &vendor},
|
||||
{FF_FORMAT_ARG_TYPE_INT, &numProcsOnline},
|
||||
{FF_FORMAT_ARG_TYPE_INT, &numProcsAvailable},
|
||||
{FF_FORMAT_ARG_TYPE_INT, &physicalCores},
|
||||
{FF_FORMAT_ARG_TYPE_INT, &numProcs},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpuTemp},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &biosLimit},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &scalingMaxFreq},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &scalingMinFreq},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &infoMaxFreq},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &infoMinFreq},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &procGhz},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &ghz}
|
||||
ffPrintAndWriteToCache(instance, FF_CPU_MODULE_NAME, &instance->config.cpu, &output, FF_CPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &cpu->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &cpu->vendor},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu->coresPhysical},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu->coresLogical},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu->coresOnline},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu->frequencyMin},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu->frequencyMax},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu->temperature}
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&cpu);
|
||||
ffStrbufDestroy(&namePretty);
|
||||
ffStrbufDestroy(&name);
|
||||
ffStrbufDestroy(&vendor);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "common/parsing.h"
|
||||
#include "common/settings.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_DE_MODULE_NAME "DE"
|
||||
#define FF_DE_NUM_FORMAT_ARGS 3
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#define FF_DISK_MODULE_NAME "Disk"
|
||||
#define FF_DISK_NUM_FORMAT_ARGS 4
|
||||
|
||||
static void getKey(FFinstance* instance, FFstrbuf* key, const char* folderPath, bool showFolderPath)
|
||||
static void createKey(FFinstance* instance, const char* folderPath, FFstrbuf* key)
|
||||
{
|
||||
if(instance->config.disk.key.length == 0)
|
||||
{
|
||||
if(showFolderPath)
|
||||
ffStrbufAppendF(key, FF_DISK_MODULE_NAME" (%s)", folderPath);
|
||||
else
|
||||
ffStrbufSetS(key, FF_DISK_MODULE_NAME);
|
||||
ffStrbufAppendS(key, FF_DISK_MODULE_NAME);
|
||||
if(folderPath != NULL)
|
||||
ffStrbufAppendF(key, " (%s)", folderPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -23,119 +23,126 @@ static void getKey(FFinstance* instance, FFstrbuf* key, const char* folderPath,
|
||||
}
|
||||
}
|
||||
|
||||
static void printStatvfs(FFinstance* instance, FFstrbuf* key, struct statvfs* fs)
|
||||
static void printStatvfs(FFinstance* instance, const FFstrbuf* key, const char* folderPath, struct statvfs* fs)
|
||||
{
|
||||
const double GB = 1024 * 1024 * 1024;
|
||||
uint64_t total = fs->f_blocks * fs->f_frsize;
|
||||
|
||||
double total = ((double) (fs->f_blocks * fs->f_frsize)) / GB;
|
||||
double available = ((double) (fs->f_bfree * fs->f_frsize)) / GB;
|
||||
double used = total - available;
|
||||
uint8_t percentage = (uint8_t) ((used / total) * 100.0);
|
||||
if(total == 0)
|
||||
{
|
||||
ffPrintErrorString(instance, key->chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs for %s returned size 0", folderPath);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t used = total - (fs->f_bfree * fs->f_frsize);
|
||||
uint32_t files = (uint32_t) (fs->f_files - fs->f_ffree);
|
||||
uint8_t percentage = (uint8_t) ((used / (long double) total) * 100.0);
|
||||
|
||||
FFstrbuf usedPretty;
|
||||
ffStrbufInit(&usedPretty);
|
||||
ffParseSize(used, instance->config.binaryPrefixType, &usedPretty);
|
||||
|
||||
FFstrbuf totalPretty;
|
||||
ffStrbufInit(&totalPretty);
|
||||
ffParseSize(total, instance->config.binaryPrefixType, &totalPretty);
|
||||
|
||||
if(instance->config.disk.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, key->chars, 0, NULL);
|
||||
|
||||
if(used >= 100.0)
|
||||
printf("%.0f", used);
|
||||
else
|
||||
printf("%.1f", used);
|
||||
|
||||
fputs(" GB / ", stdout);
|
||||
|
||||
if(total >= 100.0)
|
||||
printf("%.0f", total);
|
||||
else
|
||||
printf("%.1f", total);
|
||||
|
||||
printf("GiB (%u%%)\n", percentage);
|
||||
printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, percentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, key->chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &used},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &total},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &files},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &percentage}
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &percentage},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &files},
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&totalPretty);
|
||||
ffStrbufDestroy(&usedPretty);
|
||||
}
|
||||
|
||||
static void printStatvfsCreateKey(FFinstance* instance, const char* folderPath, struct statvfs* fs)
|
||||
static void printFolderAutodetection(FFinstance* instance, const char* folderPath, struct statvfs* fs)
|
||||
{
|
||||
FF_STRBUF_CREATE(key);
|
||||
getKey(instance, &key, folderPath, true);
|
||||
printStatvfs(instance, &key, fs);
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
createKey(instance, folderPath, &key);
|
||||
printStatvfs(instance, &key, folderPath, fs);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
|
||||
static void printFolder(FFinstance* instance, const char* folderPath)
|
||||
static void printFoldersAutodetection(FFinstance* instance)
|
||||
{
|
||||
FF_STRBUF_CREATE(key);
|
||||
getKey(instance, &key, folderPath, true);
|
||||
struct statvfs fsRoot;
|
||||
int rootRet = statvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot);
|
||||
|
||||
if(rootRet != 0)
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
createKey(instance, NULL, &key);
|
||||
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs for / returned not zero: %i", rootRet);
|
||||
ffStrbufDestroy(&key);
|
||||
return;
|
||||
}
|
||||
|
||||
//On MacOS statvfs seems to return different f_fsid for the same filesystem.
|
||||
//Since it isn't really possible to install /Users on a separate disk anyway, just never print it by default.
|
||||
#ifndef __APPLE__
|
||||
struct statvfs fsHome;
|
||||
int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome);
|
||||
bool printHome = homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid);
|
||||
#else
|
||||
bool printHome = false;
|
||||
#endif // !__APPLE__
|
||||
|
||||
printFolderAutodetection(instance, printHome ? FASTFETCH_TARGET_DIR_ROOT"/" : NULL, &fsRoot);
|
||||
|
||||
#ifndef __APPLE__
|
||||
if(printHome)
|
||||
printFolderAutodetection(instance, FASTFETCH_TARGET_DIR_HOME, &fsHome);
|
||||
#endif // !__APPLE__
|
||||
}
|
||||
|
||||
static void printFolderCustom(FFinstance* instance, const char* folderPath)
|
||||
{
|
||||
FFstrbuf key;
|
||||
ffStrbufInit(&key);
|
||||
createKey(instance, folderPath, &key);
|
||||
|
||||
struct statvfs fs;
|
||||
int ret = statvfs(folderPath, &fs);
|
||||
if(ret != 0 && instance->config.disk.outputFormat.length == 0)
|
||||
if(ret != 0)
|
||||
{
|
||||
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
|
||||
ffStrbufDestroy(&key);
|
||||
return;
|
||||
}
|
||||
|
||||
printStatvfs(instance, &key, &fs);
|
||||
printStatvfs(instance, &key, folderPath, &fs);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
|
||||
void ffPrintDisk(FFinstance* instance)
|
||||
{
|
||||
ffStrbufTrim(&instance->config.diskFolders, ':');
|
||||
|
||||
if(instance->config.diskFolders.length == 0)
|
||||
{
|
||||
struct statvfs fsRoot;
|
||||
int rootRet = statvfs("/", &fsRoot);
|
||||
|
||||
struct statvfs fsHome;
|
||||
int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome);
|
||||
|
||||
if(rootRet != 0 && homeRet != 0)
|
||||
{
|
||||
FF_STRBUF_CREATE(key);
|
||||
getKey(instance, &key, "", false);
|
||||
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs failed for both / and " FASTFETCH_TARGET_DIR_HOME);
|
||||
ffStrbufDestroy(&key);
|
||||
return;
|
||||
}
|
||||
|
||||
if(rootRet == 0)
|
||||
printStatvfsCreateKey(instance, "/", &fsRoot);
|
||||
|
||||
if(homeRet == 0 && (rootRet != 0 || fsRoot.f_fsid != fsHome.f_fsid))
|
||||
printStatvfsCreateKey(instance, FASTFETCH_TARGET_DIR_HOME, &fsHome);
|
||||
printFoldersAutodetection(instance);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < instance->config.diskFolders.length)
|
||||
{
|
||||
ffStrbufTrim(&instance->config.diskFolders, ':');
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
|
||||
instance->config.diskFolders.chars[colonIndex] = '\0';
|
||||
|
||||
if(instance->config.diskFolders.length == 0)
|
||||
{
|
||||
FF_STRBUF_CREATE(key);
|
||||
getKey(instance, &key, "", false);
|
||||
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "Custom disk folders string doesn't contain any folders");
|
||||
ffStrbufDestroy(&key);
|
||||
return;
|
||||
}
|
||||
printFolderCustom(instance, instance->config.diskFolders.chars + startIndex);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < instance->config.diskFolders.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
|
||||
instance->config.diskFolders.chars[colonIndex] = '\0';
|
||||
|
||||
printFolder(instance, instance->config.diskFolders.chars + startIndex);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "common/parsing.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_FONT_MODULE_NAME "Font"
|
||||
#define FF_FONT_NUM_FORMAT_ARGS 21
|
||||
|
||||
@@ -1,198 +1,35 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/temps.h"
|
||||
#include "detection/vulkan.h"
|
||||
#include "detection/host/host.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FF_GPU_MODULE_NAME "GPU"
|
||||
#define FF_GPU_NUM_FORMAT_ARGS 6
|
||||
#define FF_GPU_NUM_FORMAT_ARGS 4
|
||||
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* result)
|
||||
static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache, FFGPUResult* gpu)
|
||||
{
|
||||
const char* vendorPretty;
|
||||
if(ffStrbufIgnCaseCompS(&result->vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0)
|
||||
vendorPretty = "AMD ATI";
|
||||
else if(ffStrbufIgnCaseCompS(&result->vendor, "NVIDIA Corporation") == 0)
|
||||
vendorPretty = "Nvidia";
|
||||
else if(ffStrbufIgnCaseCompS(&result->vendor, "Intel Corporation") == 0)
|
||||
vendorPretty = "Intel";
|
||||
else
|
||||
vendorPretty = result->vendor.chars;
|
||||
FFstrbuf output;
|
||||
ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length);
|
||||
|
||||
FFstrbuf namePretty;
|
||||
ffStrbufInitCopy(&namePretty, &result->name);
|
||||
ffStrbufSubstrBeforeLastC(&namePretty, ']');
|
||||
ffStrbufSubstrAfterFirstC(&namePretty, '[');
|
||||
|
||||
FFstrbuf gpu;
|
||||
ffStrbufInitA(&gpu, result->vendor.length + 1 + namePretty.length);
|
||||
|
||||
if(ffStrSet(vendorPretty))
|
||||
if(gpu->vendor.length > 0)
|
||||
{
|
||||
ffStrbufAppendS(&gpu, vendorPretty);
|
||||
ffStrbufAppendC(&gpu, ' ');
|
||||
ffStrbufAppend(&output, &gpu->vendor);
|
||||
ffStrbufAppendC(&output, ' ');
|
||||
}
|
||||
|
||||
ffStrbufAppend(&gpu, &namePretty);
|
||||
ffStrbufAppend(&output, &gpu->name);
|
||||
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, vendorPretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &namePretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->driver},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature}
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &output, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&result->vendor);
|
||||
ffStrbufDestroy(&result->name);
|
||||
ffStrbufDestroy(&result->driver);
|
||||
ffStrbufDestroy(&gpu);
|
||||
ffStrbufDestroy(&namePretty);
|
||||
}
|
||||
|
||||
static void printGPUList(FFinstance* instance, const FFlist* list)
|
||||
{
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
for(uint8_t i = 0; i < (uint8_t) list->length; i++)
|
||||
printGPUResult(instance, list->length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(list, i));
|
||||
|
||||
ffCacheClose(&cache);
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/library.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
|
||||
//see https://github.com/pciutils/pciutils/blob/5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b/ls-kernel.c#L220
|
||||
static void pciGetDriver(struct pci_dev* dev, FFstrbuf* driver, char*(*ffpci_get_param)(struct pci_access*, char*))
|
||||
{
|
||||
if(dev->access->method != PCI_ACCESS_SYS_BUS_PCI)
|
||||
return;
|
||||
|
||||
const char* base = ffpci_get_param(dev->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
|
||||
FFstrbuf path;
|
||||
ffStrbufInitA(&path, 64);
|
||||
ffStrbufAppendF(&path, "%s/devices/%04x:%02x:%02x.%d/driver", base, dev->domain, dev->bus, dev->dev, dev->func);
|
||||
|
||||
ffStrbufEnsureFree(driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, driver->chars, driver->allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
driver->length = (uint32_t) resultLength;
|
||||
driver->chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(driver, '/');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&path);
|
||||
}
|
||||
|
||||
static double pciGetTemperatur(const FFinstance* instance, uint16_t deviceClass)
|
||||
{
|
||||
const FFTempsResult* tempsResult = ffDetectTemps(instance);
|
||||
|
||||
for(uint32_t i = 0; i < tempsResult->values.length; i++)
|
||||
{
|
||||
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
|
||||
|
||||
uint32_t tempClass;
|
||||
if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1)
|
||||
continue;
|
||||
|
||||
//The kernel exposes the device class multiplied by 256 for some reason
|
||||
if(tempClass == deviceClass * 256)
|
||||
return tempValue->value;
|
||||
}
|
||||
|
||||
return 0.0 / 0.0; //NaN
|
||||
}
|
||||
|
||||
static bool pciPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(pci, instance->config.libPCI, false, "libpci.so", 4)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_alloc, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_init, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_scan_bus, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_fill_info, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_lookup_name, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_get_param, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(pci, pci_cleanup, false)
|
||||
|
||||
FFlist results;
|
||||
ffListInit(&results, sizeof(FFGPUResult));
|
||||
|
||||
struct pci_access *pacc = ffpci_alloc();
|
||||
ffpci_init(pacc);
|
||||
ffpci_scan_bus(pacc);
|
||||
|
||||
struct pci_dev* dev;
|
||||
for (dev=pacc->devices; dev; dev=dev->next)
|
||||
{
|
||||
ffpci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS);
|
||||
char class[1024];
|
||||
ffpci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class);
|
||||
if(
|
||||
strcasecmp("VGA compatible controller", class) == 0 ||
|
||||
strcasecmp("3D controller", class) == 0 ||
|
||||
strcasecmp("Display controller", class) == 0
|
||||
) {
|
||||
FFGPUResult* result = ffListAdd(&results);
|
||||
|
||||
ffStrbufInitA(&result->vendor, 256);
|
||||
ffpci_lookup_name(pacc, result->vendor.chars, (int) ffStrbufGetFree(&result->vendor), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->vendor);
|
||||
|
||||
ffStrbufInitA(&result->name, 256);
|
||||
ffpci_lookup_name(pacc, result->name.chars, (int) ffStrbufGetFree(&result->name), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
|
||||
ffStrbufRecalculateLength(&result->name);
|
||||
|
||||
ffStrbufInit(&result->driver);
|
||||
result->temperature = 0;
|
||||
|
||||
//We only need it for the format string, so don't detect it if it isn't needed
|
||||
if(instance->config.gpu.outputFormat.length > 0)
|
||||
{
|
||||
pciGetDriver(dev, &result->driver, ffpci_get_param);
|
||||
result->temperature = pciGetTemperatur(instance, dev->device_class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ffpci_cleanup(pacc);
|
||||
dlclose(pci);
|
||||
|
||||
if(results.length == 0)
|
||||
{
|
||||
ffListDestroy(&results);
|
||||
return false;
|
||||
}
|
||||
|
||||
printGPUList(instance, &results);
|
||||
|
||||
ffListDestroy(&results);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool vulkanPrintGPUs(FFinstance* instance)
|
||||
{
|
||||
const FFVulkanResult* result = ffDetectVulkan(instance);
|
||||
if(result->devices.length == 0)
|
||||
return false;
|
||||
|
||||
printGPUList(instance, &result->devices);
|
||||
return true;
|
||||
ffStrbufDestroy(&output);
|
||||
}
|
||||
|
||||
void ffPrintGPU(FFinstance* instance)
|
||||
@@ -200,22 +37,25 @@ void ffPrintGPU(FFinstance* instance)
|
||||
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
if(
|
||||
getenv("WSLENV") != NULL ||
|
||||
getenv("WSL_DISTRO") != NULL ||
|
||||
getenv("WSL_INTEROP") != NULL
|
||||
) {
|
||||
if(ffStrbufCompS(&ffDetectHost()->productName, FF_HOST_PRODUCT_NAME_WSL) == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "WSL doesn't expose senseful GPU names");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
if(pciPrintGPUs(instance))
|
||||
return;
|
||||
#endif
|
||||
const FFlist* gpus = ffDetectGPU(instance);
|
||||
|
||||
if(vulkanPrintGPUs(instance))
|
||||
if(gpus->length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found");
|
||||
return;
|
||||
}
|
||||
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found.");
|
||||
FFcache cache;
|
||||
ffCacheOpenWrite(instance, FF_GPU_MODULE_NAME, &cache);
|
||||
|
||||
for(uint8_t i = 0; i < (uint8_t) gpus->length; i++)
|
||||
printGPUResult(instance, gpus->length == 1 ? 0 : (uint8_t) (i + 1), &cache, ffListGet(gpus, i));
|
||||
|
||||
ffCacheClose(&cache);
|
||||
}
|
||||
|
||||
@@ -1,196 +1,53 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/caching.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "detection/host/host.h"
|
||||
|
||||
#define FF_HOST_MODULE_NAME "Host"
|
||||
#define FF_HOST_NUM_FORMAT_ARGS 15
|
||||
|
||||
#ifndef __ANDROID__
|
||||
#include "common/io.h"
|
||||
#else
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifndef __ANDROID__
|
||||
static bool hostValueSet(FFstrbuf* value)
|
||||
{
|
||||
ffStrbufTrimRight(value, '\n');
|
||||
ffStrbufTrim(value, ' ');
|
||||
|
||||
return
|
||||
value->length > 0 &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
|
||||
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
|
||||
ffStrbufIgnCaseCompS(value, "None") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
|
||||
ffStrbufIgnCaseCompS(value, "All Series") != 0
|
||||
;
|
||||
}
|
||||
|
||||
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
|
||||
{
|
||||
ffReadFileBuffer(devicesPath, buffer);
|
||||
|
||||
if(buffer->length == 0)
|
||||
ffReadFileBuffer(classPath, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffPrintHost(FFinstance* instance)
|
||||
{
|
||||
if(ffPrintFromCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, FF_HOST_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
FFstrbuf product_family;
|
||||
ffStrbufInit(&product_family);
|
||||
#ifndef __ANDROID__
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &product_family);
|
||||
if(!hostValueSet(&product_family))
|
||||
ffStrbufClear(&product_family);
|
||||
#else
|
||||
ffSettingsGetAndroidProperty("ro.product.device", &product_family);
|
||||
#endif
|
||||
const FFHostResult* host = ffDetectHost();
|
||||
|
||||
FFstrbuf product_name;
|
||||
ffStrbufInit(&product_name);
|
||||
#ifndef __ANDROID__
|
||||
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &product_name);
|
||||
|
||||
if(product_name.length == 0)
|
||||
ffReadFileBuffer("/sys/firmware/devicetree/base/model", &product_name);
|
||||
|
||||
if(product_name.length == 0)
|
||||
ffReadFileBuffer("/tmp/sysinfo/model", &product_name);
|
||||
|
||||
if(ffStrbufStartsWithS(&product_name, "Standard PC"))
|
||||
{
|
||||
FFstrbuf copy;
|
||||
ffStrbufInitCopy(©, &product_name);
|
||||
ffStrbufSetS(&product_name, "KVM/QEMU ");
|
||||
ffStrbufAppend(&product_name, ©);
|
||||
ffStrbufDestroy(©);
|
||||
}
|
||||
|
||||
if(!hostValueSet(&product_name))
|
||||
ffStrbufClear(&product_name);
|
||||
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(product_name.length == 0 && product_family.length == 0 && (
|
||||
getenv("WSLENV") != NULL ||
|
||||
getenv("WSL_DISTRO") != NULL ||
|
||||
getenv("WSL_INTEROP") != NULL
|
||||
)) ffStrbufAppendS(&product_name, "Windows Subsystem for Linux");
|
||||
#else
|
||||
ffSettingsGetAndroidProperty("ro.product.brand", &product_name);
|
||||
if(product_name.length > 0){
|
||||
product_name.chars[0] = (char) toupper(product_name.chars[0]);
|
||||
ffStrbufAppendC(&product_name, ' ');
|
||||
}
|
||||
|
||||
if(!ffSettingsGetAndroidProperty("ro.product.model", &product_name))
|
||||
ffSettingsGetAndroidProperty("ro.product.name", &product_name);
|
||||
|
||||
ffStrbufTrimRight(&product_name, ' ');
|
||||
#endif
|
||||
|
||||
if(product_family.length == 0 && product_name.length == 0)
|
||||
if(host->productFamily.length == 0 && host->productName.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&product_family);
|
||||
ffStrbufDestroy(&product_name);
|
||||
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "neither product_family nor product_name is set by O.E.M.");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define FF_HOST_DATA(name) \
|
||||
FFstrbuf name; \
|
||||
ffStrbufInitA(&name, 0);
|
||||
#else
|
||||
#define FF_HOST_DATA(name) \
|
||||
FFstrbuf name; \
|
||||
ffStrbufInit(&name); \
|
||||
getHostValue("/sys/devices/virtual/dmi/id/"#name, "/sys/class/dmi/id/"#name, &name); \
|
||||
if(!hostValueSet(&name)) \
|
||||
ffStrbufClear(&name);
|
||||
#endif
|
||||
FFstrbuf output;
|
||||
ffStrbufInit(&output);
|
||||
|
||||
FF_HOST_DATA(product_version)
|
||||
FF_HOST_DATA(product_sku)
|
||||
FF_HOST_DATA(bios_date)
|
||||
FF_HOST_DATA(bios_release)
|
||||
FF_HOST_DATA(bios_vendor)
|
||||
FF_HOST_DATA(bios_version)
|
||||
FF_HOST_DATA(board_name)
|
||||
FF_HOST_DATA(board_vendor)
|
||||
FF_HOST_DATA(board_version)
|
||||
FF_HOST_DATA(chassis_type)
|
||||
FF_HOST_DATA(chassis_vendor)
|
||||
FF_HOST_DATA(chassis_version)
|
||||
FF_HOST_DATA(sys_vendor)
|
||||
|
||||
FFstrbuf host;
|
||||
ffStrbufInit(&host);
|
||||
|
||||
if(product_name.length > 0)
|
||||
ffStrbufAppend(&host, &product_name);
|
||||
if(host->productName.length > 0)
|
||||
ffStrbufAppend(&output, &host->productName);
|
||||
else
|
||||
ffStrbufAppend(&host, &product_family);
|
||||
ffStrbufAppend(&output, &host->productFamily);
|
||||
|
||||
if(product_version.length > 0)
|
||||
if(host->productVersion.length > 0)
|
||||
{
|
||||
ffStrbufAppendC(&host, ' ');
|
||||
ffStrbufAppend(&host, &product_version);
|
||||
ffStrbufAppendC(&output, ' ');
|
||||
ffStrbufAppend(&output, &host->productVersion);
|
||||
}
|
||||
|
||||
ffPrintAndWriteToCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, &host, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &product_family},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &product_name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &product_version},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &product_sku},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_date},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_release},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_version},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &board_name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &board_vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &board_version},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_type},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_version},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &sys_vendor}
|
||||
ffPrintAndWriteToCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, &output, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productFamily},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productSku},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosDate},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosRelease},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisType},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVersion},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &host->sysVendor}
|
||||
});
|
||||
|
||||
ffStrbufDestroy(&product_family);
|
||||
ffStrbufDestroy(&product_name);
|
||||
|
||||
//On Android, all of them get initialized without heap, so no need to destroy them.
|
||||
#ifndef __ANDROID__
|
||||
ffStrbufDestroy(&product_version);
|
||||
ffStrbufDestroy(&product_sku);
|
||||
ffStrbufDestroy(&bios_date);
|
||||
ffStrbufDestroy(&bios_release);
|
||||
ffStrbufDestroy(&bios_vendor);
|
||||
ffStrbufDestroy(&bios_version);
|
||||
ffStrbufDestroy(&board_name);
|
||||
ffStrbufDestroy(&board_vendor);
|
||||
ffStrbufDestroy(&board_version);
|
||||
ffStrbufDestroy(&chassis_type);
|
||||
ffStrbufDestroy(&chassis_vendor);
|
||||
ffStrbufDestroy(&chassis_version);
|
||||
ffStrbufDestroy(&sys_vendor);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "common/parsing.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_ICONS_MODULE_NAME "Icons"
|
||||
#define FF_ICONS_NUM_FORMAT_ARGS 5
|
||||
|
||||
@@ -18,10 +18,6 @@ static void getLocaleFromEnv(FFstrbuf* locale)
|
||||
if(locale->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(locale, getenv("LC_CTYPE"));
|
||||
if(locale->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(locale, getenv("LC_MESSAGES"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,43 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "common/parsing.h"
|
||||
#include "detection/memory/memory.h"
|
||||
|
||||
#define FF_MEMORY_MODULE_NAME "Memory"
|
||||
#define FF_MEMORY_NUM_FORMAT_ARGS 3
|
||||
|
||||
// Impl inspired by: https://github.com/sam-barr/paleofetch/blob/b7c58a52c0de39b53c9b5f417889a5886d324bfa/paleofetch.c#L544
|
||||
void ffPrintMemory(FFinstance* instance)
|
||||
{
|
||||
FILE* meminfo = fopen("/proc/meminfo", "r");
|
||||
if(meminfo == NULL) {
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "fopen(\"""/proc/meminfo\", \"r\") == NULL");
|
||||
return;
|
||||
}
|
||||
const FFMemoryResult* memory = ffDetectMemory();
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
uint32_t total = 0,
|
||||
shared = 0,
|
||||
memfree = 0,
|
||||
buffers = 0,
|
||||
cached = 0,
|
||||
reclaimable = 0;
|
||||
|
||||
while (getline(&line, &len, meminfo) != -1) {
|
||||
sscanf(line, "MemTotal: %u", &total);
|
||||
sscanf(line, "Shmem: %u", &shared);
|
||||
sscanf(line, "MemFree: %u", &memfree);
|
||||
sscanf(line, "Buffers: %u", &buffers);
|
||||
sscanf(line, "Cached: %u", &cached);
|
||||
sscanf(line, "SReclaimable: %u", &reclaimable);
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(meminfo);
|
||||
|
||||
uint32_t used_mem = (total + shared - memfree - buffers - cached - reclaimable) / 1024;
|
||||
uint32_t total_mem = total / 1024;
|
||||
uint8_t percentage = (uint8_t) ((used_mem / (double) total_mem) * 100);
|
||||
|
||||
if(used_mem == 0 && total_mem == 0 && percentage == 0)
|
||||
if(memory->bytesUsed == 0 && memory->bytesTotal == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "/proc/meminfo could't be parsed");
|
||||
ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "Failed to detect memory");
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf usedPretty;
|
||||
ffStrbufInit(&usedPretty);
|
||||
ffParseSize(memory->bytesUsed, instance->config.binaryPrefixType, &usedPretty);
|
||||
|
||||
FFstrbuf totalPretty;
|
||||
ffStrbufInit(&totalPretty);
|
||||
ffParseSize(memory->bytesTotal, instance->config.binaryPrefixType, &totalPretty);
|
||||
|
||||
if(instance->config.memory.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory.key);
|
||||
printf("%uMiB / %uMiB (%u%%)\n", used_mem, total_mem, percentage);
|
||||
printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, memory->percentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &used_mem},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &total_mem},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &percentage}
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &memory->percentage},
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&usedPretty);
|
||||
ffStrbufDestroy(&totalPretty);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifdef FF_HAVE_OPENCL
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
#include <string.h>
|
||||
|
||||
#define CL_TARGET_OPENCL_VERSION 100
|
||||
#include <CL/cl.h>
|
||||
@@ -42,6 +43,11 @@ static const char* openCLHandelData(FFinstance* instance, OpenCLData* data)
|
||||
if(!ffStrSet(version))
|
||||
return "clGetDeviceInfo returned NULL or empty string";
|
||||
|
||||
const char* versionPretty = version;
|
||||
const char* prefix = "OpenCL ";
|
||||
if(strncasecmp(version, prefix, sizeof(prefix) - 1) == 0)
|
||||
versionPretty = version + sizeof(prefix) - 1;
|
||||
|
||||
char device[128];
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(device), device, NULL);
|
||||
|
||||
@@ -51,12 +57,12 @@ static const char* openCLHandelData(FFinstance* instance, OpenCLData* data)
|
||||
if(instance->config.openCL.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL.key);
|
||||
puts(version);
|
||||
puts(versionPretty);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, FF_OPENCL_NUM_FORMAT_ARGS, (FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRING, version},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, versionPretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, device},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, vendor}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/os.h"
|
||||
#include "detection/os/os.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -13,13 +13,11 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result)
|
||||
if(os->name.length > 0)
|
||||
ffStrbufAppend(result, &os->name);
|
||||
else if(os->prettyName.length > 0)
|
||||
ffStrbufAppend(result, &os->name);
|
||||
ffStrbufAppend(result, &os->prettyName);
|
||||
else if(os->id.length > 0)
|
||||
ffStrbufAppend(result, &os->id);
|
||||
else if(os->systemName.length > 0)
|
||||
ffStrbufAppend(result, &os->systemName);
|
||||
else
|
||||
ffStrbufAppendS(result, "Linux");
|
||||
ffStrbufAppend(result, &os->systemName);
|
||||
|
||||
//Append version if it is missing
|
||||
if(os->versionID.length > 0 && ffStrbufFirstIndex(result, &os->versionID) == result->length)
|
||||
@@ -84,7 +82,7 @@ void ffPrintOS(FFinstance* instance)
|
||||
{
|
||||
const FFOSResult* os = ffDetectOS(instance);
|
||||
|
||||
if(os->name.length == 0 && os->prettyName.length == 0)
|
||||
if(os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0 && os->systemName.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, "Could not detect OS");
|
||||
return;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/os.h"
|
||||
#include "detection/os/os.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define FF_PACKAGES_MODULE_NAME "Packages"
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 13
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 14
|
||||
|
||||
typedef struct PackageCounts
|
||||
{
|
||||
@@ -26,6 +26,7 @@ typedef struct PackageCounts
|
||||
uint32_t apk;
|
||||
uint32_t flatpak;
|
||||
uint32_t snap;
|
||||
uint32_t brew;
|
||||
|
||||
FFstrbuf pacmanBranch;
|
||||
} PackageCounts;
|
||||
@@ -52,6 +53,8 @@ static uint32_t getNumElements(const char* dirname, unsigned char type)
|
||||
return num_elements;
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
static uint32_t getNumStrings(const char* filename, const char* needle)
|
||||
{
|
||||
FILE* file = fopen(filename, "r");
|
||||
@@ -77,6 +80,8 @@ static uint32_t getNumStrings(const char* filename, const char* needle)
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
|
||||
static uint32_t countFilesRecursive(FFstrbuf* baseDirPath, const char* filename)
|
||||
{
|
||||
uint32_t baseDirPathLength = baseDirPath->length;
|
||||
@@ -144,6 +149,33 @@ static uint32_t getNixPackages(char* path)
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t getXBPS(FFstrbuf* baseDir)
|
||||
{
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type != DT_REG || strncasecmp(entry->d_name, "pkgdb-", 6) != 0)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
result = getNumStrings(baseDir->chars, "<string>installed</string>");
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // !__ANDROID__
|
||||
#endif // !__APPLE__
|
||||
|
||||
#ifdef FF_HAVE_RPM
|
||||
#include "common/library.h"
|
||||
#include <rpm/rpmlib.h>
|
||||
@@ -194,36 +226,19 @@ static uint32_t getRpmFromLibrpm(const FFinstance* instance)
|
||||
|
||||
return count > 0 ? (uint32_t) count : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t getXBPS(FFstrbuf* baseDir)
|
||||
{
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type != DT_REG || strncasecmp(entry->d_name, "pkgdb-", 6) != 0)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
result = getNumStrings(baseDir->chars, "<string>installed</string>");
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
#endif //FF_HAVE_RPM
|
||||
|
||||
static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(__ANDROID__)
|
||||
FF_UNUSED(instance);
|
||||
#endif
|
||||
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
|
||||
#ifndef __APPLE__ //Linux desktop and Anrdoid
|
||||
|
||||
//pacman
|
||||
ffStrbufAppendS(baseDir, "/var/lib/pacman/local");
|
||||
packageCounts->pacman += getNumElements(baseDir->chars, DT_DIR);
|
||||
@@ -234,6 +249,8 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, Pack
|
||||
packageCounts->dpkg += getNumStrings(baseDir->chars, "Status: ");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
#ifndef __ANDROID__ //Linux Desktop
|
||||
|
||||
//rpm
|
||||
ffStrbufAppendS(baseDir, "/var/lib/rpm/rmpdb.sqlite");
|
||||
packageCounts->rpm += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(blob) FROM Packages");
|
||||
@@ -281,6 +298,20 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, Pack
|
||||
if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0)
|
||||
ffStrbufAppendS(&packageCounts->pacmanBranch, "stable");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
#endif // !__ANDROID__
|
||||
|
||||
#else // !__APPLE__
|
||||
|
||||
//brew
|
||||
ffStrbufAppendS(baseDir, "/usr/local/Caskroom");
|
||||
packageCounts->brew += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
ffStrbufAppendS(baseDir, "/usr/local/Cellar");
|
||||
packageCounts->brew += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
#endif // __APPLE__
|
||||
}
|
||||
|
||||
static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
|
||||
@@ -336,14 +367,18 @@ void ffPrintPackages(FFinstance* instance)
|
||||
counts.rpm = getRpmFromLibrpm(instance);
|
||||
#endif
|
||||
|
||||
//nix user
|
||||
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
|
||||
ffStrbufAppendS(&baseDir, "/.nix-profile");
|
||||
uint32_t nixUser = getNixPackages(baseDir.chars);
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
//nix user
|
||||
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
|
||||
ffStrbufAppendS(&baseDir, "/.nix-profile");
|
||||
uint32_t nixUser = getNixPackages(baseDir.chars);
|
||||
#else
|
||||
uint32_t nixUser = 0;
|
||||
#endif
|
||||
|
||||
ffStrbufDestroy(&baseDir);
|
||||
|
||||
uint32_t all = counts.pacman + counts.dpkg + counts.rpm + counts.emerge + counts.xbps + counts.nixSystem + nixUser + counts.nixDefault + counts.apk + counts.flatpak + counts.snap;
|
||||
uint32_t all = counts.pacman + counts.dpkg + counts.rpm + counts.emerge + counts.xbps + counts.nixSystem + nixUser + counts.nixDefault + counts.apk + counts.flatpak + counts.snap + counts.brew;
|
||||
if(all == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packages, "No packages from known package managers found");
|
||||
@@ -400,6 +435,7 @@ void ffPrintPackages(FFinstance* instance)
|
||||
FF_PRINT_PACKAGE(apk)
|
||||
FF_PRINT_PACKAGE(flatpak)
|
||||
FF_PRINT_PACKAGE(snap)
|
||||
FF_PRINT_PACKAGE(brew)
|
||||
|
||||
//Fix linter warning of unused value of all
|
||||
(void) all;
|
||||
@@ -423,7 +459,8 @@ void ffPrintPackages(FFinstance* instance)
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.nixDefault},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.apk},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.flatpak},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.snap}
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.snap},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.brew}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,16 +6,22 @@
|
||||
|
||||
void ffPrintProcesses(FFinstance* instance)
|
||||
{
|
||||
#if FF_HAVE_SYSINFO_H
|
||||
uint16_t numProcesses = instance->state.sysinfo.procs;
|
||||
#else
|
||||
uint16_t numProcesses = 0;
|
||||
#endif
|
||||
|
||||
if(instance->config.processes.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes.key);
|
||||
|
||||
printf("%hu\n", instance->state.sysinfo.procs);
|
||||
printf("%hu\n", numProcesses);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes, FF_PROCESSES_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &instance->state.sysinfo.procs}
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &numProcesses}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_RESOLUTION_MODULE_NAME "Resolution"
|
||||
#define FF_RESOLUTION_NUM_FORMAT_ARGS 3
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define FF_SONG_MODULE_NAME "Song"
|
||||
#define FF_SONG_MODULE_NAME "Media"
|
||||
#define FF_SONG_NUM_FORMAT_ARGS 5
|
||||
|
||||
static bool shouldIgoreChar(char c)
|
||||
@@ -55,9 +55,9 @@ void ffPrintSong(FFinstance* instance)
|
||||
FFstrbuf songPretty;
|
||||
ffStrbufInitCopy(&songPretty, &media->song);
|
||||
const char* removeStrings[] = {
|
||||
"(Official Music Video)", "(Official Video)", "(Music Video)",
|
||||
"[Official Music Video]", "[Official Video]", "[Music Video]",
|
||||
"| Official Music Video", "| Official Video", "| Music Video",
|
||||
"(Official Music Video)", "(Official Video)", "(Music Video)", "(Official HD Video)",
|
||||
"[Official Music Video]", "[Official Video]", "[Music Video]", "[Official HD Video]",
|
||||
"| Official Music Video", "| Official Video", "| Music Video", "| Official HD Video",
|
||||
"[Official Audio]", "[Audio]", "(Audio)", "| Official Audio", "| Audio", "| OFFICIAL AUDIO",
|
||||
"(Lyric Video)", "(Official Lyric Video)", "(Lyrics)",
|
||||
"[Lyric Video]", "[Official Lyric Video]", "[Lyrics]",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "common/font.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "detection/terminalshell.h"
|
||||
|
||||
#define FF_TERMFONT_MODULE_NAME "Terminal Font"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "common/parsing.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_THEME_MODULE_NAME "Theme"
|
||||
#define FF_THEME_NUM_FORMAT_ARGS 7
|
||||
|
||||
@@ -1,15 +1,45 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
|
||||
#if __APPLE__
|
||||
#include "time.h"
|
||||
#include "sys/sysctl.h"
|
||||
#endif
|
||||
|
||||
#define FF_UPTIME_MODULE_NAME "Uptime"
|
||||
#define FF_UPTIME_NUM_FORMAT_ARGS 4
|
||||
|
||||
void ffPrintUptime(FFinstance* instance)
|
||||
{
|
||||
uint32_t days = (uint32_t) instance->state.sysinfo.uptime / 86400;
|
||||
uint32_t hours = (uint32_t) (instance->state.sysinfo.uptime - (days * 86400)) / 3600;
|
||||
uint32_t minutes = (uint32_t) (instance->state.sysinfo.uptime - (days * 86400) - (hours * 3600)) / 60;
|
||||
uint32_t seconds = (uint32_t) instance->state.sysinfo.uptime - (days * 86400) - (hours * 3600) - (minutes * 60);
|
||||
uint64_t uptime;
|
||||
|
||||
#if FF_HAVE_SYSINFO_H
|
||||
uptime = (uint64_t) instance->state.sysinfo.uptime;
|
||||
#elif __APPLE__
|
||||
struct timeval bootTime;
|
||||
size_t bootTimeSize = sizeof(bootTime);
|
||||
if(sysctl(
|
||||
(int[]) {CTL_KERN, KERN_BOOTTIME}, 2,
|
||||
&bootTime, &bootTimeSize,
|
||||
NULL, 0
|
||||
) == 0)
|
||||
uptime = (uint64_t) difftime(time(NULL), bootTime.tv_sec);
|
||||
else
|
||||
uptime = 0;
|
||||
#else
|
||||
uptime = 0;
|
||||
#endif
|
||||
|
||||
if(uptime == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_UPTIME_MODULE_NAME, 0, &instance->config.uptime, "Uptime could't be detected");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t days = (uint32_t) uptime / 86400;
|
||||
uint32_t hours = (uint32_t) (uptime - (days * 86400)) / 3600;
|
||||
uint32_t minutes = (uint32_t) (uptime - (days * 86400) - (hours * 3600)) / 60;
|
||||
uint32_t seconds = (uint32_t) uptime - (days * 86400) - (hours * 3600) - (minutes * 60);
|
||||
|
||||
if(instance->config.uptime.outputFormat.length == 0)
|
||||
{
|
||||
|
||||
@@ -19,16 +19,16 @@ void ffPrintVulkan(FFinstance* instance)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_VULKAN_MODULE_NAME, 0, &instance->config.vulkan.key);
|
||||
|
||||
if(vulkan->driver.length > 0)
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
{
|
||||
printf("%s (driver)", vulkan->driver.chars);
|
||||
ffStrbufWriteTo(&vulkan->apiVersion, stdout);
|
||||
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
fputs(", ", stdout);
|
||||
if(vulkan->driver.length > 0)
|
||||
fputs(" - ", stdout);
|
||||
}
|
||||
|
||||
if(vulkan->apiVersion.length > 0)
|
||||
printf("%s (api version)", vulkan->apiVersion.chars);
|
||||
if(vulkan->driver.length > 0)
|
||||
ffStrbufWriteTo(&vulkan->driver, stdout);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||