From 786b23ef52221fd7444db795d431ef9cb2c57c27 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Jun 2024 14:55:40 +0800 Subject: [PATCH 01/55] Packaging: update debian stuff [ci skip] --- debian/changelog | 6 ++++++ debian/files | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index bd89f89ac..417916b77 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.16.0) jammy; urgency=medium + + * Update to 2.16.0 + + -- Carter Li Wed, 19 Jun 2024 14:53:43 +0800 + fastfetch (2.15.0) jammy; urgency=medium * Update to 2.15.0 diff --git a/debian/files b/debian/files index d6cc5ebae..004f9b053 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.15.0_source.buildinfo universe/utils optional +fastfetch_2.16.0_source.buildinfo universe/utils optional From a8c397969623c0ff840fccf249763d72327f77a3 Mon Sep 17 00:00:00 2001 From: Robin Candau Date: Wed, 19 Jun 2024 09:35:40 +0200 Subject: [PATCH 02/55] Add the missing '--users-myself-only' option in bash completions (#1027) undefined --- completions/fastfetch.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/completions/fastfetch.bash b/completions/fastfetch.bash index 93405ec61..5edb9419f 100644 --- a/completions/fastfetch.bash +++ b/completions/fastfetch.bash @@ -347,6 +347,7 @@ __fastfetch_completion() "--users-key" "--users-format" "--users-key-color" + "--users-myself-only" "--bluetooth-key" "--bluetooth-format" "--bluetooth-key-color" From 067396d3a091e5fe25c8992c6aa55fb9bfbaf6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 09:32:41 +0800 Subject: [PATCH 03/55] CI (Windows): add missing opencl headers --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 023af3321..179b84a7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -494,7 +494,7 @@ jobs: with: msystem: CLANG64 update: true - install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-cppwinrt + install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-opencl-headers mingw-w64-clang-x86_64-cppwinrt - name: print msys version run: uname -a @@ -556,7 +556,7 @@ jobs: with: msystem: CLANG32 update: true - install: git p7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd + install: git p7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd mingw-w64-clang-i686-opencl-headers - name: print msys version run: uname -a From 03e6b47eda512f4fe0630bab6c158299b224402c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 19 Jun 2024 15:40:27 +0800 Subject: [PATCH 04/55] CMake: remove unused dependencies --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 599783cff..5fb2f7de2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1082,7 +1082,6 @@ if(LINUX) ) elseif(APPLE) target_link_libraries(libfastfetch - PRIVATE "resolv" PRIVATE "-framework AVFoundation" PRIVATE "-framework Cocoa" PRIVATE "-framework CoreFoundation" From 96fc1db85e3d2e1636cfcaca85b9debf259f1d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 11:08:26 +0800 Subject: [PATCH 05/55] OpenCL: detect GPU info --- src/detection/opencl/opencl.c | 111 ++++++++++++++++++++++++---------- src/detection/opencl/opencl.h | 3 +- src/modules/opencl/opencl.c | 64 +++++++++++++++++--- 3 files changed, 135 insertions(+), 43 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index f3339bee8..3e4681f1e 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -11,6 +11,7 @@ #include "common/library.h" #include "common/parsing.h" +#include "detection/gpu/gpu.h" #include "util/stringUtils.h" #include @@ -23,50 +24,94 @@ typedef struct OpenCLData { - FF_LIBRARY_SYMBOL(clGetPlatformIDs) - FF_LIBRARY_SYMBOL(clGetDeviceIDs) + FF_LIBRARY_SYMBOL(clGetPlatformInfo) FF_LIBRARY_SYMBOL(clGetDeviceInfo) + FF_LIBRARY_SYMBOL(clGetDeviceIDs) } OpenCLData; static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) { - cl_platform_id platformID = NULL; - cl_uint numPlatforms = 0; - data->ffclGetPlatformIDs(1, &platformID, &numPlatforms); + char buffer[1024] = ""; + if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL) != CL_SUCCESS) + return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed"; - if(numPlatforms == 0) - return "clGetPlatformIDs returned 0 platforms"; + { + const char* versionPretty = buffer; + if(ffStrStartsWithIgnCase(buffer, "OpenCL ")) + versionPretty = buffer + strlen("OpenCL "); + ffStrbufSetS(&result->version, versionPretty); + ffStrbufTrim(&result->version, ' '); + } - cl_device_id deviceID = NULL; - cl_uint numDevices = 0; - data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices); + if (clGetPlatformInfo(NULL, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&result->name, buffer); - if(numDevices == 0) - data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 1, &deviceID, &numDevices); + if (clGetPlatformInfo(NULL, CL_PLATFORM_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&result->vendor, buffer); - if(numDevices == 0) - return "clGetDeviceIDs returned 0 devices"; + cl_device_id deviceIDs[32]; + cl_uint numDevices = (cl_uint) (sizeof(deviceIDs) / sizeof(deviceIDs[0])); + data->ffclGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices); - char version[64] = ""; - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL); - if(!ffStrSet(version)) - return "clGetDeviceInfo returned NULL or empty string"; + for (cl_uint index = 0; index < numDevices; ++index) + { + cl_device_id deviceID = deviceIDs[index]; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(buffer), buffer, NULL) != CL_SUCCESS) + continue; - const char* versionPretty = version; - if(ffStrStartsWithIgnCase(version, "OpenCL ")) - versionPretty = version + strlen("OpenCL "); - ffStrbufSetS(&result->version, versionPretty); - ffStrbufTrim(&result->version, ' '); + FFGPUResult* gpu = ffListAdd(&result->gpus); + ffStrbufInitS(&gpu->name, buffer); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->driver); + ffStrbufInit(&gpu->platformApi); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->deviceId = index + 1; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; - ffStrbufEnsureFree(&result->device, 128); - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, result->device.allocated, result->device.chars, NULL); - ffStrbufRecalculateLength(&result->device); - ffStrbufTrim(&result->device, ' '); + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + ffStrbufSetS(&gpu->platformApi, buffer); + ffStrbufTrimRight(&gpu->platformApi, ' '); + } + else + ffStrbufSetS(&gpu->platformApi, "OpenCL"); - ffStrbufEnsureFree(&result->vendor, 32); - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, result->vendor.allocated, result->vendor.chars, NULL); - ffStrbufRecalculateLength(&result->vendor); - ffStrbufTrim(&result->vendor, ' '); + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&gpu->vendor, buffer); + + if (data->ffclGetDeviceInfo(deviceID, CL_DRIVER_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + const char* versionPretty = strchr(buffer, ' '); + if (versionPretty) + ffStrbufSetS(&gpu->driver, versionPretty + 1); + else + ffStrbufSetS(&gpu->driver, buffer); + } + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->coreCount = (int32_t)*(cl_uint*) buffer; + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->frequency = (*(cl_uint*) buffer) / 1000.; + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->type = *(cl_bool*) buffer == CL_TRUE ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + if (*(cl_device_local_mem_type*) buffer == CL_LOCAL) + { + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->dedicated.total = *(cl_ulong*) buffer; + } + } + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->shared.total = *(cl_ulong*) buffer; + } return NULL; } @@ -85,7 +130,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result) #endif "libOpenCL"FF_LIBRARY_EXTENSION, 1 ); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformInfo); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); @@ -94,7 +139,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result) #elif defined(MACOS_HAS_OPENCL) // FF_HAVE_OPENCL OpenCLData data; - data.ffclGetPlatformIDs = clGetPlatformIDs; + data.ffclGetPlatformInfo = clGetPlatformInfo; data.ffclGetDeviceIDs = clGetDeviceIDs; data.ffclGetDeviceInfo = clGetDeviceInfo; diff --git a/src/detection/opencl/opencl.h b/src/detection/opencl/opencl.h index 5daaacbda..0274b37b4 100644 --- a/src/detection/opencl/opencl.h +++ b/src/detection/opencl/opencl.h @@ -5,8 +5,9 @@ typedef struct FFOpenCLResult { FFstrbuf version; - FFstrbuf device; + FFstrbuf name; FFstrbuf vendor; + FFlist gpus; //List of FFGPUResult, see detection/gpu/gpu.h } FFOpenCLResult; const char* ffDetectOpenCL(FFOpenCLResult* result); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 3a2135185..641122ef1 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -1,6 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" #include "detection/opencl/opencl.h" +#include "detection/gpu/gpu.h" #include "modules/opencl/opencl.h" #include "util/stringUtils.h" @@ -10,8 +11,9 @@ void ffPrintOpenCL(FFOpenCLOptions* options) { FFOpenCLResult opencl; ffStrbufInit(&opencl.version); - ffStrbufInit(&opencl.device); + ffStrbufInit(&opencl.name); ffStrbufInit(&opencl.vendor); + ffListInit(&opencl.gpus, sizeof(FFGPUResult)); const char* error = ffDetectOpenCL(&opencl); @@ -28,14 +30,14 @@ void ffPrintOpenCL(FFOpenCLOptions* options) { FF_PRINT_FORMAT_CHECKED(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_OPENCL_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.version, "version"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.device, "device"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.name, "name"}, {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.vendor, "vendor"}, })); } } ffStrbufDestroy(&opencl.version); - ffStrbufDestroy(&opencl.device); + ffStrbufDestroy(&opencl.name); ffStrbufDestroy(&opencl.vendor); } @@ -78,8 +80,9 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson { FFOpenCLResult opencl; ffStrbufInit(&opencl.version); - ffStrbufInit(&opencl.device); + ffStrbufInit(&opencl.name); ffStrbufInit(&opencl.vendor); + ffListInit(&opencl.gpus, sizeof(FFGPUResult)); const char* error = ffDetectOpenCL(&opencl); @@ -91,21 +94,64 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson { yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "version", &opencl.version); - yyjson_mut_obj_add_strbuf(doc, obj, "device", &opencl.device); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &opencl.name); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &opencl.vendor); + + yyjson_mut_val* gpus = yyjson_mut_obj_add_arr(doc, obj, "gpus"); + FF_LIST_FOR_EACH(FFGPUResult, gpu, opencl.gpus) + { + yyjson_mut_val* gpuObj = yyjson_mut_arr_add_obj(doc, gpus); + yyjson_mut_obj_add_str(doc, gpuObj, "type", gpu->type == FF_GPU_TYPE_UNKNOWN ? "Unknown" : gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete"); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &gpu->vendor); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &gpu->name); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &gpu->driver); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &gpu->platformApi); + yyjson_mut_obj_add_int(doc, gpuObj, "coreCount", gpu->coreCount); + yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency); + + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); + + { + yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); + if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "total"); + + if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "used"); + } + + { + yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); + if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "total", gpu->shared.total); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "total"); + + if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "used", gpu->shared.used); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "used"); + } + + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", gpu->deviceId); + } } ffStrbufDestroy(&opencl.version); - ffStrbufDestroy(&opencl.device); + ffStrbufDestroy(&opencl.name); ffStrbufDestroy(&opencl.vendor); } void ffPrintOpenCLHelpFormat(void) { FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_OPENCL_MODULE_NAME, "{1}", FF_OPENCL_NUM_FORMAT_ARGS, ((const char* []) { - "version - version", - "device - device", - "vendor - vendor" + "Platform version - version", + "Platform name - name", + "Platform vendor - vendor", })); } From 6737896038217924e9cd0bc3cf1f67b68627676e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 11:09:01 +0800 Subject: [PATCH 06/55] CMake: enable OpenCL detection on Android doesn't work on my smartphone --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fb2f7de2..15e0de82e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENAB cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD OR SunOS" OFF) cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD OR SunOS" OFF) cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR ANDROID OR SunOS" OFF) cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF) From 6318668d0bc71d4c0a7a5d1a4812457a763f156d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 14:05:38 +0800 Subject: [PATCH 07/55] GPU: support detect gpu devices with OpenCL --- doc/json_schema.json | 1 + src/data/help.json | 3 +- src/detection/gpu/gpu.c | 11 +++ src/detection/opencl/opencl.c | 54 ++++++++----- src/detection/opencl/opencl.h | 3 +- src/modules/gpu/gpu.c | 5 ++ src/modules/gpu/option.h | 1 + src/modules/opencl/opencl.c | 148 +++++++++++++++------------------- 8 files changed, 119 insertions(+), 107 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index cdcfd736f..d03d1b5fa 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1523,6 +1523,7 @@ "auto", "pci", "vulkan", + "opencl", "opengl" ], "default": "auto" diff --git a/src/data/help.json b/src/data/help.json index 4dcdae17b..eec3b5795 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1251,7 +1251,8 @@ "enum": { "auto": "Query platform specific graphic APIs. Requires proper GPU drivers installed. Not supported on FreeBSD", "pci": "Search PCI devices, which do not requires GPU driver installed. Not supported on Windows and macOS", - "vulkan": "Use Vulkan API. Slow and requires vulkan driver installed. Used for Android", + "vulkan": "Use Vulkan API. Slow and requires proper vulkan driver installed. Used for Android", + "opencl": "Use OpenCL API. Slow and requires proper OpenCL driver installed", "opengl": "Use OpenGL API. Slow and only detects one GPU" }, "default": "auto" diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index b75ac7679..70eac725b 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -1,5 +1,6 @@ #include "gpu.h" #include "detection/vulkan/vulkan.h" +#include "detection/opencl/opencl.h" #include "detection/opengl/opengl.h" const char* FF_GPU_VENDOR_NAME_APPLE = "Apple"; @@ -94,6 +95,16 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) return NULL; } } + if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENCL) + { + FFOpenCLResult* opencl = ffDetectOpenCL(); + if (!opencl->error && opencl->gpus.length > 0) + { + ffListDestroy(result); + ffListInitMove(result, &opencl->gpus); + return NULL; + } + } if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL) { if (detectByOpenGL(result) == NULL) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 3e4681f1e..6b97479de 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -1,13 +1,10 @@ #include "detection/opencl/opencl.h" -#ifdef __APPLE__ -#include -#if (MAC_OS_X_VERSION_MIN_REQUIRED > 1050) && !defined(__ppc__) -#define MACOS_HAS_OPENCL -#endif +#if !defined(FF_HAVE_OPENCL) && defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_15) + #define FF_HAVE_OPENCL 1 #endif -#if defined(FF_HAVE_OPENCL) || defined(MACOS_HAS_OPENCL) +#ifdef FF_HAVE_OPENCL #include "common/library.h" #include "common/parsing.h" @@ -16,7 +13,7 @@ #include #define CL_TARGET_OPENCL_VERSION 100 -#ifdef FF_HAVE_OPENCL +#ifndef __APPLE__ #include #else #include @@ -116,15 +113,13 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) return NULL; } -#endif // defined(FF_HAVE_OPENCL) || defined(MACOS_HAS_OPENCL) - -const char* ffDetectOpenCL(FFOpenCLResult* result) +static const char* detectOpenCL(FFOpenCLResult* result) { - #ifdef FF_HAVE_OPENCL - OpenCLData data; - FF_LIBRARY_LOAD(opencl, &instance.config.library.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", + #ifndef __APPLE__ + + FF_LIBRARY_LOAD(opencl, &instance.config.library.libOpenCL, "dlopen libOpenCL" FF_LIBRARY_EXTENSION" failed", #ifdef _WIN32 "OpenCL"FF_LIBRARY_EXTENSION, -1, #endif @@ -136,19 +131,36 @@ const char* ffDetectOpenCL(FFOpenCLResult* result) return openCLHandleData(&data, result); - #elif defined(MACOS_HAS_OPENCL) // FF_HAVE_OPENCL + #else - OpenCLData data; data.ffclGetPlatformInfo = clGetPlatformInfo; data.ffclGetDeviceIDs = clGetDeviceIDs; data.ffclGetDeviceInfo = clGetDeviceInfo; return openCLHandleData(&data, result); - #else - - FF_UNUSED(result); - return "Fastfetch was build without OpenCL support"; - - #endif // FF_HAVE_OPENCL + #endif +} + +#endif // defined(FF_HAVE_OPENCL) + +FFOpenCLResult* ffDetectOpenCL(void) +{ + static FFOpenCLResult result; + + if (result.gpus.elementSize == 0) + { + ffStrbufInit(&result.version); + ffStrbufInit(&result.name); + ffStrbufInit(&result.vendor); + ffListInit(&result.gpus, sizeof(FFGPUResult)); + + #ifdef FF_HAVE_OPENCL + result.error = detectOpenCL(&result); + #else + result.error = "fastfetch was compiled without OpenCL support"; + #endif + } + + return &result; } diff --git a/src/detection/opencl/opencl.h b/src/detection/opencl/opencl.h index 0274b37b4..a8b0063e4 100644 --- a/src/detection/opencl/opencl.h +++ b/src/detection/opencl/opencl.h @@ -8,6 +8,7 @@ typedef struct FFOpenCLResult FFstrbuf name; FFstrbuf vendor; FFlist gpus; //List of FFGPUResult, see detection/gpu/gpu.h + const char* error; } FFOpenCLResult; -const char* ffDetectOpenCL(FFOpenCLResult* result); +FFOpenCLResult* ffDetectOpenCL(); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 2e59cabad..0ad3ab447 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -150,6 +150,7 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char { "auto", FF_GPU_DETECTION_METHOD_AUTO }, { "pci", FF_GPU_DETECTION_METHOD_PCI }, { "vulkan", FF_GPU_DETECTION_METHOD_VULKAN }, + { "opencl", FF_GPU_DETECTION_METHOD_OPENCL }, { "opengl", FF_GPU_DETECTION_METHOD_OPENGL }, {}, }); @@ -204,6 +205,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { "auto", FF_GPU_DETECTION_METHOD_AUTO }, { "pci", FF_GPU_DETECTION_METHOD_PCI }, { "vulkan", FF_GPU_DETECTION_METHOD_VULKAN }, + { "opencl", FF_GPU_DETECTION_METHOD_OPENCL }, { "opengl", FF_GPU_DETECTION_METHOD_OPENGL }, {}, }); @@ -260,6 +262,9 @@ void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ case FF_GPU_DETECTION_METHOD_VULKAN: yyjson_mut_obj_add_str(doc, module, "detectionMethod", "vulkan"); break; + case FF_GPU_DETECTION_METHOD_OPENCL: + yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opencl"); + break; case FF_GPU_DETECTION_METHOD_OPENGL: yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opengl"); break; diff --git a/src/modules/gpu/option.h b/src/modules/gpu/option.h index 405b7b11e..5f53d2f6f 100644 --- a/src/modules/gpu/option.h +++ b/src/modules/gpu/option.h @@ -17,6 +17,7 @@ typedef enum FFGPUDetectionMethod FF_GPU_DETECTION_METHOD_AUTO, FF_GPU_DETECTION_METHOD_PCI, FF_GPU_DETECTION_METHOD_VULKAN, + FF_GPU_DETECTION_METHOD_OPENCL, FF_GPU_DETECTION_METHOD_OPENGL, } FFGPUDetectionMethod; diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 641122ef1..5eabe30de 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -9,36 +9,27 @@ void ffPrintOpenCL(FFOpenCLOptions* options) { - FFOpenCLResult opencl; - ffStrbufInit(&opencl.version); - ffStrbufInit(&opencl.name); - ffStrbufInit(&opencl.vendor); - ffListInit(&opencl.gpus, sizeof(FFGPUResult)); + FFOpenCLResult* result = ffDetectOpenCL(); - const char* error = ffDetectOpenCL(&opencl); - - if(error != NULL) - ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); - else + if(result->error != NULL) { - if(options->moduleArgs.outputFormat.length == 0) - { - ffPrintLogoAndKey(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufPutTo(&opencl.version, stdout); - } - else - { - FF_PRINT_FORMAT_CHECKED(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_OPENCL_NUM_FORMAT_ARGS, ((FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.version, "version"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.name, "name"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.vendor, "vendor"}, - })); - } + ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result->error); + return; } - ffStrbufDestroy(&opencl.version); - ffStrbufDestroy(&opencl.name); - ffStrbufDestroy(&opencl.vendor); + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&result->version, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_OPENCL_NUM_FORMAT_ARGS, ((FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &result->version, "version"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result->name, "name"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result->vendor, "vendor"}, + })); + } } bool ffParseOpenCLCommandOptions(FFOpenCLOptions* options, const char* key, const char* value) @@ -78,72 +69,61 @@ void ffGenerateOpenCLJsonConfig(FFOpenCLOptions* options, yyjson_mut_doc* doc, y void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - FFOpenCLResult opencl; - ffStrbufInit(&opencl.version); - ffStrbufInit(&opencl.name); - ffStrbufInit(&opencl.vendor); - ffListInit(&opencl.gpus, sizeof(FFGPUResult)); + FFOpenCLResult* result = ffDetectOpenCL(); - const char* error = ffDetectOpenCL(&opencl); - - if(error != NULL) + if(result->error != NULL) { - yyjson_mut_obj_add_str(doc, module, "error", error); + yyjson_mut_obj_add_str(doc, module, "error", result->error); + return; } - else - { - yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); - yyjson_mut_obj_add_strbuf(doc, obj, "version", &opencl.version); - yyjson_mut_obj_add_strbuf(doc, obj, "name", &opencl.name); - yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &opencl.vendor); - yyjson_mut_val* gpus = yyjson_mut_obj_add_arr(doc, obj, "gpus"); - FF_LIST_FOR_EACH(FFGPUResult, gpu, opencl.gpus) + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->version); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &result->name); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result->vendor); + + yyjson_mut_val* gpus = yyjson_mut_obj_add_arr(doc, obj, "gpus"); + FF_LIST_FOR_EACH(FFGPUResult, gpu, result->gpus) + { + yyjson_mut_val* gpuObj = yyjson_mut_arr_add_obj(doc, gpus); + yyjson_mut_obj_add_str(doc, gpuObj, "type", gpu->type == FF_GPU_TYPE_UNKNOWN ? "Unknown" : gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete"); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &gpu->vendor); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &gpu->name); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &gpu->driver); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &gpu->platformApi); + yyjson_mut_obj_add_int(doc, gpuObj, "coreCount", gpu->coreCount); + yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency); + + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); + { - yyjson_mut_val* gpuObj = yyjson_mut_arr_add_obj(doc, gpus); - yyjson_mut_obj_add_str(doc, gpuObj, "type", gpu->type == FF_GPU_TYPE_UNKNOWN ? "Unknown" : gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete"); - yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &gpu->vendor); - yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &gpu->name); - yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &gpu->driver); - yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &gpu->platformApi); - yyjson_mut_obj_add_int(doc, gpuObj, "coreCount", gpu->coreCount); - yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency); + yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); + if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "total"); - yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); - - { - yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); - if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) - yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", gpu->dedicated.total); - else - yyjson_mut_obj_add_null(doc, dedicatedMemory, "total"); - - if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) - yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", gpu->dedicated.total); - else - yyjson_mut_obj_add_null(doc, dedicatedMemory, "used"); - } - - { - yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); - if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) - yyjson_mut_obj_add_uint(doc, sharedMemory, "total", gpu->shared.total); - else - yyjson_mut_obj_add_null(doc, sharedMemory, "total"); - - if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) - yyjson_mut_obj_add_uint(doc, sharedMemory, "used", gpu->shared.used); - else - yyjson_mut_obj_add_null(doc, sharedMemory, "used"); - } - - yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", gpu->deviceId); + if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "used"); } - } - ffStrbufDestroy(&opencl.version); - ffStrbufDestroy(&opencl.name); - ffStrbufDestroy(&opencl.vendor); + { + yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); + if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "total", gpu->shared.total); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "total"); + + if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "used", gpu->shared.used); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "used"); + } + + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", gpu->deviceId); + } } void ffPrintOpenCLHelpFormat(void) From 3c7cb339e21e4253febc509910c88fb31223cd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 14:58:15 +0800 Subject: [PATCH 08/55] OpenCL: fix building on non-apple platforms --- src/detection/opencl/opencl.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 6b97479de..01c8a4c09 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -12,7 +12,7 @@ #include "util/stringUtils.h" #include -#define CL_TARGET_OPENCL_VERSION 100 +#define CL_TARGET_OPENCL_VERSION 110 #ifndef __APPLE__ #include #else @@ -29,8 +29,21 @@ typedef struct OpenCLData static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) { char buffer[1024] = ""; - if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL) != CL_SUCCESS) - return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed"; + cl_int res = data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL); + if (res != CL_SUCCESS) + { + switch (res) + { + case CL_INVALID_PLATFORM: + return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: CL_INVALID_PLATFORM"; + case CL_INVALID_VALUE: + return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: CL_INVALID_VALUE"; + case CL_OUT_OF_HOST_MEMORY: + return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: CL_OUT_OF_HOST_MEMORY"; + default: + return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: unknown error"; + } + } { const char* versionPretty = buffer; @@ -40,10 +53,10 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) ffStrbufTrim(&result->version, ' '); } - if (clGetPlatformInfo(NULL, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL) == CL_SUCCESS) ffStrbufSetS(&result->name, buffer); - if (clGetPlatformInfo(NULL, CL_PLATFORM_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) ffStrbufSetS(&result->vendor, buffer); cl_device_id deviceIDs[32]; From 146c9b2bc6de247ec0c0310c8ccb71459a102c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 15:34:09 +0800 Subject: [PATCH 09/55] OpenCL: fix building when OpenCL is disabled --- src/detection/opencl/opencl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 01c8a4c09..83d287afd 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -1,4 +1,5 @@ #include "detection/opencl/opencl.h" +#include "detection/gpu/gpu.h" #if !defined(FF_HAVE_OPENCL) && defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_15) #define FF_HAVE_OPENCL 1 @@ -8,7 +9,6 @@ #include "common/library.h" #include "common/parsing.h" -#include "detection/gpu/gpu.h" #include "util/stringUtils.h" #include From 8b3cff33dab0329072805530ab526b816f1e05ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 15:54:08 +0800 Subject: [PATCH 10/55] OpenCL: use strong typing --- src/detection/opencl/opencl.c | 49 +++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 83d287afd..d783eb381 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -87,7 +87,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) ffStrbufTrimRight(&gpu->platformApi, ' '); } else - ffStrbufSetS(&gpu->platformApi, "OpenCL"); + ffStrbufSetStatic(&gpu->platformApi, "OpenCL"); if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) ffStrbufSetS(&gpu->vendor, buffer); @@ -95,32 +95,47 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) if (data->ffclGetDeviceInfo(deviceID, CL_DRIVER_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) { const char* versionPretty = strchr(buffer, ' '); - if (versionPretty) + if (versionPretty && *versionPretty) ffStrbufSetS(&gpu->driver, versionPretty + 1); else ffStrbufSetS(&gpu->driver, buffer); } - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - gpu->coreCount = (int32_t)*(cl_uint*) buffer; - - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - gpu->frequency = (*(cl_uint*) buffer) / 1000.; - - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - gpu->type = *(cl_bool*) buffer == CL_TRUE ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) { - if (*(cl_device_local_mem_type*) buffer == CL_LOCAL) + cl_uint value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(value), &value, NULL) == CL_SUCCESS) + gpu->coreCount = (int32_t) value; + } + + { + cl_uint value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(value), &value, NULL) == CL_SUCCESS) + gpu->frequency = value / 1000.; + } + + { + cl_bool value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(value), &value, NULL) == CL_SUCCESS) + gpu->type = value ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + } + + { + cl_device_local_mem_type memType; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(memType), &memType, NULL) == CL_SUCCESS && memType == CL_LOCAL) { - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - gpu->dedicated.total = *(cl_ulong*) buffer; + cl_ulong value; + // 32 KiB is the minimum value required by OpenCL spec, don't use it + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(value), &value, NULL) == CL_SUCCESS && value > 32 * 1024) + gpu->dedicated.total = value; } } - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - gpu->shared.total = *(cl_ulong*) buffer; + { + cl_ulong value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(value), &value, NULL) == CL_SUCCESS) + gpu->shared.total = value; + + } } return NULL; From dbd1f9635376c604c7f2b0c4f08fc8e4462807c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 19:44:08 +0800 Subject: [PATCH 11/55] OpenCL: don't use NULL as platform id --- src/detection/opencl/opencl.c | 186 +++++++++++++++++----------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index d783eb381..3432665d4 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -21,6 +21,7 @@ typedef struct OpenCLData { + FF_LIBRARY_SYMBOL(clGetPlatformIDs) FF_LIBRARY_SYMBOL(clGetPlatformInfo) FF_LIBRARY_SYMBOL(clGetDeviceInfo) FF_LIBRARY_SYMBOL(clGetDeviceIDs) @@ -28,113 +29,110 @@ typedef struct OpenCLData static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) { - char buffer[1024] = ""; - cl_int res = data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL); - if (res != CL_SUCCESS) + cl_platform_id platforms[32]; + cl_uint numPlatforms = 0; + if (data->ffclGetPlatformIDs(sizeof(platforms) / sizeof(platforms[0]), platforms, &numPlatforms) != CL_SUCCESS) + return "clGetPlatformIDs() failed"; + + if (numPlatforms == 0) + return "clGetPlatformIDs returned 0 platforms"; + + char buffer[1024]; + for (cl_uint iplat = 0; iplat < numPlatforms; ++iplat) { - switch (res) + if (data->ffclGetPlatformInfo(platforms[iplat], CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL) != CL_SUCCESS) + return "clGetPlatformInfo() failed"; + + if (iplat == 0) { - case CL_INVALID_PLATFORM: - return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: CL_INVALID_PLATFORM"; - case CL_INVALID_VALUE: - return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: CL_INVALID_VALUE"; - case CL_OUT_OF_HOST_MEMORY: - return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: CL_OUT_OF_HOST_MEMORY"; - default: - return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed: unknown error"; - } - } + const char* versionPretty = buffer; + if(ffStrStartsWithIgnCase(buffer, "OpenCL ")) + versionPretty = buffer + strlen("OpenCL "); + ffStrbufSetS(&result->version, versionPretty); + ffStrbufTrim(&result->version, ' '); - { - const char* versionPretty = buffer; - if(ffStrStartsWithIgnCase(buffer, "OpenCL ")) - versionPretty = buffer + strlen("OpenCL "); - ffStrbufSetS(&result->version, versionPretty); - ffStrbufTrim(&result->version, ' '); - } + if (data->ffclGetPlatformInfo(platforms[iplat], CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&result->name, buffer); - if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - ffStrbufSetS(&result->name, buffer); - - if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - ffStrbufSetS(&result->vendor, buffer); - - cl_device_id deviceIDs[32]; - cl_uint numDevices = (cl_uint) (sizeof(deviceIDs) / sizeof(deviceIDs[0])); - data->ffclGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices); - - for (cl_uint index = 0; index < numDevices; ++index) - { - cl_device_id deviceID = deviceIDs[index]; - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(buffer), buffer, NULL) != CL_SUCCESS) - continue; - - FFGPUResult* gpu = ffListAdd(&result->gpus); - ffStrbufInitS(&gpu->name, buffer); - ffStrbufInit(&gpu->vendor); - ffStrbufInit(&gpu->driver); - ffStrbufInit(&gpu->platformApi); - gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; - gpu->type = FF_GPU_TYPE_UNKNOWN; - gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->deviceId = index + 1; - gpu->frequency = FF_GPU_FREQUENCY_UNSET; - - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - { - ffStrbufSetS(&gpu->platformApi, buffer); - ffStrbufTrimRight(&gpu->platformApi, ' '); - } - else - ffStrbufSetStatic(&gpu->platformApi, "OpenCL"); - - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - ffStrbufSetS(&gpu->vendor, buffer); - - if (data->ffclGetDeviceInfo(deviceID, CL_DRIVER_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) - { - const char* versionPretty = strchr(buffer, ' '); - if (versionPretty && *versionPretty) - ffStrbufSetS(&gpu->driver, versionPretty + 1); - else - ffStrbufSetS(&gpu->driver, buffer); + if (data->ffclGetPlatformInfo(platforms[iplat], CL_PLATFORM_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&result->vendor, buffer); } - { - cl_uint value; - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(value), &value, NULL) == CL_SUCCESS) - gpu->coreCount = (int32_t) value; - } + cl_device_id deviceIDs[32]; + cl_uint numDevices = (cl_uint) (sizeof(deviceIDs) / sizeof(deviceIDs[0])); + data->ffclGetDeviceIDs(platforms[iplat], CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices); + for (cl_uint idev = 0; idev < numDevices; ++idev) { - cl_uint value; - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(value), &value, NULL) == CL_SUCCESS) - gpu->frequency = value / 1000.; - } + cl_device_id deviceID = deviceIDs[idev]; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(buffer), buffer, NULL) != CL_SUCCESS) + continue; - { - cl_bool value; - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(value), &value, NULL) == CL_SUCCESS) - gpu->type = value ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - } + FFGPUResult* gpu = ffListAdd(&result->gpus); + ffStrbufInitS(&gpu->name, buffer); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->driver); + ffStrbufInit(&gpu->platformApi); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->deviceId = 0; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; - { - cl_device_local_mem_type memType; - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(memType), &memType, NULL) == CL_SUCCESS && memType == CL_LOCAL) + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) { - cl_ulong value; - // 32 KiB is the minimum value required by OpenCL spec, don't use it - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(value), &value, NULL) == CL_SUCCESS && value > 32 * 1024) - gpu->dedicated.total = value; + ffStrbufSetS(&gpu->platformApi, buffer); + ffStrbufTrimRight(&gpu->platformApi, ' '); } - } + else + ffStrbufSetStatic(&gpu->platformApi, "OpenCL"); - { - cl_ulong value; - if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(value), &value, NULL) == CL_SUCCESS) - gpu->shared.total = value; + { + cl_uint vendorId; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR_ID, sizeof(vendorId), &vendorId, NULL) == CL_SUCCESS) + ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); + if (gpu->vendor.length == 0 && data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&gpu->vendor, buffer); + } + if (data->ffclGetDeviceInfo(deviceID, CL_DRIVER_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + const char* versionPretty = strchr(buffer, ' '); + if (versionPretty && *versionPretty) + ffStrbufSetS(&gpu->driver, versionPretty + 1); + else + ffStrbufSetS(&gpu->driver, buffer); + } + + { + cl_uint value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(value), &value, NULL) == CL_SUCCESS) + gpu->coreCount = (int32_t) value; + } + + { + cl_uint value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(value), &value, NULL) == CL_SUCCESS) + gpu->frequency = value / 1000.; + } + + { + cl_bool value; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(value), &value, NULL) == CL_SUCCESS) + { + gpu->type = value ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + + cl_ulong memSize; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(memSize), &memSize, NULL) == CL_SUCCESS) + { + if (gpu->type == FF_GPU_TYPE_INTEGRATED) + gpu->shared.total = memSize; + else + gpu->dedicated.total = memSize; + } + } + } } } @@ -153,6 +151,7 @@ static const char* detectOpenCL(FFOpenCLResult* result) #endif "libOpenCL"FF_LIBRARY_EXTENSION, 1 ); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformInfo); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); @@ -161,6 +160,7 @@ static const char* detectOpenCL(FFOpenCLResult* result) #else + data.ffclGetPlatformIDs = clGetPlatformIDs; data.ffclGetPlatformInfo = clGetPlatformInfo; data.ffclGetDeviceIDs = clGetDeviceIDs; data.ffclGetDeviceInfo = clGetDeviceInfo; From bf15adf57af3664a8dc2173689cde35167a14598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 21 Jun 2024 08:45:21 +0800 Subject: [PATCH 12/55] OpenCL (Linux): fix crashing on AlpineLinux --- src/detection/opencl/opencl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 3432665d4..17dfabc88 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -60,7 +60,8 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) cl_device_id deviceIDs[32]; cl_uint numDevices = (cl_uint) (sizeof(deviceIDs) / sizeof(deviceIDs[0])); - data->ffclGetDeviceIDs(platforms[iplat], CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices); + if (data->ffclGetDeviceIDs(platforms[iplat], CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices) != CL_SUCCESS) + continue; for (cl_uint idev = 0; idev < numDevices; ++idev) { From 16d70eed0304b351d96a13e2774d1d808caec6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 21 Jun 2024 08:57:08 +0800 Subject: [PATCH 13/55] GPU: report `deviceId` in JSON output --- src/detection/opencl/opencl.c | 2 +- src/modules/gpu/gpu.c | 7 +++---- src/modules/opencl/opencl.c | 6 +++++- src/modules/vulkan/vulkan.c | 1 + 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 17dfabc88..ed71afca0 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -78,7 +78,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->deviceId = 0; + gpu->deviceId = (size_t) deviceID; gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 0ad3ab447..002c3d7fb 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -355,10 +355,9 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi); - if (gpu->frequency == FF_GPU_FREQUENCY_UNSET) - yyjson_mut_obj_add_null(doc, obj, "frequency"); - else - yyjson_mut_obj_add_real(doc, obj, "frequency", gpu->frequency); + yyjson_mut_obj_add_real(doc, obj, "frequency", gpu->frequency); // NaN will be output as "null" + + yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId); } FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 5eabe30de..a74328661 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -91,7 +91,11 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &gpu->name); yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &gpu->driver); yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &gpu->platformApi); - yyjson_mut_obj_add_int(doc, gpuObj, "coreCount", gpu->coreCount); + if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) + yyjson_mut_obj_add_int(doc, gpuObj, "coreCount", gpu->coreCount); + else + yyjson_mut_obj_add_null(doc, gpuObj, "coreCount"); + yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency); yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 7bb57300b..64d63d52e 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -110,6 +110,7 @@ void ffGenerateVulkanJsonResult(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &vulkanGpu->name); yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &vulkanGpu->driver); yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &vulkanGpu->platformApi); + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->deviceId); yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); From ddbafd1ccaad67265b934d1044dddb457ebd4273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 21 Jun 2024 09:18:08 +0800 Subject: [PATCH 14/55] OpenCL: use the newest supported OpenCL version --- src/detection/opencl/opencl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index ed71afca0..0626dd4d3 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -43,7 +43,8 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) if (data->ffclGetPlatformInfo(platforms[iplat], CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL) != CL_SUCCESS) return "clGetPlatformInfo() failed"; - if (iplat == 0) + // Use the newest supported OpenCL version + if (ffStrbufCompS(&result->version, buffer) < 0) { const char* versionPretty = buffer; if(ffStrStartsWithIgnCase(buffer, "OpenCL ")) From 31859699741228814d19b00d4e54d37404420479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 21 Jun 2024 09:43:18 +0800 Subject: [PATCH 15/55] CMake (Windows): install `libffwinrt.dll` --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15e0de82e..e6388cf2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1266,6 +1266,13 @@ install( DESTINATION "${CMAKE_INSTALL_BINDIR}" ) +if (TARGET ffwinrt) + install( + TARGETS ffwinrt + DESTINATION "${CMAKE_INSTALL_BINDIR}" + ) +endif() + install( FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.bash" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions" From 672604081a67a3785dff3cadd7010b4f7c2d8ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 21 Jun 2024 10:05:54 +0800 Subject: [PATCH 16/55] Doc: update json_schema [ci skip] --- doc/json_schema.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index d03d1b5fa..146a1822d 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -23,7 +23,7 @@ "default": 0 }, "format": { - "description": "Output format of the module. See `-h <module>-format` for detail", + "description": "Output format of the module. See `-h module-format` for detail", "type": "string" }, "outputColor": { @@ -89,10 +89,12 @@ "default": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json" }, "logo": { + "description": "Fastfetch logo configurations\nSee also https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options", "oneOf": [ { "description": "Disable logo", - "type": "null" + "type": "null", + "const": null }, { "description": "Set the source file of the logo", From becd9b7f26ecc6c6aa217b408b77a76b4a2d2f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 21 Jun 2024 20:27:22 +0800 Subject: [PATCH 17/55] LM (Linux): fix invalid path Fix #1031 --- src/detection/lm/lm_linux.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index a792da592..4adc9ec82 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -6,7 +6,7 @@ #include -#define FF_SYSTEMD_SESSIONS_PATH "/var/run/systemd/sessions/" +#define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" #define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" static const char* getGdmVersion(FFstrbuf* version) @@ -143,7 +143,7 @@ const char* ffDetectLM(FFLMResult* result) { // On some incorrectly configured systems, $XDG_SESSION_ID is not set. Try finding it ourself // WARNING: This is private data. Do not parse - ffStrbufAppendF(&path, "/run/systemd/users/%d", getuid()); + ffStrbufSetF(&path, FF_SYSTEMD_USERS_PATH "%d", getuid()); // This is actually buggy, and assumes current user is using DE // `sd_pid_get_session` can be a better option, but we need to find a pid to use @@ -151,10 +151,9 @@ const char* ffDetectLM(FFLMResult* result) {"DISPLAY=", &sessionId}, })) return "Failed to get $XDG_SESSION_ID"; - ffStrbufClear(&path); } - ffStrbufAppendS(&path, "/var/run/systemd/sessions/"); + ffStrbufSetS(&path, FF_SYSTEMD_SESSIONS_PATH); ffStrbufAppend(&path, &sessionId); // WARNING: This is private data. Do not parse @@ -162,7 +161,7 @@ const char* ffDetectLM(FFLMResult* result) {"SERVICE=", &result->service}, {"TYPE=", &result->type}, })) - return "Failed to parse /run/systemd/sessions/$XDG_SESSION_ID"; + return "Failed to parse " FF_SYSTEMD_SESSIONS_PATH "$XDG_SESSION_ID"; if (ffStrbufStartsWithS(&result->service, "gdm")) getGdmVersion(&result->version); From edf24d982023a7e6a05a48a2b31be54de3b916a5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Jun 2024 15:21:55 +0800 Subject: [PATCH 18/55] CPUCache: add detection by SMBIOS --- CMakeLists.txt | 4 +- src/detection/battery/battery_windows.c | 2 +- src/detection/cpucache/cpucache_shared.c | 75 ++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/detection/cpucache/cpucache_shared.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e6388cf2d..fa526f990 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -549,7 +549,7 @@ elseif(BSD) src/detection/brightness/brightness_bsd.c src/detection/chassis/chassis_bsd.c src/detection/cpu/cpu_bsd.c - src/detection/cpucache/cpucache_nosupport.c + src/detection/cpucache/cpucache_shared.c src/detection/cpuusage/cpuusage_bsd.c src/detection/cursor/cursor_linux.c src/detection/disk/disk_bsd.c @@ -749,7 +749,7 @@ elseif(SunOS) src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_windows.c src/detection/cpu/cpu_sunos.c - src/detection/cpucache/cpucache_nosupport.c + src/detection/cpucache/cpucache_shared.c src/detection/cpuusage/cpuusage_sunos.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_nosupport.c diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 1d507c8c6..6c7298231 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -172,7 +172,7 @@ typedef struct FFSmbiosPortableBattery static_assert(offsetof(FFSmbiosPortableBattery, OEMSpecific) == 0x16, "FFSmbiosPortableBattery: Wrong struct alignment"); -const char* detectBySmbios(FFBatteryResult* battery) +static const char* detectBySmbios(FFBatteryResult* battery) { const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); if (!smbiosTable) diff --git a/src/detection/cpucache/cpucache_shared.c b/src/detection/cpucache/cpucache_shared.c new file mode 100644 index 000000000..abf0e9474 --- /dev/null +++ b/src/detection/cpucache/cpucache_shared.c @@ -0,0 +1,75 @@ +#include "cpucache.h" +#include "util/smbiosHelper.h" +#include "util/stringUtils.h" + +typedef struct FFSmbiosCacheInfo +{ + FFSmbiosHeader Header; + + uint8_t SocketDesignation; // string + uint16_t CacheConfiguration; // varies + uint16_t MaximumCacheSize; // varies + uint16_t InstalledSize; // varies + uint16_t SupportedSramType; // bit field + uint16_t CurrentSramType; // bit field + + // 2.1+ + uint8_t CacheSpeed; // varies + uint8_t ErrorCorrectionType; // enum + uint8_t SystemCacheType; // enum + uint8_t Associativity; // enum + + // 3.1+ + uint32_t MaximumCacheSize2; // bit field + uint32_t InstalledCacheSize2; // bit field +} __attribute__((__packed__)) FFSmbiosCacheInfo; + +static_assert(offsetof(FFSmbiosCacheInfo, InstalledCacheSize2) == 0x17, + "FFSmbiosCacheInfo: Wrong struct alignment"); + +const char* ffDetectCPUCache(FFCPUCacheResult* result) +{ + const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); + if (!smbiosTable) + return "Failed to get SMBIOS data"; + + const FFSmbiosCacheInfo* data = (const FFSmbiosCacheInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_CACHE_INFO]; + if (!data) + return "Cache information is not found in SMBIOS data"; + + for (; data->Header.Type == FF_SMBIOS_TYPE_CACHE_INFO; + data = (const FFSmbiosCacheInfo*) ffSmbiosNextEntry(&data->Header)) + { + bool enabled = !!(data->CacheConfiguration & (1 << 7)); + if (!enabled) + continue; + + uint32_t size = data->InstalledSize; + if (size == 0) + continue; + + if (data->InstalledSize != 0xFFFF) + { + size *= (size >> 15 ? 64 : 1) * 1024u; + } + else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2)) + { + size = data->InstalledCacheSize2; + size *= (size >> 31 ? 64 : 1) * 1024u; + } + + uint32_t level = (data->CacheConfiguration & 0b111u) + 1; + + FFCPUCacheType type; + switch (data->SystemCacheType) + { + case 3: type = FF_CPU_CACHE_TYPE_INSTRUCTION; break; + case 4: type = FF_CPU_CACHE_TYPE_DATA; break; + default: type = FF_CPU_CACHE_TYPE_UNIFIED; break; + } + + ffCPUCacheAddItem(result, level, size, 0, type); + } + + return NULL; +} From 63cdc47d1839189daf04120560f4e3d50f0d3c2d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Jun 2024 23:29:08 +0800 Subject: [PATCH 19/55] GPU (SunOS): fix detection --- src/detection/gpu/gpu_sunos.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index c5522c8bb..a040adf1f 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -17,12 +17,12 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (error) return error; - if (!ffStrbufStartsWithS(&buffer, "\npci domain 0x")) + if (!ffStrbufStartsWithS(&buffer, "\npci ")) return "Invalid scanpci result"; FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - // pci domain 0x354b bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e + // pci bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e // Device unknown // CardVendor 0x0000 card 0x0000 (Card unknown) // STATUS 0x0010 COMMAND 0x0007 @@ -42,9 +42,9 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* pstart = memrchr(buffer.chars, '\n', (size_t) (pstart - buffer.chars - 1)); ++pstart; - uint32_t pciDomain, pciBus, pciDev, pciFunc, vendorId, deviceId; - if (sscanf(pstart, "pci domain %x bus %x cardnum %x function %x: vendor %x device %x", - &pciDomain, &pciBus, &pciDev, &pciFunc, &vendorId, &deviceId) != 6) + uint32_t vendorId, deviceId; + if (sscanf(pstart, "pci %*[^:]: vendor %x device %x", + &vendorId, &deviceId) != 2) return "PCI info not found, invalid scanpci result"; pclass += strlen("\n CLASS 0x03 "); @@ -61,7 +61,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (pciDev << 2) | pciFunc; + gpu->deviceId = 0; gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) From 77fbfd3fbd2ddc49830cc93e9daf5c0e1a3f1145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 22 Jun 2024 08:10:52 +0800 Subject: [PATCH 20/55] GPU (Windows): detect GPU type with AMD driver Ref: #1032 --- src/detection/gpu/gpu_amd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 3efd23c40..0b367acca 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -63,5 +63,8 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu if (result.frequency) *result.frequency = device->coreClock / 1000.; // Maximum frequency + if (result.type) + *result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + return NULL; } From b500e9c09ba4433cafb30a9098899e2e1a039c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 22 Jun 2024 15:42:56 +0800 Subject: [PATCH 21/55] Terminal: add fast path of version and font detection for kitty Ref: https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 --- src/detection/terminalfont/terminalfont.c | 63 ++++++++++++++------- src/detection/terminalshell/terminalshell.c | 34 ++++------- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 78609ef9c..453c209e1 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -1,4 +1,5 @@ #include "terminalfont.h" +#include "common/io/io.h" #include "common/properties.h" #include "common/processing.h" #include "detection/terminalshell/terminalshell.h" @@ -256,8 +257,6 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon } } - - #endif //defined(_WIN32) || defined(__linux__) FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResult* result) @@ -265,33 +264,55 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); - if(!ffProcessAppendStdOut(&buf, (char* const[]){ - exe->chars, - "+kitten", - "query-terminal", - NULL, - })) + char fontHex[64] = "", sizeHex[64] = ""; + // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 + if (ffGetTerminalResponse( + "\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size + "\eP1+r%*[^=]=%64[^\e]\e\\\eP1+r%*[^=]=%64[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) { - ffParsePropLines(buf.chars, "font_family: ", &fontName); - ffParsePropLines(buf.chars, "font_size: ", &fontSize); + // decode hex string + for (const char* p = fontHex; p[0] && p[1]; p += 2) + { + unsigned value; + if (sscanf(p, "%2x", &value)) + ffStrbufAppendC(&fontName, (char) value); + } + for (const char* p = sizeHex; p[0] && p[1]; p += 2) + { + unsigned value; + if (sscanf(p, "%2x", &value)) + ffStrbufAppendC(&fontSize, (char) value); + } } else { - FFpropquery fontQuery[] = { - {"font_family ", &fontName}, - {"font_size ", &fontSize}, - }; + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + if(!ffProcessAppendStdOut(&buf, (char* const[]){ + exe->chars, + "+kitten", + "query-terminal", + NULL, + })) + { + ffParsePropLines(buf.chars, "font_family: ", &fontName); + ffParsePropLines(buf.chars, "font_size: ", &fontSize); + } + else + { + FFpropquery fontQuery[] = { + {"font_family ", &fontName}, + {"font_size ", &fontSize}, + }; - ffParsePropFileConfigValues("kitty/kitty.conf", 2, fontQuery); + ffParsePropFileConfigValues("kitty/kitty.conf", 2, fontQuery); - if(fontName.length == 0) - ffStrbufSetS(&fontName, "monospace"); - if(fontSize.length == 0) - ffStrbufSetS(&fontSize, "11.0"); + if(fontName.length == 0) + ffStrbufSetS(&fontName, "monospace"); + if(fontSize.length == 0) + ffStrbufSetS(&fontSize, "11.0"); + } } - ffFontInitValues(&result->font, fontName.chars, fontSize.chars); return true; diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 7766790c2..e0246ea37 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -480,33 +480,21 @@ static bool getTerminalVersionZellij(FFstrbuf* exe, FFstrbuf* version) #ifndef _WIN32 static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { - #if defined(__linux__) || defined(__FreeBSD__) - // kitty is written in python. `kitty --version` can be expensive - char buffer[1024] = {}; - if ( - #ifdef __linux__ - ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) || - ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) - #else - ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) - #endif - ) + char versionHex[64] = ""; + // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 + if (ffGetTerminalResponse( + "\eP+q6b697474792d71756572792d76657273696f6e\e\\", // kitty-query-version + "\eP1+r%*[^=]=%64[^\e]\e\\\\", versionHex) == NULL && *versionHex) { - // Starts from version 0.17.0 - // https://github.com/kovidgoyal/kitty/blob/master/kitty/constants.py#L25 - const char* p = memmem(buffer, sizeof(buffer) - 1, "version: Version = Version(", strlen("version: Version = Version(")); - if (p) + // decode hex string + for (const char* p = versionHex; p[0] && p[1]; p += 2) { - p += strlen("version: Version = Version("); - int major, minor, patch; - if (sscanf(p, "%d,%d,%d", &major, &minor, &patch) == 3) - { - ffStrbufSetF(version, "%d.%d.%d", major, minor, patch); - return true; - } + unsigned value; + if (sscanf(p, "%2x", &value)) + ffStrbufAppendC(version, (char) value); } + return true; } - #endif //kitty 0.21.2 created by Kovid Goyal return getExeVersionGeneral(exe, version); From e37ad26729ff795be12d92799870601ad149e3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 22 Jun 2024 21:52:20 +0800 Subject: [PATCH 22/55] GPU (Nvidia): fix definition of `nvmlMemory_v2` --- src/detection/gpu/nvml.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index 7a2761893..ea776a4be 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -52,7 +52,8 @@ typedef struct { // Allocated device memory (in bytes) unsigned long long used; } nvmlMemory_v2_t; -enum { nvmlMemory_v2 = 2 }; +// https://github.com/NVIDIA/nvidia-settings/issues/78#issuecomment-1012837988 +enum { nvmlMemory_v2 = (unsigned int)(sizeof(nvmlMemory_v2_t) | (2 << 24U)) }; // https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g805c0647be9996589fc5e3f6ff680c64 // Clock types From 88e075ad9dbb03bb4b5c8b8b756461441bc469db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 22 Jun 2024 22:03:28 +0800 Subject: [PATCH 23/55] CMake: remove option `ENABLE_PROPRIETARY_GPU_DRIVER_API` --- CHANGELOG.md | 7 +++++++ CMakeLists.txt | 21 +++++++-------------- src/common/init.c | 3 --- src/detection/gpu/gpu_bsd.c | 2 -- src/detection/gpu/gpu_linux.c | 7 +------ src/detection/gpu/gpu_windows.c | 9 +-------- src/detection/gpu/gpu_wsl.cpp | 2 -- 7 files changed, 16 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f5a55cee..e87fe6a59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 2.17.0 + +Changes: +* CMake option `ENABLE_PROPRIETARY_GPU_DRIVER_API` is removed. The GPU driver APIs are now enabled by default. + * The option was introduced to reduce the license concerns. Since all non MIT proprietary code has been rewritten manually from scratch, it is no longer necessary. + * See for detail + # 2.16.0 This release added basic support for SunOS (Solaris, illumos). The binaries provided in the release lack a few useful features (such as Display detection). People who use SunOS should consider building fastfetch themselves. diff --git a/CMakeLists.txt b/CMakeLists.txt index fa526f990..ff5632707 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,6 @@ cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF) option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF) -option(ENABLE_PROPRIETARY_GPU_DRIVER_API "Enable proprietary GPU driver API (NVML, IGCL and AGS)" ON) 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 option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions @@ -813,15 +812,13 @@ if(ENABLE_DIRECTX_HEADERS) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp) endif() -if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32)) - message(STATUS "Enabling proprietary GPU driver API") - if(LINUX OR BSD OR WIN32) - list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c) - endif() - if(WIN32) - list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c) - list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c) - endif() +# Proprietary GPU driver APIs +if(LINUX OR BSD OR WIN32) + list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c) +endif() +if(WIN32) + list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c) + list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c) endif() include(CheckFunctionExists) @@ -850,10 +847,6 @@ add_library(libfastfetch OBJECT ${LIBFASTFETCH_SRC} ) -if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32)) - target_compile_definitions(libfastfetch PRIVATE FF_USE_PROPRIETARY_GPU_DRIVER_API) -endif() - if(yyjson_FOUND) target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON) target_link_libraries(libfastfetch PRIVATE yyjson::yyjson) diff --git a/src/common/init.c b/src/common/init.c index 1898de1c7..13d6f4468 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -254,9 +254,6 @@ void ffListFeatures(void) #ifdef FF_HAVE_DIRECTX_HEADERS "Directx Headers\n" #endif - #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API - "Proprietary GPU driver API\n" - #endif #ifdef FF_USE_SYSTEM_YYJSON "System yyjson\n" #endif diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 8beef72a9..7bc22b485 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -76,7 +76,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); } - #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) { ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { @@ -98,7 +97,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; } - #endif // FF_USE_PROPRIETARY_GPU_DRIVER_API } return NULL; diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index a924a114f..28b33f38c 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -2,14 +2,11 @@ #include "detection/vulkan/vulkan.h" #include "detection/temps/temps_linux.h" #include "detection/cpu/cpu.h" +#include "detection/gpu/gpu_driver_specific.h" #include "common/io/io.h" #include "common/properties.h" #include "util/stringUtils.h" -#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API - #include "detection/gpu/gpu_driver_specific.h" -#endif - #define FF_STR_INDIR(x) #x #define FF_STR(x) FF_STR_INDIR(x) @@ -261,7 +258,6 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) { - #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API if (options->temp || options->driverSpecific) { ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { @@ -280,7 +276,6 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf .frequency = &gpu->frequency, }, "libnvidia-ml.so"); } - #endif // FF_USE_PROPRIETARY_GPU_DRIVER_API if (gpu->type == FF_GPU_TYPE_UNKNOWN) { diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index dc809727f..b2e4b8d83 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -1,11 +1,8 @@ #include "gpu.h" +#include "detection/gpu/gpu_driver_specific.h" #include "util/windows/unicode.h" #include "util/windows/registry.h" -#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API - #include "detection/gpu/gpu_driver_specific.h" -#endif - #include static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name) @@ -13,7 +10,6 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name) return ffStrbufEqual(&gpu->name, name); } -#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName) { if (vendor == FF_GPU_VENDOR_NAME_NVIDIA) @@ -48,7 +44,6 @@ static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(& return true; } -#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { @@ -144,7 +139,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* } } -#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API __typeof__(&ffDetectNvidiaGpuInfo) detectFn; const char* dllName; @@ -174,7 +168,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ); } } -#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API } return NULL; diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index eb7ed5b17..e4ef8e4ff 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -104,7 +104,6 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID); ffStrbufSetStatic(&gpu->vendor, vendorStr); - #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && (options->driverSpecific || options->temp)) { FFGpuDriverCondition cond = { @@ -124,7 +123,6 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .frequency = &gpu->frequency, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); } - #endif } } From 42b84161d90c20c75a90cadf6abeb091b3fb5e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 23 Jun 2024 08:57:06 +0800 Subject: [PATCH 24/55] GPU (Windows): don't assume `revId` is not 0 --- src/detection/gpu/gpu_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index b2e4b8d83..261d0e82a 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -144,7 +144,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { - if (vendorId && deviceId && subSystemId && revId) + if (vendorId && deviceId && subSystemId) { detectFn( &(FFGpuDriverCondition) { From a6c006221d21d8db370f1e29c1fbd27c65e888bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 23 Jun 2024 09:03:32 +0800 Subject: [PATCH 25/55] GPU (AMD): fix use-after-free crashes Ref: https://github.com/fastfetch-cli/fastfetch/issues/1032 --- src/detection/gpu/gpu_amd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 0b367acca..8df677f65 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -19,13 +19,12 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu inited = true; FF_LIBRARY_LOAD(libags, NULL, "dlopen amd_ags failed", soName , 1); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libags, agsInitialize) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libags, agsDeInitialize) struct AGSContext* apiHandle; if (ffagsInitialize(AGS_CURRENT_VERSION, NULL, &apiHandle, &gpuInfo) != AGS_SUCCESS) return "loading ags library failed"; - ffagsDeInitialize(apiHandle); + // agsDeInitialize will free pointers allocated in gpuInfo. Just leak them. } if (gpuInfo.numDevices == 0) From 63a28cc8f40c0880f07984c20378e7915f468d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 23 Jun 2024 21:26:48 +0800 Subject: [PATCH 26/55] CI (Windows): bundle amd_ags dlls --- .github/workflows/ci.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 179b84a7a..8a3d7025d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -508,6 +508,9 @@ jobs: - name: copy necessary dlls run: cp /clang64/bin/{OpenCL,vulkan-1}.dll . + - name: download amd_ags + run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x64.dll + - name: list features run: ./fastfetch --list-features @@ -527,10 +530,10 @@ jobs: run: ctest - name: create zip archive - run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets - name: create 7z archive - run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets - name: upload artifacts uses: actions/upload-artifact@v4 @@ -578,6 +581,9 @@ jobs: - name: copy necessary dlls run: cp /clang32/bin/{OpenCL,vulkan-1}.dll . + - name: download amd_ags + run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x86.dll + - name: run fastfetch run: time ./fastfetch -c presets/ci.jsonc @@ -594,10 +600,10 @@ jobs: run: ctest - name: create zip archive - run: 7z a -tzip -mx9 -bd -y fastfetch-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -tzip -mx9 -bd -y fastfetch-windows-i686.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets - name: create 7z archive - run: 7z a -t7z -mx9 -bd -y fastfetch-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets + run: 7z a -t7z -mx9 -bd -y fastfetch-windows-i686.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets - name: upload artifacts uses: actions/upload-artifact@v4 From a210128592fcefa9c78bff45452dff7363493392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 08:41:44 +0800 Subject: [PATCH 27/55] OS (macOS): correctly set pretty name --- src/detection/os/os_apple.m | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index f82d7a501..5a8ef621a 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -54,18 +54,18 @@ static bool detectOSCodeName(FFOSResult* os) case 14: ffStrbufSetStatic(&os->codename, "Mojave"); return true; case 13: ffStrbufSetStatic(&os->codename, "High Sierra"); return true; case 12: ffStrbufSetStatic(&os->codename, "Sierra"); return true; - case 11: ffStrbufSetStatic(&os->codename, "El Capitan"); return true; - case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); return true; - case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); return true; - case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); return true; - case 7: ffStrbufSetStatic(&os->codename, "Lion"); return true; - case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); return true; - case 5: ffStrbufSetStatic(&os->codename, "Leopard"); return true; - case 4: ffStrbufSetStatic(&os->codename, "Tiger"); return true; - case 3: ffStrbufSetStatic(&os->codename, "Panther"); return true; - case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); return true; - case 1: ffStrbufSetStatic(&os->codename, "Puma"); return true; - case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); return true; + case 11: ffStrbufSetStatic(&os->codename, "El Capitan"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true; + case 10: ffStrbufSetStatic(&os->codename, "Yosemite"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true; + case 9: ffStrbufSetStatic(&os->codename, "Mavericks"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true; + case 8: ffStrbufSetStatic(&os->codename, "Mountain Lion"); ffStrbufSetStatic(&os->prettyName, "OS X"); return true; + case 7: ffStrbufSetStatic(&os->codename, "Lion"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 6: ffStrbufSetStatic(&os->codename, "Snow Leopard"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 5: ffStrbufSetStatic(&os->codename, "Leopard"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 4: ffStrbufSetStatic(&os->codename, "Tiger"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 3: ffStrbufSetStatic(&os->codename, "Panther"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 2: ffStrbufSetStatic(&os->codename, "Jaguar"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 1: ffStrbufSetStatic(&os->codename, "Puma"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; + case 0: ffStrbufSetStatic(&os->codename, "Cheetah"); ffStrbufSetStatic(&os->prettyName, "Mac OS X"); return true; } } } @@ -106,7 +106,8 @@ void ffDetectOSImpl(FFOSResult* os) if(os->buildID.length == 0) ffSysctlGetString("kern.osversion", &os->buildID); - ffStrbufAppend(&os->prettyName, &os->name); + if(os->prettyName.length == 0) + ffStrbufSetStatic(&os->prettyName, "macOS"); ffStrbufAppend(&os->versionID, &os->version); if(!detectOSCodeName(os)) From b5e199d2b237e270369f596192ac975231a181bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 09:06:21 +0800 Subject: [PATCH 28/55] IO (Linux): make sure `stdin` and `stdout` are tty when querying terminal --- src/common/io/io_unix.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 501e23015..20eb3b3b0 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -136,29 +136,44 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...) if (instance.config.display.pipe) return "Not supported in --pipe mode"; + int fin = STDIN_FILENO, fout = STDOUT_FILENO; + FF_AUTO_CLOSE_FD int ftty = -1; + + if (!isatty(STDIN_FILENO)) + { + if (ftty < 0) + ftty = open("/dev/tty", O_RDWR | O_CLOEXEC); + fin = ftty; + } + if (!isatty(STDOUT_FILENO)) + { + if (ftty < 0) + ftty = open("/dev/tty", O_RDWR | O_CLOEXEC); + fout = ftty; + } + struct termios oldTerm, newTerm; - if(tcgetattr(STDIN_FILENO, &oldTerm) == -1) + if(tcgetattr(fin, &oldTerm) == -1) return "tcgetattr(STDIN_FILENO, &oldTerm) failed"; newTerm = oldTerm; newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO); - if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1) + if(tcsetattr(fin, TCSANOW, &newTerm) == -1) return "tcsetattr(STDIN_FILENO, TCSANOW, &newTerm)"; - fputs(request, stdout); - fflush(stdout); + ffWriteFDData(fout, strlen(request), request); //Give the terminal 35ms to respond - if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0) + if(poll(&(struct pollfd) { .fd = fin, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0) { - tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm); + tcsetattr(fin, TCSANOW, &oldTerm); return "poll() timeout or failed"; } char buffer[512]; - ssize_t bytesRead = read(STDIN_FILENO, buffer, sizeof(buffer) - 1); + ssize_t bytesRead = read(fin, buffer, sizeof(buffer) - 1); - tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm); + tcsetattr(fin, TCSANOW, &oldTerm); if(bytesRead <= 0) return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed"; From 071be4794f7a6a02f36b32f1b1daf8ad5ab945f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 10:03:19 +0800 Subject: [PATCH 29/55] Builtin (Asahi): fix logo color --- src/logo/ascii/asahi.txt | 4 ++-- src/logo/builtin.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/logo/ascii/asahi.txt b/src/logo/ascii/asahi.txt index 005f05613..4ee539605 100644 --- a/src/logo/ascii/asahi.txt +++ b/src/logo/ascii/asahi.txt @@ -1,4 +1,4 @@ -$1 ## $2** + ## $2** $1*####$2****. $1###$2, $3...,$1/#$3,,,.. @@ -15,4 +15,4 @@ $3((((((((((((((((((((($5@@@$6&%&$5@@@%$4,.......... $3/(((((((((((($5@@@@@@/$4.../&& $3.((((((((($5@@@@($4.... $3/((((($5@@#$4... - $3.(($4&, \ No newline at end of file + $3.(($4&, diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 69d6d99e9..067d772ad 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -484,7 +484,7 @@ static const FFlogo A[] = { FF_COLOR_FG_YELLOW, FF_COLOR_FG_GREEN, FF_COLOR_FG_RED, - "38", //cyan + FF_COLOR_FG_LIGHT_BLACK, FF_COLOR_FG_WHITE, FF_COLOR_FG_CYAN, FF_COLOR_FG_BLUE, @@ -1520,7 +1520,7 @@ static const FFlogo F[] = { FF_COLOR_FG_YELLOW, FF_COLOR_FG_GREEN, FF_COLOR_FG_RED, - "38", //cyan + FF_COLOR_FG_LIGHT_BLACK, FF_COLOR_FG_WHITE, FF_COLOR_FG_CYAN, FF_COLOR_FG_BLUE, From 0bc9149a23a00c863ac3c6a3b8cf260f79dc9997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 16:09:19 +0800 Subject: [PATCH 30/55] IO: improve `ffGetTerminalResponse` --- src/common/io/io_unix.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 20eb3b3b0..3912582e6 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -142,28 +142,28 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...) if (!isatty(STDIN_FILENO)) { if (ftty < 0) - ftty = open("/dev/tty", O_RDWR | O_CLOEXEC); + ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); fin = ftty; } if (!isatty(STDOUT_FILENO)) { if (ftty < 0) - ftty = open("/dev/tty", O_RDWR | O_CLOEXEC); + ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); fout = ftty; } - struct termios oldTerm, newTerm; + struct termios oldTerm; if(tcgetattr(fin, &oldTerm) == -1) return "tcgetattr(STDIN_FILENO, &oldTerm) failed"; - newTerm = oldTerm; + struct termios newTerm = oldTerm; newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO); - if(tcsetattr(fin, TCSANOW, &newTerm) == -1) - return "tcsetattr(STDIN_FILENO, TCSANOW, &newTerm)"; + if(tcsetattr(fin, TCSAFLUSH, &newTerm) == -1) + return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)"; ffWriteFDData(fout, strlen(request), request); - //Give the terminal 35ms to respond + //Give the terminal some time to respond if(poll(&(struct pollfd) { .fd = fin, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0) { tcsetattr(fin, TCSANOW, &oldTerm); From 0606cde06143211b65c0907196ac4eb31010819c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 16:10:54 +0800 Subject: [PATCH 31/55] TerminalFont (Linux): fix `XTGETTCAP` response is printed in console when query kitty term font --- src/detection/terminalfont/terminalfont.c | 44 ++++++++++++----------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 453c209e1..18fc8eec7 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -259,31 +259,35 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon #endif //defined(_WIN32) || defined(__linux__) +static bool queryKittyTerm(const char* query, FFstrbuf* res) +{ + // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 + char buffer[64] = ""; + if (ffGetTerminalResponse( + query, // kitty-query-font_family;kitty-query-font_size + "\eP1+r%*[^=]=%64[^\e]\e\\", buffer) == NULL && *buffer) + { + // decode hex string + for (const char* p = buffer; p[0] && p[1]; p += 2) + { + unsigned value; + if (sscanf(p, "%2x", &value)) + ffStrbufAppendC(res, (char) value); + } + return true; + } + return false; +} + FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResult* result) { FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); - char fontHex[64] = "", sizeHex[64] = ""; - // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 - if (ffGetTerminalResponse( - "\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size - "\eP1+r%*[^=]=%64[^\e]\e\\\eP1+r%*[^=]=%64[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) - { - // decode hex string - for (const char* p = fontHex; p[0] && p[1]; p += 2) - { - unsigned value; - if (sscanf(p, "%2x", &value)) - ffStrbufAppendC(&fontName, (char) value); - } - for (const char* p = sizeHex; p[0] && p[1]; p += 2) - { - unsigned value; - if (sscanf(p, "%2x", &value)) - ffStrbufAppendC(&fontSize, (char) value); - } - } + // Kitty generates response independently even if we query font family and size in one query + // which may result in short read in `ffGetTerminalResponse` + if (queryKittyTerm("\eP+q6b697474792d71756572792d666f6e745f66616d696c79\e\\", &fontName)) // kitty-query-font_family + queryKittyTerm("\eP+q6b697474792d71756572792d666f6e745f73697a65\e\\", &fontSize); // kitty-query-font_size else { FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); From abf6c403d415ffa4c6e5e49ec7da9787a755d478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 16:15:35 +0800 Subject: [PATCH 32/55] Fastfetch: add JSON config `general.preRun` --- doc/json_schema.json | 5 +++++ src/options/general.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/doc/json_schema.json b/doc/json_schema.json index 146a1822d..4c5ae9367 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -329,6 +329,11 @@ "type": "integer", "description": "Set the timeout (ms) when waiting for child processes, `-1` for no timeout", "default": 1000 + }, + "preRun": { + "type": "string", + "description": "Set the command to be executed before printing logos", + "default": "" } } }, diff --git a/src/options/general.c b/src/options/general.c index 2b87d7929..b2fe71150 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -1,5 +1,6 @@ #include "fastfetch.h" #include "common/jsonconfig.h" +#include "common/processing.h" #include "options/general.h" #include "util/stringUtils.h" @@ -21,6 +22,20 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va options->multithreading = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "processingTimeout")) options->processingTimeout = (int32_t) yyjson_get_int(val); + else if (ffStrEqualsIgnCase(key, "preRun")) + { + FF_STRBUF_AUTO_DESTROY _ = ffStrbufCreate(); + const char* error = ffProcessAppendStdOut(&_, (char* const[]) { + #ifdef _WIN32 + "cmd.exe", "/C", + #else + "/bin/sh", "-c", + #endif + (char*) yyjson_get_str(val), NULL + }); + if (error) + return "Failed to execute preRun command"; + } #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) else if (ffStrEqualsIgnCase(key, "escapeBedrock")) From 1704dc62e0d9c3bd22735a235aa46b7765399e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Jun 2024 18:15:14 +0800 Subject: [PATCH 33/55] Doc: add debian in README [ci skip] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d59f1f04d..52dbac052 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/ Some distros packaged an outdated fastfetch version. Older version is not supported, please always ensure that the latest version is used. * Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer) +* Debian: `sudo apt install fastfetch` (for Debian 13 or newer) * Debian / Ubuntu: Download `fastfetch-linux-.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer). * Arch Linux: `sudo pacman -S fastfetch` * Fedora: `sudo dnf install fastfetch` From 47a9cf0450b321ce4da756adbe8ed47b975a9238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 10:01:23 +0800 Subject: [PATCH 34/55] IO: enable terminal query in `--pipe` mode --- src/common/io/io_unix.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 3912582e6..788d47a3f 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -133,9 +133,6 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o const char* ffGetTerminalResponse(const char* request, const char* format, ...) { - if (instance.config.display.pipe) - return "Not supported in --pipe mode"; - int fin = STDIN_FILENO, fout = STDOUT_FILENO; FF_AUTO_CLOSE_FD int ftty = -1; From e9031171c0f1734b854573e48190f540473bbc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 10:14:03 +0800 Subject: [PATCH 35/55] Doc: update changelog [ci skip] --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e87fe6a59..816a2641c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,35 @@ Changes: * The option was introduced to reduce the license concerns. Since all non MIT proprietary code has been rewritten manually from scratch, it is no longer necessary. * See for detail +Features: +* Add support for `--gpu-detection-method opencl` which uses OpenCL to detect GPUs. +* Support detecting CPU cache size by using SMBIOS as fallback (CPUCache) +* Support GPU detection (SunOS) +* Support GPU type detection with AMD GPU driver (GPU, Windows) +* Add fast path of version and font detection for kitty (Terminal / TerminalFont) +* Make sure `stdin` and `stdout` are TTYs when querying terminal (Linux) +* Add new JSON config option `general.preRun`, which is executed before fastfetch prints output. + * It can be used to generate a temp logo file. For example +```jsonc +{ + "general": { + "preRun": "kitten icat --align=left /path/to/image > /tmp/logo.kitty" + }, + "logo": { + "source": "/tmp/logo.kitty", + "type": "raw" + } +} +``` + +Bugfixes: +* Fix invalid path (#1031, LM, Linux) +* Fix VMEM detection for Nvidia GPU (requires `--gpu-driver-specific`) (GPU) +* Fix AMD `--gpu-driver-specific` for AMD cards (#1032, GPU, Windows) + +Logo: +* Fix colors of Asahi Linux + # 2.16.0 This release added basic support for SunOS (Solaris, illumos). The binaries provided in the release lack a few useful features (such as Display detection). People who use SunOS should consider building fastfetch themselves. From e257f876ae2f54d69a2f0e2d5edd26ccf91f43e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 10:50:25 +0800 Subject: [PATCH 36/55] TerminalSize (Windows): make it work when stdin or stdout is redirected --- CHANGELOG.md | 3 +- src/common/io/io_windows.c | 33 +++++++++++++------ .../terminalsize/terminalsize_windows.c | 14 ++++++-- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 816a2641c..cad3178e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ Features: * Support GPU detection (SunOS) * Support GPU type detection with AMD GPU driver (GPU, Windows) * Add fast path of version and font detection for kitty (Terminal / TerminalFont) -* Make sure `stdin` and `stdout` are TTYs when querying terminal (Linux) +* Make sure `stdin` and `stdout` are TTYs when querying terminal + * So modules like `TerminalSize` should work when `stdin` or `stdout` is redirected * Add new JSON config option `general.preRun`, which is executed before fastfetch prints output. * It can be used to generate a temp logo file. For example ```jsonc diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index be8e7e573..fd6c22ce2 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -175,24 +175,37 @@ void ffListFilesRecursively(const char* path, bool pretty) const char* ffGetTerminalResponse(const char* request, const char* format, ...) { - if (instance.config.display.pipe) - return "Not supported in --pipe mode"; - HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); - DWORD prev_mode; - GetConsoleMode(hInput, &prev_mode); + FF_AUTO_CLOSE_FD HANDLE hConin = INVALID_HANDLE_VALUE; + DWORD inputMode; + if (!GetConsoleMode(hInput, &inputMode)) + { + hConin = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, NULL); + hInput = hConin; + } SetConsoleMode(hInput, 0); FlushConsoleInputBuffer(hInput); - DWORD bytes = 0; - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), request, (DWORD) strlen(request), &bytes, NULL); + { + DWORD bytes = 0; + HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + FF_AUTO_CLOSE_FD HANDLE hConout = INVALID_HANDLE_VALUE; + DWORD outputMode; + if (!GetConsoleMode(hOutput, &outputMode)) + { + hConout = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL); + hOutput = hConout; + } + WriteFile(hOutput, "TEST\n", 5, &bytes, NULL); + WriteFile(hOutput, request, (DWORD) strlen(request), &bytes, NULL); + } while (true) { if (WaitForSingleObjectEx(hInput, FF_IO_TERM_RESP_WAIT_MS, TRUE) != WAIT_OBJECT_0) { - SetConsoleMode(hInput, prev_mode); + SetConsoleMode(hInput, inputMode); return "WaitForSingleObject() failed or timeout"; } @@ -213,10 +226,10 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...) } char buffer[512]; - bytes = 0; + DWORD bytes = 0; ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL); - SetConsoleMode(hInput, prev_mode); + SetConsoleMode(hInput, inputMode); if(bytes <= 0) return "ReadFile() failed"; diff --git a/src/detection/terminalsize/terminalsize_windows.c b/src/detection/terminalsize/terminalsize_windows.c index 4d2f6c83d..1264f0321 100644 --- a/src/detection/terminalsize/terminalsize_windows.c +++ b/src/detection/terminalsize/terminalsize_windows.c @@ -5,9 +5,19 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result) { + HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + FF_AUTO_CLOSE_FD HANDLE hConout = INVALID_HANDLE_VALUE; + { + DWORD outputMode; + if (!GetConsoleMode(hOutput, &outputMode)) + { + hConout = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL); + hOutput = hConout; + } + } { CONSOLE_SCREEN_BUFFER_INFO csbi; - if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + if (GetConsoleScreenBufferInfo(hOutput, &csbi)) { result->columns = (uint16_t) (csbi.srWindow.Right - csbi.srWindow.Left + 1); result->rows = (uint16_t) (csbi.srWindow.Bottom - csbi.srWindow.Top + 1); @@ -23,7 +33,7 @@ bool ffDetectTerminalSize(FFTerminalSizeResult* result) { CONSOLE_FONT_INFO cfi; - if(GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi)) // Only works for ConHost + if(GetCurrentConsoleFont(hOutput, FALSE, &cfi)) // Only works for ConHost { result->width = result->columns * (uint16_t) cfi.dwFontSize.X; result->height = result->rows * (uint16_t) cfi.dwFontSize.Y; From a4614ec4128911f27dd3ea77ed0d690738b0e2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 13:50:42 +0800 Subject: [PATCH 37/55] IO (Windows): implement `ffSuppressIO` --- src/common/io/io_windows.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index fd6c22ce2..ce7cde96a 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -114,8 +114,40 @@ bool ffPathExpandEnv(const char* in, FFstrbuf* out) bool ffSuppressIO(bool suppress) { - (void) suppress; //Not implemented. - return false; + static bool init = false; + static HANDLE hOrigOut = INVALID_HANDLE_VALUE; + static HANDLE hOrigErr = INVALID_HANDLE_VALUE; + static HANDLE hNullFile = INVALID_HANDLE_VALUE; + static int fOrigOut = -1; + static int fOrigErr = -1; + static int fNullFile = -1; + + if (!init) + { + if(!suppress) + return true; + + hOrigOut = GetStdHandle(STD_OUTPUT_HANDLE); + hOrigErr = GetStdHandle(STD_ERROR_HANDLE); + hNullFile = CreateFileW(L"NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL); + fOrigOut = _dup(STDOUT_FILENO); + fOrigErr = _dup(STDERR_FILENO); + fNullFile = _open_osfhandle((intptr_t) hNullFile, 0); + + init = true; + } + if (hNullFile == INVALID_HANDLE_VALUE || fNullFile == -1) + return false; + + fflush(stdout); + fflush(stderr); + + SetStdHandle(STD_OUTPUT_HANDLE, suppress ? hNullFile : hOrigOut); + SetStdHandle(STD_ERROR_HANDLE, suppress ? hNullFile : hOrigErr); + _dup2(suppress ? fNullFile : fOrigOut, STDOUT_FILENO); + _dup2(suppress ? fNullFile : fOrigErr, STDERR_FILENO); + + return true; } void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indentation, const char* folderName, bool pretty) From 18d36c50540c403715ca48a3bdf62164813b2b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 16:14:34 +0800 Subject: [PATCH 38/55] Format: support argument truncation Fix #1043 --- CHANGELOG.md | 2 + src/common/format.c | 80 +++++++++++++++++++++++----------------- src/data/help_format.txt | 4 ++ 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cad3178e4..fdf40a905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Features: * Add fast path of version and font detection for kitty (Terminal / TerminalFont) * Make sure `stdin` and `stdout` are TTYs when querying terminal * So modules like `TerminalSize` should work when `stdin` or `stdout` is redirected +* Support argument truncation in `---format` + * See `fastfetch --help format` for detail * Add new JSON config option `general.preRun`, which is executed before fastfetch prints output. * It can be used to generate a temp logo file. For example ```jsonc diff --git a/src/common/format.c b/src/common/format.c index 525b65788..8e1d8736c 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -52,24 +52,28 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg) * @param placeholderValue the string to parse * @return uint32_t the parsed value */ -static uint32_t getArgumentIndex(const FFstrbuf* placeholderValue, uint32_t numArgs, const FFformatarg* arguments) +static uint32_t getArgumentIndex(const char* placeholderValue, uint32_t numArgs, const FFformatarg* arguments) { - char firstChar = placeholderValue->chars[0]; + char firstChar = placeholderValue[0]; + if (firstChar == '\0') + return 0; // use arg counter - if(firstChar >= '1' && firstChar <= '9') + if (firstChar >= '0' && firstChar <= '9') { char* pEnd = NULL; - unsigned long result = strtoul(placeholderValue->chars, &pEnd, 10); - if (pEnd != placeholderValue->chars + placeholderValue->length || result > numArgs) + uint32_t result = (uint32_t) strtoul(placeholderValue, &pEnd, 10); + if (result > numArgs) return UINT32_MAX; - return (uint32_t) result; + if (*pEnd != '\0') + return UINT32_MAX; + return result; } else if (ffCharIsEnglishAlphabet(firstChar)) { for (uint32_t i = 0; i < numArgs; ++i) { const FFformatarg* arg = &arguments[i]; - if(arg->name && ffStrbufIgnCaseEqualS(placeholderValue, arg->name)) + if (arg->name && strcasecmp(placeholderValue, arg->name) == 0) return i + 1; } } @@ -86,16 +90,6 @@ static inline void appendInvalidPlaceholder(FFstrbuf* buffer, const char* start, ffStrbufAppendC(buffer, '}'); } -static inline void appendEmptyPlaceholder(FFstrbuf* buffer, const char* placeholder, uint32_t* argCounter, uint32_t numArgs, const FFformatarg* arguments) -{ - if(*argCounter >= numArgs) - ffStrbufAppendS(buffer, placeholder); - else - ffFormatAppendFormatArg(buffer, arguments + *argCounter); - - (*argCounter)++; -} - static inline bool formatArgSet(const FFformatarg* arg) { return arg->value != NULL && ( @@ -128,13 +122,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n continue; } - // if we have an { at the end handle it as {} - if(i == formatstr->length - 1) - { - appendEmptyPlaceholder(buffer, "{", &argCounter, numArgs, arguments); - continue; - } - // jump to next char, the start of the placeholder value ++i; @@ -145,13 +132,6 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n continue; } - // placeholder is {} - if(formatstr->chars[i] == '}') - { - appendEmptyPlaceholder(buffer, "{}", &argCounter, numArgs, arguments); - continue; - } - ffStrbufClear(&placeholderValue); { @@ -205,7 +185,7 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n { ffStrbufSubstrAfter(&placeholderValue, 0); - uint32_t index = getArgumentIndex(&placeholderValue, numArgs, arguments); + uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments); // testing for an invalid index if (index > numArgs) @@ -231,7 +211,7 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n { ffStrbufSubstrAfter(&placeholderValue, 0); - uint32_t index = getArgumentIndex(&placeholderValue, numArgs, arguments); + uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments); // testing for an invalid index if (index > numArgs) @@ -264,16 +244,48 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n continue; } - uint32_t index = getArgumentIndex(&placeholderValue, numArgs, arguments); + int32_t truncLength = INT32_MAX; + char* pColon = memchr(placeholderValue.chars, ':', placeholderValue.length); + if (pColon != NULL) + { + char* pEnd = NULL; + truncLength = (int32_t) strtol(pColon + 1, &pEnd, 10); + if (*pEnd != '\0') + { + appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length); + continue; + } + *pColon = '\0'; + } + + uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments); // test for invalid index + if (index == 0) + index = ++argCounter; + if (index > numArgs) { + if (pColon) *pColon = ':'; appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length); continue; } + bool ellipsis = false; + if (truncLength < 0) + { + ellipsis = true; + truncLength = -truncLength; + } + + uint32_t oldLength = buffer->length; ffFormatAppendFormatArg(buffer, &arguments[index - 1]); + if (buffer->length - oldLength > (uint32_t) truncLength) + { + ffStrbufSubstrBefore(buffer, oldLength + (uint32_t) truncLength); + if (ellipsis) + ffStrbufAppendS(buffer, "…"); + } } if (!instance.config.display.pipe) diff --git a/src/data/help_format.txt b/src/data/help_format.txt index 2939abbdb..3fd6a9283 100644 --- a/src/data/help_format.txt +++ b/src/data/help_format.txt @@ -8,6 +8,10 @@ In 2.14.0 or newer, the value indices can be meaningful named tags. For example: "--title-format '{user-name-colored}{at-symbol-colored}{host-name-colored}'" is equivalent to "--title-format '{6}{7}{8}'" See "fastfetch -h title-format" for all supported tags. +In 2.17.0 or newer, a truncation length can be specified using syntax ':` +For example: "--title-format '{user-name:5}'" will truncate user name into 5-length string. +If '' is negative, an ellipsis … will be appended at the end when the original string is truncated. + If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index. This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})". Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again. From 4a74f69c96a1f7a6745766be6883d93bc1a94794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 16:23:51 +0800 Subject: [PATCH 39/55] Doc: clearify that we don't support truncate multi-byte chars [ci skip] --- src/data/help_format.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data/help_format.txt b/src/data/help_format.txt index 3fd6a9283..dbb960f45 100644 --- a/src/data/help_format.txt +++ b/src/data/help_format.txt @@ -11,6 +11,7 @@ See "fastfetch -h title-format" for all supported tags. In 2.17.0 or newer, a truncation length can be specified using syntax ':` For example: "--title-format '{user-name:5}'" will truncate user name into 5-length string. If '' is negative, an ellipsis … will be appended at the end when the original string is truncated. +Note: The string length is counted in raw bytes. Multi-byte unicode charactors and ANSI escape codes are not taken into account. If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index. This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})". From 963b5c6c4e511b8b874195179e2f180b39629fc3 Mon Sep 17 00:00:00 2001 From: Jack Nolddor <1280022+nolddor@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:17:09 +0200 Subject: [PATCH 40/55] Doc: Make format description more clear at json_schema.json (#1045) [ci skip] --- doc/json_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 4c5ae9367..ebd4ce8b4 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -23,7 +23,7 @@ "default": 0 }, "format": { - "description": "Output format of the module. See `-h module-format` for detail", + "description": "Output format of the module. See `-h -format` for detail. I.e: fastfetch -h disk-format", "type": "string" }, "outputColor": { From f940ef0592d5e347fdec34f52ee59b2df04e1c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jun 2024 21:07:39 +0800 Subject: [PATCH 41/55] Doc: fix typo [ci skip] --- src/data/help_format.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/help_format.txt b/src/data/help_format.txt index dbb960f45..4474e8694 100644 --- a/src/data/help_format.txt +++ b/src/data/help_format.txt @@ -11,7 +11,7 @@ See "fastfetch -h title-format" for all supported tags. In 2.17.0 or newer, a truncation length can be specified using syntax ':` For example: "--title-format '{user-name:5}'" will truncate user name into 5-length string. If '' is negative, an ellipsis … will be appended at the end when the original string is truncated. -Note: The string length is counted in raw bytes. Multi-byte unicode charactors and ANSI escape codes are not taken into account. +Note: The string length is counted in raw bytes. Multi-byte unicode characters and ANSI escape codes are not taken into account. If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index. This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})". From a334b805fd687b2aabf367eed4b13474e07137a7 Mon Sep 17 00:00:00 2001 From: Jack Nolddor <1280022+nolddor@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:08:47 +0200 Subject: [PATCH 42/55] CMake: Use Coordinated Universal Time rather than timezone-varying local date (#1046) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ff5632707..92d586291 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,7 +255,7 @@ if(APPLE) configure_file(src/util/apple/Info.plist.in Info.plist @ONLY) endif() -string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y") +string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y" UTC) configure_file(doc/fastfetch.1.in fastfetch.1 @ONLY) #################### From 6413656ceae41fe80d66e1cf764a7821f229d7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 27 Jun 2024 10:27:17 +0800 Subject: [PATCH 43/55] Logo: rename `--logo-separate` to `--logo-position` --- doc/json_schema.json | 13 +++++++++---- src/data/help.json | 13 ++++++++----- src/logo/image/image.c | 24 ++++++++++++------------ src/logo/logo.c | 4 ++-- src/options/logo.c | 37 ++++++++++++++++++++++++++++++------- src/options/logo.h | 9 ++++++++- 6 files changed, 69 insertions(+), 31 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index ebd4ce8b4..648ef6bfa 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -219,10 +219,15 @@ "description": "If true, regenerate image logo cache", "default": false }, - "separate": { - "type": "boolean", - "description": "If true, print modules at bottom of the logo", - "default": false + "position": { + "type": "string", + "description": "Set the position of the logo should be displayed", + "enum": [ + "left", + "top", + "right" + ], + "default": "left" }, "chafa": { "type": "object", diff --git a/src/data/help.json b/src/data/help.json index eec3b5795..8c4683e15 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -257,12 +257,15 @@ } }, { - "long": "logo-separate", - "desc": "If true, print modules at bottom of the logo", + "long": "logo-position", + "desc": "Set the position of the logo should be displayed", "arg": { - "type": "bool", - "optional": true, - "default": false + "type": "enum", + "enum": { + "left": "Left", + "top": "Top", + "right": "Right" + } } }, { diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 3daf8cfde..495dbccc9 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -72,14 +72,14 @@ static bool printImageIterm(bool printError) if (!options->width || !options->height) { - if (!options->separate) + if (options->position == FF_LOGO_POSITION_LEFT) { ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH", (unsigned) options->paddingTop, (unsigned) options->paddingLeft ); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { ffStrbufAppendNC(&buf, options->paddingTop, '\n'); ffStrbufAppendNC(&buf, options->paddingLeft, ' '); @@ -90,7 +90,7 @@ static bool printImageIterm(bool printError) ffStrbufAppendF(&buf, "\e]1337;File=inline=1:%s\a", base64.chars); ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); - if (!options->separate) + if (options->position == FF_LOGO_POSITION_LEFT) { uint16_t X = 0, Y = 0; const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); @@ -103,7 +103,7 @@ static bool printImageIterm(bool printError) instance.state.logoHeight = Y; fputs("\e[H", stdout); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { instance.state.logoWidth = instance.state.logoHeight = 0; ffPrintCharTimes('\n', options->paddingRight); @@ -120,13 +120,13 @@ static bool printImageIterm(bool printError) base64.chars ); - if (!options->separate) + if (options->position == FF_LOGO_POSITION_LEFT) { instance.state.logoWidth = options->width + options->paddingLeft + options->paddingRight; instance.state.logoHeight = options->paddingTop + options->height; ffStrbufAppendF(&buf, "\e[%uA", (unsigned) instance.state.logoHeight); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { instance.state.logoWidth = instance.state.logoHeight = 0; ffStrbufAppendNC(&buf, options->paddingRight, '\n'); @@ -152,7 +152,7 @@ static bool printImageKittyDirect(bool printError) if (!options->width || !options->height) { - if (!options->separate) + if (options->position == FF_LOGO_POSITION_LEFT) { // We must clear the entre screen to make sure that terminal buffer won't scroll up printf("\e[2J\e[3J\e[%u;%uH", @@ -160,7 +160,7 @@ static bool printImageKittyDirect(bool printError) (unsigned) options->paddingLeft ); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { ffPrintCharTimes('\n', options->paddingTop); ffPrintCharTimes(' ', options->paddingLeft); @@ -171,7 +171,7 @@ static bool printImageKittyDirect(bool printError) else printf("\e_Ga=T,f=100,t=f;%s\e\\", base64.chars); fflush(stdout); - if (!options->separate) + if (options->position == FF_LOGO_POSITION_LEFT) { uint16_t X = 0, Y = 0; const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); @@ -184,7 +184,7 @@ static bool printImageKittyDirect(bool printError) instance.state.logoHeight = Y; fputs("\e[H", stdout); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { instance.state.logoWidth = instance.state.logoHeight = 0; ffPrintCharTimes('\n', options->paddingRight); @@ -200,13 +200,13 @@ static bool printImageKittyDirect(bool printError) (unsigned) options->height, base64.chars ); - if (!options->separate) + if (options->position == FF_LOGO_POSITION_LEFT) { instance.state.logoWidth = options->width + options->paddingLeft + options->paddingRight; instance.state.logoHeight = options->paddingTop + options->height; printf("\e[%uA", (unsigned) instance.state.logoHeight); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { instance.state.logoWidth = instance.state.logoHeight = 0; ffPrintCharTimes('\n', options->paddingRight); diff --git a/src/logo/logo.c b/src/logo/logo.c index edada9d3e..96386336f 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -199,7 +199,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) if(!instance.config.display.pipe) ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); - if(!options->separate) + if(options->position == FF_LOGO_POSITION_LEFT) { //Happens if the last line is the longest if(currentlineLength > instance.state.logoWidth) @@ -210,7 +210,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) //Go to the leftmost position and go up the height ffStrbufAppendF(&result, "\e[1G\e[%uA", instance.state.logoHeight); } - else + else if (options->position == FF_LOGO_POSITION_TOP) { instance.state.logoWidth = instance.state.logoHeight = 0; ffStrbufAppendNC(&result, options->paddingRight, '\n'); diff --git a/src/options/logo.c b/src/options/logo.c index 9c0373040..da526e2b6 100644 --- a/src/options/logo.c +++ b/src/options/logo.c @@ -17,7 +17,7 @@ void ffOptionsInitLogo(FFOptionsLogo* options) options->printRemaining = true; options->preserveAspectRatio = false; options->recache = false; - options->separate = false; + options->position = FF_LOGO_POSITION_LEFT; options->chafaFgOnly = false; ffStrbufInitStatic(&options->chafaSymbols, "block+border+space-wide-inverted"); // Chafa default @@ -110,8 +110,15 @@ logoType: options->preserveAspectRatio = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(subKey, "recache")) options->recache = ffOptionParseBoolean(value); - else if(ffStrEqualsIgnCase(subKey, "separate")) - options->separate = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(subKey, "position")) + { + options->position = (FFLogoPosition) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "left", FF_LOGO_POSITION_LEFT }, + { "right", FF_LOGO_POSITION_RIGHT }, + { "top", FF_LOGO_POSITION_TOP }, + {}, + }); + } else return false; } @@ -355,9 +362,19 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo options->recache = yyjson_get_bool(val); continue; } - else if (ffStrEqualsIgnCase(key, "separate")) + else if (ffStrEqualsIgnCase(key, "position")) { - options->separate = yyjson_get_bool(val); + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "left", FF_LOGO_POSITION_LEFT }, + { "top", FF_LOGO_POSITION_TOP }, + { "right", FF_LOGO_POSITION_RIGHT }, + {}, + }); + + if (error) return error; + options->chafaCanvasMode = (uint32_t) value; + continue; } else if (ffStrEqualsIgnCase(key, "chafa")) @@ -528,8 +545,14 @@ void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc if (options->recache != defaultOptions.recache) yyjson_mut_obj_add_bool(doc, obj, "recache", options->recache); - if (options->separate != defaultOptions.separate) - yyjson_mut_obj_add_bool(doc, obj, "separate", options->separate); + if (options->position != defaultOptions.position) + { + yyjson_mut_obj_add_str(doc, obj, "position", ((const char* []) { + "left", + "top", + "right", + })[options->position]); + } { yyjson_mut_val* chafa = yyjson_mut_obj(doc); diff --git a/src/options/logo.h b/src/options/logo.h index b93d0ef8a..ab22843b9 100644 --- a/src/options/logo.h +++ b/src/options/logo.h @@ -23,10 +23,18 @@ typedef enum FFLogoType FF_LOGO_TYPE_NONE, //--logo none } FFLogoType; +typedef enum FFLogoPosition +{ + FF_LOGO_POSITION_LEFT, + FF_LOGO_POSITION_TOP, + FF_LOGO_POSITION_RIGHT, +} FFLogoPosition; + typedef struct FFOptionsLogo { FFstrbuf source; FFLogoType type; + FFLogoPosition position; FFstrbuf colors[FASTFETCH_LOGO_MAX_COLORS]; uint32_t width; uint32_t height; @@ -36,7 +44,6 @@ typedef struct FFOptionsLogo bool printRemaining; bool preserveAspectRatio; bool recache; - bool separate; bool chafaFgOnly; FFstrbuf chafaSymbols; From 4f261509a08081195c104772986a2dea23d75d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 27 Jun 2024 13:52:42 +0800 Subject: [PATCH 44/55] Logo (Builtin): support `--logo-position right` Fix #1034 --- src/logo/logo.c | 100 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index 96386336f..51b990aab 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -53,54 +53,54 @@ static void ffLogoPrintCharsRaw(const char* data, size_t length) } } -void ffLogoPrintChars(const char* data, bool doColorReplacement) +// If result is NULL, calculate logo width +// Returns logo height +static uint32_t logoAppendChars(const char* data, bool doColorReplacement, FFstrbuf* result) { FFOptionsLogo* options = &instance.config.logo; - uint32_t currentlineLength = 0; + uint32_t logoHeight = 0; - FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048); - - if (!instance.config.display.pipe && instance.config.display.brightColor) - ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT); - - ffStrbufAppendNC(&result, options->paddingTop, '\n'); - ffStrbufAppendNC(&result, options->paddingLeft, ' '); - - instance.state.logoHeight = options->paddingTop; - - //Use logoColor[0] as the default color - if(doColorReplacement && !instance.config.display.pipe) - ffStrbufAppendF(&result, "\e[%sm", options->colors[0].chars); + if (result) + { + if (options->position != FF_LOGO_POSITION_RIGHT) + ffStrbufAppendNC(result, options->paddingLeft, ' '); + else + ffStrbufAppendF(result, "\e[9999999C\e[%dD", options->paddingRight + instance.state.logoWidth); + } while(*data != '\0') { //We are at the end of a line. Print paddings and update max line length if(*data == '\n' || (*data == '\r' && *(data + 1) == '\n')) { - ffStrbufAppendNC(&result, options->paddingRight, ' '); - //We have \r\n, skip the \r if(*data == '\r') ++data; - ffStrbufAppendC(&result, '\n'); + if(result) ffStrbufAppendC(result, '\n'); ++data; - ffStrbufAppendNC(&result, options->paddingLeft, ' '); + if (result) + { + if (options->position != FF_LOGO_POSITION_RIGHT) + ffStrbufAppendNC(result, options->paddingLeft, ' '); + else + ffStrbufAppendF(result, "\e[9999999C\e[%dD", options->paddingRight + instance.state.logoWidth); + } if(currentlineLength > instance.state.logoWidth) instance.state.logoWidth = currentlineLength; currentlineLength = 0; - ++instance.state.logoHeight; + ++logoHeight; continue; } //Always print tabs as 4 spaces, to have consistent spacing if(*data == '\t') { - ffStrbufAppendNC(&result, 4, ' '); + if(result) ffStrbufAppendNC(result, 4, ' '); ++data; continue; } @@ -110,16 +110,20 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) { const char* start = data; - ffStrbufAppendS(&result, "\e["); + if(result) ffStrbufAppendS(result, "\e["); data += 2; while(ffCharIsDigit(*data) || *data == ';') - ffStrbufAppendC(&result, *data++); // number + { + if(result) ffStrbufAppendC(result, *data); // number + ++data; + } //We have a valid control sequence, print it and continue with next char if(isascii(*data)) { - ffStrbufAppendC(&result, *data++); // single letter, end of control sequence + if(result) ffStrbufAppendC(result, *data); // single letter, end of control sequence + ++data; continue; } @@ -137,7 +141,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) //If we have $$, or $\0, print it as single $ if(*data == '$' || *data == '\0') { - ffStrbufAppendC(&result, '$'); + if(result) ffStrbufAppendC(result, '$'); ++currentlineLength; ++data; continue; @@ -146,18 +150,18 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) if(!instance.config.display.pipe) { //Map the number to an array index, so that '1' -> 0, '2' -> 1, etc. - int index = ((int) *data) - 49; + int index = *data - '1'; //If the index is valid, print the color. Otherwise continue as normal if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS) { - ffStrbufAppendC(&result, '$'); + if(result) ffStrbufAppendC(result, '$'); ++currentlineLength; //Don't continue here, we want to print the current char as unicode } else { - ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars); + if(result) ffStrbufAppendF(result, "\e[%sm", options->colors[index].chars); ++data; continue; } @@ -192,24 +196,54 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) if(*data == '\0') break; - ffStrbufAppendC(&result, *data++); + if(result) ffStrbufAppendC(result, *data); + ++data; } } + //Happens if the last line is the longest + if(currentlineLength > instance.state.logoWidth) + instance.state.logoWidth = currentlineLength; + + return logoHeight; +} + +void ffLogoPrintChars(const char* data, bool doColorReplacement) +{ + FFOptionsLogo* options = &instance.config.logo; + + if (options->position == FF_LOGO_POSITION_RIGHT) + logoAppendChars(data, doColorReplacement, NULL); + + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048); + + if (!instance.config.display.pipe && instance.config.display.brightColor) + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT); + + ffStrbufAppendNC(&result, options->paddingTop, '\n'); + + //Use logoColor[0] as the default color + if(doColorReplacement && !instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[%sm", options->colors[0].chars); + + instance.state.logoHeight = options->paddingTop + logoAppendChars(data, doColorReplacement, &result); if(!instance.config.display.pipe) ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); if(options->position == FF_LOGO_POSITION_LEFT) { - //Happens if the last line is the longest - if(currentlineLength > instance.state.logoWidth) - instance.state.logoWidth = currentlineLength; - instance.state.logoWidth += options->paddingLeft + options->paddingRight; //Go to the leftmost position and go up the height ffStrbufAppendF(&result, "\e[1G\e[%uA", instance.state.logoHeight); } + else if(options->position == FF_LOGO_POSITION_RIGHT) + { + instance.state.logoWidth = 0; + + //Go to the leftmost position and go up the height + ffStrbufAppendF(&result, "\e[1G\e[%uA", instance.state.logoHeight); + } else if (options->position == FF_LOGO_POSITION_TOP) { instance.state.logoWidth = instance.state.logoHeight = 0; From d979f55c8e1f0587d3980bf2dd9db5f474ea3f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 27 Jun 2024 17:49:30 +0800 Subject: [PATCH 45/55] Modules: fix custom key not working if the key is formatted outside Fix #1049 --- src/common/printing.h | 2 +- src/modules/bios/bios.c | 4 ++-- src/modules/cpucache/cpucache.c | 14 +++++++++----- src/modules/diskio/diskio.c | 4 ++-- src/modules/netio/netio.c | 2 +- src/modules/physicaldisk/physicaldisk.c | 2 +- src/modules/physicalmemory/physicalmemory.c | 8 ++------ 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/common/printing.h b/src/common/printing.h index ad02b8047..7ccc645f2 100644 --- a/src/common/printing.h +++ b/src/common/printing.h @@ -5,7 +5,7 @@ typedef enum FFPrintType { FF_PRINT_TYPE_DEFAULT = 0, - FF_PRINT_TYPE_NO_CUSTOM_KEY = 1 << 0, + FF_PRINT_TYPE_NO_CUSTOM_KEY = 1 << 0, // key has been formatted outside FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR = 1 << 1, FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH = 1 << 2, FF_PRINT_TYPE_NO_CUSTOM_OUTPUT_FORMAT = 1 << 3, // reserved diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 5e9d1742c..b9a4fc902 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -50,7 +50,7 @@ void ffPrintBios(FFBiosOptions* options) if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); ffStrbufWriteTo(&bios.version, stdout); if (bios.release.length) printf(" (%s)\n", bios.release.chars); @@ -59,7 +59,7 @@ void ffPrintBios(FFBiosOptions* options) } else { - FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_BIOS_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BIOS_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &bios.date, "date"}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.release, "release"}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.vendor, "vendor"}, diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 31b931e6a..d728929bf 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -12,15 +12,19 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + char levelStr[4] = "L"; for (uint32_t i = 0; i < sizeof (result->caches) / sizeof (result->caches[0]) && result->caches[i].length > 0; i++) { ffStrbufClear(&key); + levelStr[1] = (char) ('1' + i); if (options->moduleArgs.key.length == 0) - ffStrbufAppendF(&key, "%s (L%u)", FF_CPUCACHE_DISPLAY_NAME, i + 1); + ffStrbufAppendF(&key, "%s (%s)", FF_CPUCACHE_DISPLAY_NAME, levelStr); else { - FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 1, ((FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_UINT, &i, "index"}, + uint32_t index = i + 1; + FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 2, ((FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index, "index"}, + {FF_FORMAT_ARG_TYPE_STRING, levelStr, "level"}, })); } @@ -49,14 +53,14 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); ffStrbufPutTo(&buffer, stdout); } else { FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); ffParseSize(sum, &buffer2); - FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_CPUCACHE_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_CPUCACHE_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &buffer, "result"}, {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2, "sum"}, })); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 424226b60..dbe52f061 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -37,7 +37,7 @@ void ffPrintDiskIO(FFDiskIOOptions* options) if(error) { - ffPrintError(FF_DISKIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_DISKIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error); return; } @@ -55,7 +55,7 @@ void ffPrintDiskIO(FFDiskIOOptions* options) if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); ffParseSize(dev->bytesRead, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 10d7a3ca1..cc4a70238 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -57,7 +57,7 @@ void ffPrintNetIO(FFNetIOOptions* options) if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); ffParseSize(inf->rxBytes, &buffer); if (!options->detectTotal) ffStrbufAppendS(&buffer, "/s"); diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 8827eb317..ef042382d 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -70,7 +70,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); if (physicalType[0] || removableType[0] || readOnlyType[0]) { diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index fd748d4c8..c629a3831 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -32,11 +32,7 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey( - FF_PHYSICALMEMORY_DISPLAY_NAME, - result.length == 1 ? 0 : (uint8_t) i, - &options->moduleArgs, - FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_PHYSICALMEMORY_DISPLAY_NAME, result.length == 1 ? 0 : (uint8_t) i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); fputs(prettySize.chars, stdout); fputs(" - ", stdout); @@ -53,7 +49,7 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) } else { - FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_PHYSICALMEMORY_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_PHYSICALMEMORY_DISPLAY_NAME, (uint8_t) i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_PHYSICALMEMORY_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_UINT64, &device->size, "bytes"}, {FF_FORMAT_ARG_TYPE_STRBUF, &prettySize, "size"}, {FF_FORMAT_ARG_TYPE_UINT, &device->maxSpeed, "max-speed"}, From 165aa93fd3b16686dd4017253f4cddcf3f2bb48c Mon Sep 17 00:00:00 2001 From: Carlos Eduardo Date: Wed, 26 Jun 2024 14:28:46 -0300 Subject: [PATCH 46/55] QT: import kvantum theme name --- src/detection/gtk_qt/qt.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/detection/gtk_qt/qt.c b/src/detection/gtk_qt/qt.c index 23558d7b5..e0d8fd81a 100644 --- a/src/detection/gtk_qt/qt.c +++ b/src/detection/gtk_qt/qt.c @@ -135,6 +135,13 @@ static void detectLXQt(FFQtResult* result) ffParsePropFileConfig("pcmanfm-qt/lxqt/settings.conf", "Wallpaper=", &result->wallpaper); } +static void detectKvantum(FFQtResult* result) +{ + ffParsePropFileConfigValues("Kvantum/kvantum.kvconfig", 1, (FFpropquery[]) { + {"theme=", &result->widgetStyle}, + }); +} + const FFQtResult* ffDetectQt(void) { static FFQtResult result; @@ -157,5 +164,11 @@ const FFQtResult* ffDetectQt(void) else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT)) detectLXQt(&result); + if(ffStrbufEqualS(&result.widgetStyle, "kvantum") || ffStrbufEqualS(&result.widgetStyle, "kvantum-dark")) + { + ffStrbufClear(&result.widgetStyle); + detectKvantum(&result); + } + return &result; } From 09782d67e51c63b664cfc5042420ea710d320169 Mon Sep 17 00:00:00 2001 From: Carlos Eduardo Date: Wed, 26 Jun 2024 14:34:16 -0300 Subject: [PATCH 47/55] QT: add qt[56]ct support --- src/detection/gtk_qt/qt.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/detection/gtk_qt/qt.c b/src/detection/gtk_qt/qt.c index e0d8fd81a..ed8465781 100644 --- a/src/detection/gtk_qt/qt.c +++ b/src/detection/gtk_qt/qt.c @@ -135,6 +135,22 @@ static void detectLXQt(FFQtResult* result) ffParsePropFileConfig("pcmanfm-qt/lxqt/settings.conf", "Wallpaper=", &result->wallpaper); } +static void detectQtCt(char qver, FFQtResult* result) +{ + // qt5ct and qt6ct are technically separate applications, but they're both + // by the same author and qt6ct understands qt5ct in qt6 applications as well. + char file[] = "qtXct/qtXct.conf"; + file[2] = file[8] = qver; + ffParsePropFileConfigValues(file, 3, (FFpropquery[]) { + {"style=", &result->widgetStyle}, + {"icon_theme=", &result->icons}, + // FIXME: on older versions this was hex-encoded binary format + // (See QVariant notes on https://doc.qt.io/qt-5/qsettings.html) + // Thankfully, newer versions use the more common font encoding. + {"general=", &result->font} + }); +} + static void detectKvantum(FFQtResult* result) { ffParsePropFileConfigValues("Kvantum/kvantum.kvconfig", 1, (FFpropquery[]) { @@ -158,11 +174,14 @@ const FFQtResult* ffDetectQt(void) ffStrbufInit(&result.wallpaper); const FFDisplayServerResult* wmde = ffConnectDisplayServer(); + const char *qplatformtheme = getenv("QT_QPA_PLATFORMTHEME"); if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA)) detectPlasma(&result); else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT)) detectLXQt(&result); + else if(ffStrSet(qplatformtheme) && (ffStrEquals(qplatformtheme, "qt5ct") || ffStrEquals(qplatformtheme, "qt6ct"))) + detectQtCt(qplatformtheme[2], &result); if(ffStrbufEqualS(&result.widgetStyle, "kvantum") || ffStrbufEqualS(&result.widgetStyle, "kvantum-dark")) { From a9df048d49b706dd33ae4364b4ed17d56ff676bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 27 Jun 2024 20:39:22 +0800 Subject: [PATCH 48/55] Logo (Image): support `--logo-position right` for `iterm` and `kitty-direct` --- src/logo/image/image.c | 32 ++++++++++++++++++++++++++++++-- src/options/logo.c | 3 +-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 495dbccc9..afac5c466 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -84,6 +84,12 @@ static bool printImageIterm(bool printError) ffStrbufAppendNC(&buf, options->paddingTop, '\n'); ffStrbufAppendNC(&buf, options->paddingLeft, ' '); } + else if (options->position == FF_LOGO_POSITION_RIGHT) + { + if (printError) + fputs("Logo (iterm): Must set logo width and height\n", stderr); + return false; + } if (options->width) ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u:%s\a", (unsigned) options->width, base64.chars); else @@ -112,7 +118,10 @@ static bool printImageIterm(bool printError) else { ffStrbufAppendNC(&buf, options->paddingTop, '\n'); - ffStrbufAppendNC(&buf, options->paddingLeft, ' '); + if (options->position == FF_LOGO_POSITION_RIGHT) + ffStrbufAppendF(&buf, "\e[9999999C\e[%uD", (unsigned) options->paddingRight + options->width); + else + ffStrbufAppendF(&buf, "\e[%uC", (unsigned) options->paddingLeft); ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\n", (unsigned) options->width, (unsigned) options->height, @@ -131,6 +140,11 @@ static bool printImageIterm(bool printError) instance.state.logoWidth = instance.state.logoHeight = 0; ffStrbufAppendNC(&buf, options->paddingRight, '\n'); } + else if (options->position == FF_LOGO_POSITION_RIGHT) + { + instance.state.logoWidth = instance.state.logoHeight = 0; + ffStrbufAppendF(&buf, "\e[1G\e[%uA", (unsigned) options->height); + } ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); } @@ -165,6 +179,12 @@ static bool printImageKittyDirect(bool printError) ffPrintCharTimes('\n', options->paddingTop); ffPrintCharTimes(' ', options->paddingLeft); } + else if (options->position == FF_LOGO_POSITION_RIGHT) + { + if (printError) + fputs("Logo (iterm): Must set logo width and height\n", stderr); + return false; + } if (options->width) printf("\e_Ga=T,f=100,t=f,c=%u;%s\e\\", (unsigned) options->width, base64.chars); @@ -193,7 +213,10 @@ static bool printImageKittyDirect(bool printError) else { ffPrintCharTimes('\n', options->paddingTop); - ffPrintCharTimes(' ', options->paddingLeft); + if (options->position == FF_LOGO_POSITION_RIGHT) + printf("\e[9999999C\e[%uD", (unsigned) options->paddingRight + options->width); + else + printf("\e[%uC", (unsigned) options->paddingLeft); printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\n", (unsigned) options->width, @@ -211,6 +234,11 @@ static bool printImageKittyDirect(bool printError) instance.state.logoWidth = instance.state.logoHeight = 0; ffPrintCharTimes('\n', options->paddingRight); } + else if (options->position == FF_LOGO_POSITION_RIGHT) + { + instance.state.logoWidth = instance.state.logoHeight = 0; + printf("\e[1G\e[%uA", (unsigned) options->height); + } } return true; diff --git a/src/options/logo.c b/src/options/logo.c index da526e2b6..717ae21ee 100644 --- a/src/options/logo.c +++ b/src/options/logo.c @@ -373,8 +373,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo }); if (error) return error; - options->chafaCanvasMode = (uint32_t) value; - + options->position = (FFLogoPosition) value; continue; } else if (ffStrEqualsIgnCase(key, "chafa")) From 4370c0944bd2922d7d1f2502deb9400eab5eaddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 27 Jun 2024 23:20:31 +0800 Subject: [PATCH 49/55] Format: trim white spaces after truncation --- src/common/format.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/format.c b/src/common/format.c index 8e1d8736c..5d1938a0d 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -283,6 +283,7 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n if (buffer->length - oldLength > (uint32_t) truncLength) { ffStrbufSubstrBefore(buffer, oldLength + (uint32_t) truncLength); + ffStrbufTrimRightSpace(buffer); if (ellipsis) ffStrbufAppendS(buffer, "…"); } From 3f0ae1350593c68b32b588ff0295094552804a61 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Jun 2024 09:15:09 +0800 Subject: [PATCH 50/55] JsonConfig: clarify the breaking change --- src/options/logo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/options/logo.c b/src/options/logo.c index 717ae21ee..582644c7f 100644 --- a/src/options/logo.c +++ b/src/options/logo.c @@ -110,6 +110,11 @@ logoType: options->preserveAspectRatio = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(subKey, "recache")) options->recache = ffOptionParseBoolean(value); + else if(ffStrEqualsIgnCase(subKey, "separate")) + { + fputs("--logo-separate has been renamed to --logo-position\n", stderr); + exit(477); + } else if(ffStrEqualsIgnCase(subKey, "position")) { options->position = (FFLogoPosition) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { @@ -362,6 +367,8 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo options->recache = yyjson_get_bool(val); continue; } + else if(ffStrEqualsIgnCase(key, "separate")) + return "logo.separate has been renamed to logo.position\n"; else if (ffStrEqualsIgnCase(key, "position")) { int value; From 3d7d02b5c5ff34cb6800b9d8319cfcc6ad7090d0 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Jun 2024 10:05:38 +0800 Subject: [PATCH 51/55] Logo (Image): support `--logo-position right` --- src/logo/image/image.c | 44 +++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index afac5c466..8644f0b02 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -373,12 +373,21 @@ static void printImagePixels(FFLogoRequestData* requestData, const FFstrbuf* res //Write result to stdout ffPrintCharTimes('\n', options->paddingTop); - ffPrintCharTimes(' ', options->paddingLeft); + if (options->position == FF_LOGO_POSITION_RIGHT) + printf("\e[9999999C\e[%uD", (unsigned) options->paddingRight + requestData->logoCharacterWidth); + else + printf("\e[%uC", (unsigned) options->paddingLeft); fflush(stdout); ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), result); - //Go to upper left corner - printf("\e[1G\e[%uA", instance.state.logoHeight); + if (options->position != FF_LOGO_POSITION_TOP) + { + //Go to upper left corner + printf("\e[1G\e[%uA", instance.state.logoHeight); + } + + if (options->position != FF_LOGO_POSITION_LEFT) + instance.state.logoWidth = instance.state.logoHeight = 0; } static bool printImageSixel(FFLogoRequestData* requestData, const ImageData* imageData) @@ -711,7 +720,9 @@ static bool printCachedChars(FFLogoRequestData* requestData) static bool printCachedPixel(FFLogoRequestData* requestData) { - requestData->logoCharacterWidth = instance.config.logo.width; + FFOptionsLogo* options = &instance.config.logo; + + requestData->logoCharacterWidth = options->width; if(requestData->logoCharacterWidth == 0) { requestData->logoCharacterWidth = readCachedUint32(requestData, FF_CACHE_FILE_WIDTH); @@ -719,7 +730,7 @@ static bool printCachedPixel(FFLogoRequestData* requestData) return false; } - requestData->logoCharacterHeight = instance.config.logo.height; + requestData->logoCharacterHeight = options->height; if(requestData->logoCharacterHeight == 0) { requestData->logoCharacterHeight = readCachedUint32(requestData, FF_CACHE_FILE_HEIGHT); @@ -727,7 +738,7 @@ static bool printCachedPixel(FFLogoRequestData* requestData) return false; } - int fd = -1; + FF_AUTO_CLOSE_FD int fd = -1; if(requestData->type == FF_LOGO_TYPE_IMAGE_KITTY) { fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_COMPRESSED); @@ -740,8 +751,11 @@ static bool printCachedPixel(FFLogoRequestData* requestData) if(fd == -1) return false; - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + ffPrintCharTimes('\n', options->paddingTop); + if (options->position == FF_LOGO_POSITION_RIGHT) + printf("\e[9999999C\e[%uD", (unsigned) options->paddingRight + requestData->logoCharacterWidth); + else + printf("\e[%uC", (unsigned) options->paddingLeft); fflush(stdout); char buffer[32768]; @@ -749,13 +763,17 @@ static bool printCachedPixel(FFLogoRequestData* requestData) while((readBytes = ffReadFDData(FFUnixFD2NativeFD(fd), sizeof(buffer), buffer)) > 0) ffWriteFDData(FFUnixFD2NativeFD(STDOUT_FILENO), (size_t) readBytes, buffer); - close(fd); + instance.state.logoWidth = requestData->logoCharacterWidth + options->paddingLeft + options->paddingRight; + instance.state.logoHeight = requestData->logoCharacterHeight + options->paddingTop; - instance.state.logoWidth = requestData->logoCharacterWidth + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = requestData->logoCharacterHeight + instance.config.logo.paddingTop; + if (options->position != FF_LOGO_POSITION_TOP) + { + //Go to upper left corner + printf("\e[1G\e[%uA", instance.state.logoHeight); + } - //Go to upper left corner - printf("\e[1G\e[%uA", instance.state.logoHeight); + if (options->position != FF_LOGO_POSITION_LEFT) + instance.state.logoWidth = instance.state.logoHeight = 0; return true; } From debcc3ca7fec5b08dbf6ff52e76904ed8421f38a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Jun 2024 10:23:38 +0800 Subject: [PATCH 52/55] Logo (Image): improve performance when image is cached --- src/logo/image/image.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 8644f0b02..bb337c3a3 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -10,6 +10,8 @@ #include #elif _WIN32 #include +#elif __linux__ + #include #endif // https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145 @@ -758,10 +760,32 @@ static bool printCachedPixel(FFLogoRequestData* requestData) printf("\e[%uC", (unsigned) options->paddingLeft); fflush(stdout); - char buffer[32768]; - ssize_t readBytes; - while((readBytes = ffReadFDData(FFUnixFD2NativeFD(fd), sizeof(buffer), buffer)) > 0) - ffWriteFDData(FFUnixFD2NativeFD(STDOUT_FILENO), (size_t) readBytes, buffer); + bool sent = false; + #ifdef __linux__ + struct stat st; + if (fstat(fd, &st) >= 0) + { + while (st.st_size > 0) + { + ssize_t bytes = sendfile(STDOUT_FILENO, fd, NULL, (size_t) st.st_size); + if (bytes > 0) + { + sent = true; + st.st_size -= bytes; + } + else + break; + } + } + #endif + + if (!sent) + { + char buffer[32768]; + ssize_t readBytes; + while((readBytes = ffReadFDData(FFUnixFD2NativeFD(fd), sizeof(buffer), buffer)) > 0) + ffWriteFDData(FFUnixFD2NativeFD(STDOUT_FILENO), (size_t) readBytes, buffer); + } instance.state.logoWidth = requestData->logoCharacterWidth + options->paddingLeft + options->paddingRight; instance.state.logoHeight = requestData->logoCharacterHeight + options->paddingTop; From adb6dc537c4c647d1c6636fc7bc42e1280c1014f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Jun 2024 10:33:18 +0800 Subject: [PATCH 53/55] Doc: update readme & changelog --- CHANGELOG.md | 6 +++++- README.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdf40a905..7a5e27f87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Changes: * CMake option `ENABLE_PROPRIETARY_GPU_DRIVER_API` is removed. The GPU driver APIs are now enabled by default. * The option was introduced to reduce the license concerns. Since all non MIT proprietary code has been rewritten manually from scratch, it is no longer necessary. * See for detail +* Option `--logo-separate true` is changed to `--logo-position top` for better readability + * Builtin ascii logos can be positioned on the right side now with`--logo-position right` Features: * Add support for `--gpu-detection-method opencl` which uses OpenCL to detect GPUs. @@ -13,8 +15,9 @@ Features: * Add fast path of version and font detection for kitty (Terminal / TerminalFont) * Make sure `stdin` and `stdout` are TTYs when querying terminal * So modules like `TerminalSize` should work when `stdin` or `stdout` is redirected -* Support argument truncation in `---format` +* Support argument truncation in `---format` (#1043) * See `fastfetch --help format` for detail +* Improve Qt theme detection (#1047, Theme, Linux) * Add new JSON config option `general.preRun`, which is executed before fastfetch prints output. * It can be used to generate a temp logo file. For example ```jsonc @@ -33,6 +36,7 @@ Bugfixes: * Fix invalid path (#1031, LM, Linux) * Fix VMEM detection for Nvidia GPU (requires `--gpu-driver-specific`) (GPU) * Fix AMD `--gpu-driver-specific` for AMD cards (#1032, GPU, Windows) +* Use Coordinated Universal Time rather than timezone-varying local date (#1046) Logo: * Fix colors of Asahi Linux diff --git a/README.md b/README.md index 52dbac052..0efdf80f7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![latest packaged version(s)](https://repology.org/badge/latest-versions/fastfetch.svg)](https://repology.org/project/fastfetch/versions) [![Packaging status](https://repology.org/badge/tiny-repos/fastfetch.svg)](https://repology.org/project/fastfetch/versions) -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 mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported. +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 mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, macOS, SunOS and Windows 7+ are supported. From b94a322dfc330914244e20d83b7f71da7022371f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Jun 2024 10:34:42 +0800 Subject: [PATCH 54/55] Release: v2.17.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92d586291..7fc5d0e06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.16.0 + VERSION 2.17.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From 0c1462898b68d97a4ef76ecdfa8d7c04f71cac52 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Jun 2024 10:50:37 +0800 Subject: [PATCH 55/55] TerminalShell / TerminalFont: fix CodeQL warnings --- src/detection/terminalfont/terminalfont.c | 2 +- src/detection/terminalshell/terminalshell.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 18fc8eec7..63e0a6fc0 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -271,7 +271,7 @@ static bool queryKittyTerm(const char* query, FFstrbuf* res) for (const char* p = buffer; p[0] && p[1]; p += 2) { unsigned value; - if (sscanf(p, "%2x", &value)) + if (sscanf(p, "%2x", &value) == 1) ffStrbufAppendC(res, (char) value); } return true; diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index e0246ea37..28bd7c591 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -490,7 +490,7 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) for (const char* p = versionHex; p[0] && p[1]; p += 2) { unsigned value; - if (sscanf(p, "%2x", &value)) + if (sscanf(p, "%2x", &value) == 1) ffStrbufAppendC(version, (char) value); } return true;