From 25e81b39f9539a440c3927e4f1f8e3bc6453912d Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Tue, 24 Jan 2023 10:39:33 +0100 Subject: [PATCH 001/119] Bluetooth module --- CHANGELOG.md | 5 + CMakeLists.txt | 4 + README.md | 4 +- completions/bash | 4 + presets/all | 2 +- presets/verbose | 1 + src/common/dbus.c | 201 +++++++++++++++++ src/common/dbus.h | 57 +++++ src/common/init.c | 2 + src/data/config_user.txt | 3 + src/data/modules.txt | 1 + src/detection/bluetooth/bluetooth.c | 21 ++ src/detection/bluetooth/bluetooth.h | 19 ++ src/detection/bluetooth/bluetooth_linux.c | 200 +++++++++++++++++ src/detection/media/media_linux.c | 262 +++++----------------- src/fastfetch.c | 12 + src/fastfetch.h | 2 + src/modules/bluetooth.c | 36 +++ 18 files changed, 622 insertions(+), 214 deletions(-) create mode 100644 src/common/dbus.c create mode 100644 src/common/dbus.h create mode 100644 src/detection/bluetooth/bluetooth.c create mode 100644 src/detection/bluetooth/bluetooth.h create mode 100644 src/detection/bluetooth/bluetooth_linux.c create mode 100644 src/modules/bluetooth.c diff --git a/CHANGELOG.md b/CHANGELOG.md index b4fba05d4..5400ffdcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# dev + +Features: +* Bluetooth module + # 1.9.0 Notable Changes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d257dab7..29e6c62de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,6 +232,7 @@ set(LIBFASTFETCH_SRC src/common/printing.c src/common/properties.c src/common/settings.c + src/detection/bluetooth/bluetooth.c src/detection/cpu/cpu.c src/detection/cpuUsage/cpuUsage.c src/detection/datetime.c @@ -254,6 +255,7 @@ set(LIBFASTFETCH_SRC src/logo/logo.c src/modules/battery.c src/modules/bios.c + src/modules/bluetooth.c src/modules/board.c src/modules/brightness.c src/modules/break.c @@ -308,6 +310,7 @@ set(LIBFASTFETCH_SRC if(LINUX) list(APPEND LIBFASTFETCH_SRC + src/common/dbus.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_linux.c @@ -318,6 +321,7 @@ if(LINUX) src/detection/cpu/cpu_linux.c src/detection/cpuUsage/cpuUsage_linux.c src/detection/cursor/cursor_linux.c + src/detection/bluetooth/bluetooth_linux.c src/detection/disk/disk_linux.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/wayland.c diff --git a/README.md b/README.md index c1d5dbb99..45a092552 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ The following libraries are used if present at runtime: * [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol. * [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. * [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol. -* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song. +* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Bluetooth, Player & Media detection. * [`libEGL`](https://www.khronos.org/registry/EGL/), [`libGLX`](https://dri.freedesktop.org/wiki/GLX/), [`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation. @@ -88,7 +88,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme ``` ##### Builtin logos diff --git a/completions/bash b/completions/bash index 7c32c4cc3..246a4904a 100644 --- a/completions/bash +++ b/completions/bash @@ -42,6 +42,7 @@ __fastfetch_complete_help() "vulkan-format" "opengl-format" "opencl-format" + "bluetooth-format" ) COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD")) } @@ -349,6 +350,9 @@ __fastfetch_completion() "--users-key" "--users-format" "--users-error" + "--bluetooth-key" + "--bluetooth-format" + "--bluetooth-error" ) local FF_OPTIONS_PATH=( diff --git a/presets/all b/presets/all index 85be11eef..7a44f5bad 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Weather:Break:Colors diff --git a/presets/verbose b/presets/verbose index 57711c43d..991fecb7f 100644 --- a/presets/verbose +++ b/presets/verbose @@ -28,3 +28,4 @@ --vulkan-format driver: {}; Api Version: {}; Conformance Version: {} --opengl-format version: {}; renderer: {}; vendor: {} --opencl-format version: {}; device: {}; vendor: {} +--bluetooth-format Name: {}; Address: {}; Type: {}; Battery: {} diff --git a/src/common/dbus.c b/src/common/dbus.c new file mode 100644 index 000000000..e053be9a5 --- /dev/null +++ b/src/common/dbus.c @@ -0,0 +1,201 @@ +#include "dbus.h" + +#include "common/thread.h" + +static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib) +{ + FF_LIBRARY_LOAD(dbus, &instance->config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4); + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_has_next, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false) + + return true; +} + +static const FFDBusLibrary* loadLib(const FFinstance* instance) +{ + static FFDBusLibrary lib; + static bool loaded = false; + static bool loadSuccess = false; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; + + ffThreadMutexLock(&mutex); + + if(!loaded) + { + loaded = true; + loadSuccess = loadLibSymbols(instance, &lib); + } + + ffThreadMutexUnlock(&mutex); + return loadSuccess ? &lib : NULL; +} + +const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data) +{ + data->lib = loadLib(instance); + if(data->lib == NULL) + return "Failed to load DBus library"; + + data->connection = data->lib->ffdbus_bus_get(busType, NULL); + if(data->connection == NULL) + return "Failed to connect to DBus"; + + return NULL; +} + +bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) +{ + int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); + + if(argType == DBUS_TYPE_STRING) + { + const char* value = NULL; + dbus->lib->ffdbus_message_iter_get_basic(iter, &value); + + if(!ffStrSet(value)) + return false; + + ffStrbufAppendS(result, value); + return true; + } + + if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY) + return false; + + DBusMessageIter subIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); + + if(argType == DBUS_TYPE_VARIANT) + return ffDBusGetValue(dbus, &subIter, result); + + //At this point we have an array + + bool foundAValue = false; + + while(true) + { + if(ffDBusGetValue(dbus, &subIter, result)) + { + foundAValue = true; + ffStrbufAppendS(result, ", "); + } + + FF_DBUS_ITER_CONTINUE(dbus, &subIter); + } + + if(foundAValue) + ffStrbufSubstrBefore(result, result->length - 2); + + return foundAValue; +} + +bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result) +{ + int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); + + if(argType == DBUS_TYPE_BOOLEAN) + { + dbus_bool_t value = 0; + dbus->lib->ffdbus_message_iter_get_basic(iter, &value); + *result = value != 0; + return true; + } + + if(argType != DBUS_TYPE_VARIANT) + return false; + + DBusMessageIter subIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); + return ffDBusGetBool(dbus, &subIter, result); +} + +bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result) +{ + int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); + + if(argType == DBUS_TYPE_BYTE) + { + dbus->lib->ffdbus_message_iter_get_basic(iter, result); + return true; + } + + if(argType != DBUS_TYPE_VARIANT) + return false; + + DBusMessageIter subIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); + return ffDBusGetByte(dbus, &subIter, result); +} + +DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method) +{ + DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method); + if(message == NULL) + return NULL; + + DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); + + dbus->lib->ffdbus_message_unref(message); + + return reply; +} + +DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property) +{ + DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get"); + if(message == NULL) + return NULL; + + DBusMessageIter requestIterator; + dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator); + + if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface)) + { + dbus->lib->ffdbus_message_unref(message); + return NULL; + } + + if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property)) + { + dbus->lib->ffdbus_message_unref(message); + return NULL; + } + + DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); + + dbus->lib->ffdbus_message_unref(message); + + return reply; +} + +void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result) +{ + DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property); + if(reply == NULL) + return; + + DBusMessageIter rootIterator; + if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) + { + dbus->lib->ffdbus_message_unref(reply); + return; + } + + ffDBusGetValue(dbus, &rootIterator, result); + + dbus->lib->ffdbus_message_unref(reply); +} diff --git a/src/common/dbus.h b/src/common/dbus.h new file mode 100644 index 000000000..7f0fa2402 --- /dev/null +++ b/src/common/dbus.h @@ -0,0 +1,57 @@ +#pragma once + +#ifndef FF_INCLUDED_common_dbus +#define FF_INCLUDED_common_dbus + +#ifdef FF_HAVE_DBUS +#include + +#include "util/FFstrbuf.h" +#include "common/library.h" + +#define FF_DBUS_TIMEOUT_MILLISECONDS 35 + +#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \ + { \ + if(!(dbus)->lib->ffdbus_message_iter_has_next(iterator)) \ + break; \ + (dbus)->lib->ffdbus_message_iter_next(iterator); \ + continue; \ + } + +typedef struct FFDBusLibrary +{ + FF_LIBRARY_SYMBOL(dbus_bus_get) + FF_LIBRARY_SYMBOL(dbus_message_new_method_call) + FF_LIBRARY_SYMBOL(dbus_message_iter_init) + FF_LIBRARY_SYMBOL(dbus_message_iter_init_append) + FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic) + FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type) + FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic) + FF_LIBRARY_SYMBOL(dbus_message_iter_recurse) + FF_LIBRARY_SYMBOL(dbus_message_iter_has_next) + FF_LIBRARY_SYMBOL(dbus_message_iter_next) + FF_LIBRARY_SYMBOL(dbus_message_unref) + FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block) + FF_LIBRARY_SYMBOL(dbus_connection_flush) + FF_LIBRARY_SYMBOL(dbus_pending_call_block) + FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply) + FF_LIBRARY_SYMBOL(dbus_pending_call_unref) +} FFDBusLibrary; + +typedef struct FFDBusData +{ + const FFDBusLibrary* lib; + DBusConnection* connection; +} FFDBusData; + +const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success +bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result); +bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result); +bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result); +DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method); +DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property); +void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result); + +#endif // FF_HAVE_DBUS +#endif // FF_INCLUDED_common_dbus diff --git a/src/common/init.c b/src/common/init.c index e4f106e94..67cd43535 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -115,6 +115,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.openGL); initModuleArg(&instance->config.openCL); initModuleArg(&instance->config.users); + initModuleArg(&instance->config.bluetooth); ffStrbufInitA(&instance->config.libPCI, 0); ffStrbufInitA(&instance->config.libVulkan, 0); @@ -377,6 +378,7 @@ static void destroyConfig(FFinstance* instance) destroyModuleArg(&instance->config.openGL); destroyModuleArg(&instance->config.openCL); destroyModuleArg(&instance->config.users); + destroyModuleArg(&instance->config.bluetooth); ffStrbufDestroy(&instance->config.libPCI); ffStrbufDestroy(&instance->config.libVulkan); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 0e987509e..56b164ebf 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -295,6 +295,7 @@ #--opengl-key OpenGL #--opencl-key OpenCL #--users-key Users +#--bluetooth-key Bluetooth # Format options: # Sets the format string for module values. @@ -339,6 +340,7 @@ #--opengl-format #--opencl-format #--users-format +#--bluetooth-format # Error options: # Sets the format string to use if an error occured @@ -383,6 +385,7 @@ #--opengl-error #--opencl-error #--users-error +#--bluetooth-error # Library options: # Sets an user specific path to a library to load. diff --git a/src/data/modules.txt b/src/data/modules.txt index 586c2de1d..e83353ec9 100644 --- a/src/data/modules.txt +++ b/src/data/modules.txt @@ -1,5 +1,6 @@ Battery Bios +Bluetooth Board Break Chassis diff --git a/src/detection/bluetooth/bluetooth.c b/src/detection/bluetooth/bluetooth.c new file mode 100644 index 000000000..4fd3d55af --- /dev/null +++ b/src/detection/bluetooth/bluetooth.c @@ -0,0 +1,21 @@ +#include "bluetooth.h" + +#include "../internal.h" + +void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth); + +const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance) +{ + FF_DETECTION_INTERNAL_GUARD(FFBluetoothResult, + ffStrbufInit(&result.error); + ffStrbufInit(&result.name); + ffStrbufInit(&result.address); + ffStrbufInit(&result.type); + result.battery = 0; + + ffDetectBluetoothImpl(instance, &result); + + if(result.error.length == 0 && result.name.length == 0) + ffStrbufAppendS(&result.error, "No bluetooth device found"); + ) +} diff --git a/src/detection/bluetooth/bluetooth.h b/src/detection/bluetooth/bluetooth.h new file mode 100644 index 000000000..6fb09415d --- /dev/null +++ b/src/detection/bluetooth/bluetooth.h @@ -0,0 +1,19 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_bluetooth_bluetooth +#define FF_INCLUDED_detection_bluetooth_bluetooth + +#include "fastfetch.h" + +typedef struct FFBluetoothResult +{ + FFstrbuf error; + FFstrbuf name; + FFstrbuf address; + FFstrbuf type; + uint8_t battery; // 0-100% +} FFBluetoothResult; + +const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance); + +#endif diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c new file mode 100644 index 000000000..6ed0ab7bc --- /dev/null +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -0,0 +1,200 @@ +#include "bluetooth.h" + +#ifdef FF_HAVE_DBUS +#include "common/dbus.h" + +/* Example dbus reply, striped to only the relevant parts: +array [ //root + dict entry( //object + object path "/org/bluez/hci0/dev_03_21_8B_91_16_4D" + array [ + dict entry( //property + string "org.bluez.Device1" + array [ + dict entry( + string "Address" + variant string "03:21:8B:91:16:4D" + ) + dict entry( + string "Name" + variant string "JBL TUNE160BT" + ) + dict entry( + string "Connected" + variant boolean true + ) + ] + ) + dict entry( //property + string "org.bluez.Battery1" + array [ + dict entry( + string "Percentage" + variant byte 100 + ) + ] + ) + ] + ) +] +*/ + +static void detectBluetoothProperty(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter, bool* connected) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) + return; + + DBusMessageIter dictIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) + return; + + const char* propertyType; + dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType); + + if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL) + return; //We don't care about other properties + + dbus->lib->ffdbus_message_iter_next(&dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) + return; + + DBusMessageIter arrayIter; + dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); + + while(true) + { + if(dbus->lib->ffdbus_message_iter_get_arg_type(&arrayIter) != DBUS_TYPE_DICT_ENTRY) + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter) + + DBusMessageIter deviceIter; + dbus->lib->ffdbus_message_iter_recurse(&arrayIter, &deviceIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&deviceIter) != DBUS_TYPE_STRING) + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter) + + const char* deviceProperty; + dbus->lib->ffdbus_message_iter_get_basic(&deviceIter, &deviceProperty); + + dbus->lib->ffdbus_message_iter_next(&deviceIter); + + if(strcmp(deviceProperty, "Address") == 0) + ffDBusGetValue(dbus, &deviceIter, &bluetooth->address); + else if(strcmp(deviceProperty, "Name") == 0) + ffDBusGetValue(dbus, &deviceIter, &bluetooth->name); + else if(strcmp(deviceProperty, "Icon") == 0) + ffDBusGetValue(dbus, &deviceIter, &bluetooth->type); + else if(strcmp(deviceProperty, "Percentage") == 0) + ffDBusGetByte(dbus, &deviceIter, &bluetooth->battery); + else if(strcmp(deviceProperty, "Connected") == 0) + { + ffDBusGetBool(dbus, &deviceIter, connected); + if(!*connected) + return; //Just for performance, we don't need to continue if we're not connected + } + + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); + } +} + +static bool detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) + return false; + + DBusMessageIter dictIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH) + return false; + + const char* objectPath; + dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath); + + //We don't want adapter objects + if(strstr(objectPath, "dev_") == NULL) + return false; + + dbus->lib->ffdbus_message_iter_next(&dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) + return false; + + DBusMessageIter arrayIter; + dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); + + bool connected = false; + + while(true) + { + detectBluetoothProperty(bluetooth, dbus, &arrayIter, &connected); + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); + } + + if(!connected || bluetooth->name.length == 0) + { + ffStrbufClear(&bluetooth->address); + ffStrbufClear(&bluetooth->name); + ffStrbufClear(&bluetooth->type); + bluetooth->battery = 0; + return false; + } + + return true; +} + +static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + DBusMessageIter arrayIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter); + + while(true) + { + if(detectBluetoothObject(bluetooth, dbus, &arrayIter)) + return; + + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); + } + + return; +} + +static const char* detectBluetooth(const FFinstance* instance, FFBluetoothResult* bluetooth) +{ + FFDBusData dbus; + const char* error = ffDBusLoadData(instance, DBUS_BUS_SYSTEM, &dbus); + if(error) + return error; + + DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + if(!managedObjects) + return "Failed to call GetManagedObjects"; + + DBusMessageIter rootIter; + if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter)) + { + dbus.lib->ffdbus_message_unref(managedObjects); + return "Failed to get root iterator of GetManagedObjects"; + } + + detectBluetoothRoot(bluetooth, &dbus, &rootIter); + + dbus.lib->ffdbus_message_unref(managedObjects); + return NULL; +} + +#endif + +void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth) +{ + #ifdef FF_HAVE_DBUS + ffStrbufAppendS(&bluetooth->error, detectBluetooth(instance, bluetooth)); + #else + ffStrbufAppendS(&bluetooth->error, "Fastfetch was compiled without DBus support"); + #endif +} diff --git a/src/detection/media/media_linux.c b/src/detection/media/media_linux.c index f8d410593..d41ce1e4f 100644 --- a/src/detection/media/media_linux.c +++ b/src/detection/media/media_linux.c @@ -8,208 +8,75 @@ #define FF_DBUS_TIMEOUT_MILLISECONDS 35 #ifdef FF_HAVE_DBUS +#include "common/dbus.h" #include "common/library.h" #include "common/parsing.h" -#include -#define FF_DBUS_ITER_CONTINUE(iterator) \ - { \ - if(!data->ffdbus_message_iter_has_next(&iterator)) \ - break; \ - data->ffdbus_message_iter_next(&iterator); \ - continue; \ - } - -typedef struct DBusData +static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result) { - FF_LIBRARY_SYMBOL(dbus_message_new_method_call) - FF_LIBRARY_SYMBOL(dbus_message_iter_init) - FF_LIBRARY_SYMBOL(dbus_message_iter_init_append) - FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic) - FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type) - FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic) - FF_LIBRARY_SYMBOL(dbus_message_iter_recurse) - FF_LIBRARY_SYMBOL(dbus_message_iter_has_next) - FF_LIBRARY_SYMBOL(dbus_message_iter_next) - FF_LIBRARY_SYMBOL(dbus_message_unref) - FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply) - FF_LIBRARY_SYMBOL(dbus_connection_flush) - FF_LIBRARY_SYMBOL(dbus_pending_call_block) - FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply) - FF_LIBRARY_SYMBOL(dbus_pending_call_unref) - - DBusConnection *connection; -} DBusData; - -static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data) -{ - int argType = data->ffdbus_message_iter_get_arg_type(iter); - - if(argType == DBUS_TYPE_STRING) - { - const char* value = NULL; - data->ffdbus_message_iter_get_basic(iter, &value); - - if(!ffStrSet(value)) - return false; - - ffStrbufAppendS(result, value); - return true; - } - - if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY) - return false; - - DBusMessageIter subIter; - data->ffdbus_message_iter_recurse(iter, &subIter); - - if(argType == DBUS_TYPE_VARIANT) - return getValue(&subIter, result, data); - - //At this point we have an array - - bool foundAValue = false; - - while(true) - { - if(getValue(&subIter, result, data)) - { - foundAValue = true; - ffStrbufAppendS(result, ", "); - } - - FF_DBUS_ITER_CONTINUE(subIter); - } - - if(foundAValue) - ffStrbufSubstrBefore(result, result->length - 2); - - return foundAValue; -} - -static DBusMessage* getReply(DBusMessage* request, DBusData* data) -{ - DBusPendingCall* pendingCall = NULL; - dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, FF_DBUS_TIMEOUT_MILLISECONDS); - data->ffdbus_message_unref(request); - if(!succesfull || pendingCall == NULL) - return NULL; - - data->ffdbus_connection_flush(data->connection); - data->ffdbus_pending_call_block(pendingCall); - - DBusMessage* reply = data->ffdbus_pending_call_steal_reply(pendingCall); - data->ffdbus_pending_call_unref(pendingCall); - return reply; -} - -static DBusMessage* getProperty(const char* busName, const char* objectPath, const char* interface, const char* property, DBusData* data) -{ - DBusMessage* message = data->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get"); - if(message == NULL) - return NULL; - - DBusMessageIter requestIterator; - data->ffdbus_message_iter_init_append(message, &requestIterator); - - if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface)) - { - data->ffdbus_message_unref(message); - return NULL; - } - - if(!data->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property)) - { - data->ffdbus_message_unref(message); - return NULL; - } - - return getReply(message, data); -} - -static void getPropertyString(const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result, DBusData* data) -{ - DBusMessage* reply = getProperty(busName, objectPath, interface, property, data); - if(reply == NULL) - return; - - DBusMessageIter rootIterator; - if(!data->ffdbus_message_iter_init(reply, &rootIterator)) - { - data->ffdbus_message_unref(reply); - return; - } - - getValue(&rootIterator, result, data); - - data->ffdbus_message_unref(reply); -} - -static bool getBusProperties(const char* busName, FFMediaResult* result, DBusData* data) -{ - DBusMessage* reply = getProperty(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata", data); + DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata"); if(reply == NULL) return false; DBusMessageIter rootIterator; - if(!data->ffdbus_message_iter_init(reply, &rootIterator)) + if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator)) { - data->ffdbus_message_unref(reply); + data->lib->ffdbus_message_unref(reply); return false; } - if(data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT) + if(data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_VARIANT) { - data->ffdbus_message_unref(reply); + data->lib->ffdbus_message_unref(reply); return false; } DBusMessageIter variantIterator; - data->ffdbus_message_iter_recurse(&rootIterator, &variantIterator); - if(data->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY) + data->lib->ffdbus_message_iter_recurse(&rootIterator, &variantIterator); + if(data->lib->ffdbus_message_iter_get_arg_type(&variantIterator) != DBUS_TYPE_ARRAY) { - data->ffdbus_message_unref(reply); + data->lib->ffdbus_message_unref(reply); return false; } DBusMessageIter arrayIterator; - data->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator); + data->lib->ffdbus_message_iter_recurse(&variantIterator, &arrayIterator); while(true) { - if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY) - FF_DBUS_ITER_CONTINUE(arrayIterator) + if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) DBusMessageIter dictIterator; - data->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator); + data->lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator); - if(data->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING) - FF_DBUS_ITER_CONTINUE(arrayIterator) + if(data->lib->ffdbus_message_iter_get_arg_type(&dictIterator) != DBUS_TYPE_STRING) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) - if(!data->ffdbus_message_iter_has_next(&dictIterator)) - FF_DBUS_ITER_CONTINUE(arrayIterator) + if(!data->lib->ffdbus_message_iter_has_next(&dictIterator)) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) const char* key; - data->ffdbus_message_iter_get_basic(&dictIterator, &key); + data->lib->ffdbus_message_iter_get_basic(&dictIterator, &key); - data->ffdbus_message_iter_next(&dictIterator); + data->lib->ffdbus_message_iter_next(&dictIterator); if(strcmp(key, "xesam:title") == 0) - getValue(&dictIterator, &result->song, data); + ffDBusGetValue(data, &dictIterator, &result->song); else if(strcmp(key, "xesam:album") == 0) - getValue(&dictIterator, &result->album, data); + ffDBusGetValue(data, &dictIterator, &result->album); else if(strcmp(key, "xesam:artist") == 0) - getValue(&dictIterator, &result->artist, data); + ffDBusGetValue(data, &dictIterator, &result->artist); else if(strcmp(key, "xesam:url") == 0) - getValue(&dictIterator, &result->url, data); + ffDBusGetValue(data, &dictIterator, &result->url); if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0) break; - FF_DBUS_ITER_CONTINUE(arrayIterator) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) } - data->ffdbus_message_unref(reply); + data->lib->ffdbus_message_unref(reply); if(result->song.length == 0) { @@ -223,20 +90,20 @@ static bool getBusProperties(const char* busName, FFMediaResult* result, DBusDat ffStrbufAppendS(&result->busNameShort, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1); //We found a song, get the player name - getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player, data); + ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "Identity", &result->player); if(result->player.length == 0) - getPropertyString(busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player, data); + ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2", "DesktopEntry", &result->player); if(result->player.length == 0) ffStrbufAppend(&result->player, &result->busNameShort); return true; } -static void getCustomBus(const FFinstance* instance, FFMediaResult* result, DBusData* data) +static void getCustomBus(FFDBusData* data, const FFinstance* instance, FFMediaResult* result) { if(ffStrbufStartsWithS(&instance->config.playerName, FF_DBUS_MPRIS_PREFIX)) { - getBusProperties(instance->config.playerName.chars, result, data); + getBusProperties(data, instance->config.playerName.chars, result); return; } @@ -244,88 +111,61 @@ static void getCustomBus(const FFinstance* instance, FFMediaResult* result, DBus ffStrbufInit(&busName); ffStrbufAppendS(&busName, FF_DBUS_MPRIS_PREFIX); ffStrbufAppend(&busName, &instance->config.playerName); - getBusProperties(busName.chars, result, data); + getBusProperties(data, busName.chars, result); ffStrbufDestroy(&busName); } -static void getBestBus(FFMediaResult* result, DBusData* data) +static void getBestBus(FFDBusData* data, FFMediaResult* result) { if( - getBusProperties(FF_DBUS_MPRIS_PREFIX"spotify", result, data) || - getBusProperties(FF_DBUS_MPRIS_PREFIX"vlc", result, data) || - getBusProperties(FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result, data) + getBusProperties(data, FF_DBUS_MPRIS_PREFIX"spotify", result) || + getBusProperties(data, FF_DBUS_MPRIS_PREFIX"vlc", result) || + getBusProperties(data, FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result) ) return; - DBusMessage* message = data->ffdbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames"); - if(message == NULL) - return; - - DBusMessage* reply = getReply(message, data); + DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames"); if(reply == NULL) return; DBusMessageIter rootIterator; - if(!data->ffdbus_message_iter_init(reply, &rootIterator) || data->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY) + if(!data->lib->ffdbus_message_iter_init(reply, &rootIterator) || data->lib->ffdbus_message_iter_get_arg_type(&rootIterator) != DBUS_TYPE_ARRAY) return; DBusMessageIter arrayIterator; - data->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator); + data->lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator); while(true) { - if(data->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING) - FF_DBUS_ITER_CONTINUE(arrayIterator) + if(data->lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_STRING) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) const char* busName; - data->ffdbus_message_iter_get_basic(&arrayIterator, &busName); + data->lib->ffdbus_message_iter_get_basic(&arrayIterator, &busName); if(strncmp(busName, FF_DBUS_MPRIS_PREFIX, sizeof(FF_DBUS_MPRIS_PREFIX) - 1) != 0) - FF_DBUS_ITER_CONTINUE(arrayIterator) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) - if(getBusProperties(busName, result, data)) + if(getBusProperties(data, busName, result)) break; - FF_DBUS_ITER_CONTINUE(arrayIterator) + FF_DBUS_ITER_CONTINUE(data, &arrayIterator) } - data->ffdbus_message_unref(reply); + data->lib->ffdbus_message_unref(reply); } static const char* getMedia(const FFinstance* instance, FFMediaResult* result) { - DBusData data; - - FF_LIBRARY_LOAD(dbus, &instance->config.libDBus, "dlopen dbus failed", "libdbus-1" FF_LIBRARY_EXTENSION, 4); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dbus, dbus_bus_get) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_new_method_call) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_init) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_init_append) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_append_basic) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_get_arg_type) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_get_basic) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_recurse) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_has_next) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_iter_next) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_message_unref) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_connection_send_with_reply) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_connection_flush) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_pending_call_block) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_pending_call_steal_reply) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(dbus, data, dbus_pending_call_unref) - - data.connection = ffdbus_bus_get(DBUS_BUS_SESSION, NULL); - if(data.connection == NULL) - { - dlclose(dbus); - return "Failed to connect to session dbus"; - } + FFDBusData data; + const char* error = ffDBusLoadData(instance, DBUS_BUS_SESSION, &data); + if(error != NULL) + return error; if(instance->config.playerName.length > 0) - getCustomBus(instance, result, &data); + getCustomBus(&data, instance, result); else - getBestBus(result, &data); + getBestBus(&data, result); - dlclose(dbus); return NULL; } diff --git a/src/fastfetch.c b/src/fastfetch.c index 18c130ef2..771071d94 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -448,6 +448,15 @@ static inline void printCommandHelp(const char* command) "vendor" ); } + else if(strcasecmp(command, "bluetooth-format") == 0) + { + constructAndPrintCommandHelpFormat("bluetooth", "{1} (4%)", 4, + "Name", + "Address", + "Type", + "Battery percentage" + ); + } else fprintf(stderr, "No specific help for command %s provided\n", command); } @@ -1208,6 +1217,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "opengl", &instance->config.openGL)) {} else if(optionParseModuleArgs(key, value, "opencl", &instance->config.openCL)) {} else if(optionParseModuleArgs(key, value, "users", &instance->config.users)) {} + else if(optionParseModuleArgs(key, value, "bluetooth", &instance->config.bluetooth)) {} /////////////////// //Library options// @@ -1503,6 +1513,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintUsers(instance); else if(strcasecmp(line, "command") == 0) ffPrintCommand(instance); + else if(strcasecmp(line, "bluetooth") == 0) + ffPrintBluetooth(instance); else ffPrintErrorString(instance, line, 0, NULL, NULL, ""); } diff --git a/src/fastfetch.h b/src/fastfetch.h index 69121e4c9..c72f3e19b 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -139,6 +139,7 @@ typedef struct FFconfig FFModuleArgs openGL; FFModuleArgs openCL; FFModuleArgs users; + FFModuleArgs bluetooth; FFstrbuf libPCI; FFstrbuf libVulkan; @@ -310,5 +311,6 @@ void ffPrintOpenGL(FFinstance* instance); void ffPrintOpenCL(FFinstance* instance); void ffPrintUsers(FFinstance* instance); void ffPrintCommand(FFinstance* instance); +void ffPrintBluetooth(FFinstance* instance); #endif diff --git a/src/modules/bluetooth.c b/src/modules/bluetooth.c new file mode 100644 index 000000000..c68e90380 --- /dev/null +++ b/src/modules/bluetooth.c @@ -0,0 +1,36 @@ +#include "common/printing.h" +#include "detection/bluetooth/bluetooth.h" + +#define FF_BLUETOOTH_MODULE_NAME "Bluetooth" +#define FF_BLUETOOTH_NUM_FORMAT_ARGS 4 + +void ffPrintBluetooth(FFinstance* instance) +{ + const FFBluetoothResult* bluetooth = ffDetectBluetooth(instance); + + if(bluetooth->error.length > 0) + { + ffPrintError(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth, "%s", bluetooth->error.chars); + return; + } + + if(instance->config.bluetooth.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth.key); + ffStrbufWriteTo(&bluetooth->name, stdout); + + if(bluetooth->battery > 0) + printf(" (%d%%)", bluetooth->battery); + + putchar('\n'); + } + else + { + ffPrintFormat(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth, FF_BLUETOOTH_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->address}, + {FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->type}, + {FF_FORMAT_ARG_TYPE_UINT8, &bluetooth->battery} + }); + } +} From 4967d0a22288ff58409ec86248396862ec5ae4f6 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Tue, 24 Jan 2023 10:46:00 +0100 Subject: [PATCH 002/119] Bluetooth: Build on unsupported platforms --- CMakeLists.txt | 5 +++++ src/detection/bluetooth/bluetooth_nosupport.c | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 src/detection/bluetooth/bluetooth_nosupport.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 67d7dc1c4..47543fab6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -357,6 +357,7 @@ elseif(ANDROID) src/common/processing_linux.c src/detection/battery/battery_android.c src/detection/bios/bios_nosupport.c + src/detection/bluetooth/bluetooth_nosupport.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_nosupport.c @@ -388,11 +389,13 @@ elseif(ANDROID) ) elseif(BSD) list(APPEND LIBFASTFETCH_SRC + src/common/dbus.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c src/detection/battery/battery_bsd.c src/detection/bios/bios_bsd.c + src/detection/bluetooth/bluetooth_linux.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_nosupport.c @@ -435,6 +438,7 @@ elseif(APPLE) src/common/sysctl.c src/detection/battery/battery_apple.c src/detection/bios/bios_apple.c + src/detection/bluetooth/bluetooth_nosupport.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_apple.c src/detection/chassis/chassis_nosupport.c @@ -473,6 +477,7 @@ elseif(WIN32) src/common/processing_windows.c src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c + src/detection/bluetooth/bluetooth_nosupport.c src/detection/board/board_windows.c src/detection/brightness/brightness_windows.cpp src/detection/chassis/chassis_nosupport.c diff --git a/src/detection/bluetooth/bluetooth_nosupport.c b/src/detection/bluetooth/bluetooth_nosupport.c new file mode 100644 index 000000000..1bb524a02 --- /dev/null +++ b/src/detection/bluetooth/bluetooth_nosupport.c @@ -0,0 +1,6 @@ +#include "bluetooth.h" + +void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth) +{ + ffStrbufAppendS(&bluetooth->error, "Bluetooth not supported on this platform"); +} From 209d0c98d9dad58ce1fbcf0047783fa025395156 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Tue, 24 Jan 2023 12:02:20 +0100 Subject: [PATCH 003/119] Bluetooth: Support multiple devices --- completions/bash | 1 + src/common/init.c | 2 + src/data/config_user.txt | 6 +++ src/data/help.txt | 61 ++++++++++++----------- src/detection/bluetooth/bluetooth.c | 8 +-- src/detection/bluetooth/bluetooth.h | 10 +++- src/detection/bluetooth/bluetooth_linux.c | 52 +++++++++---------- src/fastfetch.c | 2 + src/fastfetch.h | 2 + src/modules/bluetooth.c | 54 ++++++++++++++------ 10 files changed, 117 insertions(+), 81 deletions(-) diff --git a/completions/bash b/completions/bash index 246a4904a..2542c6887 100644 --- a/completions/bash +++ b/completions/bash @@ -199,6 +199,7 @@ __fastfetch_completion() "--gpu-hide-integrated" "--gpu-hide-discrete" "--disk-show-unknown" + "--bluetooth-show-disconnected" ) local FF_OPTIONS_STRING=( diff --git a/src/common/init.c b/src/common/init.c index 67cd43535..67ce0a35e 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -160,6 +160,8 @@ static void defaultConfig(FFinstance* instance) instance->config.diskShowUnknown = false; instance->config.diskShowSubvolumes = false; + instance->config.bluetoothShowDisconnected = false; + ffStrbufInitA(&instance->config.batteryDir, 0); ffStrbufInitA(&instance->config.separatorString, 0); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 56b164ebf..39cba21e8 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -247,6 +247,12 @@ # Default is "/:/home" ("C:\\;D:\\ ..." on Windows). #--disk-folders /:/home +# Bluetooth show disconnected option +# Sets if disconnected bluetooth devices should be printed +# Must be either true or false +# Default is false. +#--bluetooth-show-disconnected false + # Percentage output type option # Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported. # Only works with default format ( without --module-format option ). diff --git a/src/data/help.txt b/src/data/help.txt index b8a546c9c..0a335e660 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -100,36 +100,37 @@ Library options: Set the path of a library to load --lib-cjson Module specific options: - --title-fqdn : Set if the title should use fully qualified domain name. Default is false - --separator-string : Set the string printed by the separator module - --os-file : Set the path to the file containing OS information - --shell-version : Set if shell version should be detected and printed - --terminal-version : Set if terminal version should be detected and printed - --disk-folders : A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows) - --disk-show-removable : Set if removable volume should be printed. Default is true - --disk-show-hidden : Set if hidden volumes should be printed. Default is false - --disk-show-subvolumes : Set if subvolumes should be printed. Default is false - --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false - --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ - --cpu-temp : Detect and display CPU temperature if supported. Default is false - --gpu-temp : Detect and display GPU temperature if supported. Default is false - --gpu-hide-integrated : Hide integrated GPU if supported. Default is false - --gpu-hide-discrete : Hide discrete GPU if supported. Default is false - --battery-temp : Detect and display Battery temperature if supported. Default is false - --localip-show-ipv4 : Show IPv4 addresses in local ip module. Default is true - --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false - --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false - --localip-name-prefix : Show IPs with given name prefix only. Default is empty - --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) - --public-ip-url: The URL of public IP detection server to be used. - --weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0) - --weather-output-format: The output weather format to be used. It must be URI encoded. - --player-name: The name of the player to use - --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto - --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 - --command-shell : Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others - --command-key : Set the module key to display, can be specified mulitple times - --command-text : Set the command text to be executed, can be specified mulitple times + --title-fqdn : Set if the title should use fully qualified domain name. Default is false + --separator-string : Set the string printed by the separator module + --os-file : Set the path to the file containing OS information + --shell-version : Set if shell version should be detected and printed + --terminal-version : Set if terminal version should be detected and printed + --disk-folders : A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows) + --disk-show-removable : Set if removable volume should be printed. Default is true + --disk-show-hidden : Set if hidden volumes should be printed. Default is false + --disk-show-subvolumes : Set if subvolumes should be printed. Default is false + --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false + --bluetooth-show-disconnected: : Set if disconnected bluetooth devices should be printed. Default is false + --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ + --cpu-temp : Detect and display CPU temperature if supported. Default is false + --gpu-temp : Detect and display GPU temperature if supported. Default is false + --gpu-hide-integrated : Hide integrated GPU if supported. Default is false + --gpu-hide-discrete : Hide discrete GPU if supported. Default is false + --battery-temp : Detect and display Battery temperature if supported. Default is false + --localip-show-ipv4 : Show IPv4 addresses in local ip module. Default is true + --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false + --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false + --localip-name-prefix : Show IPs with given name prefix only. Default is empty + --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) + --public-ip-url: The URL of public IP detection server to be used. + --weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0) + --weather-output-format: The output weather format to be used. It must be URI encoded. + --player-name: The name of the player to use + --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto + --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 + --command-shell : Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others + --command-key : Set the module key to display, can be specified mulitple times + --command-text : Set the command text to be executed, can be specified mulitple times Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci" If a value starts with a ?, it is optional. "true" will be used if not set. diff --git a/src/detection/bluetooth/bluetooth.c b/src/detection/bluetooth/bluetooth.c index 4fd3d55af..f254fe535 100644 --- a/src/detection/bluetooth/bluetooth.c +++ b/src/detection/bluetooth/bluetooth.c @@ -8,14 +8,8 @@ const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance) { FF_DETECTION_INTERNAL_GUARD(FFBluetoothResult, ffStrbufInit(&result.error); - ffStrbufInit(&result.name); - ffStrbufInit(&result.address); - ffStrbufInit(&result.type); - result.battery = 0; + ffListInit(&result.devices, sizeof(FFBluetoothDevice)); ffDetectBluetoothImpl(instance, &result); - - if(result.error.length == 0 && result.name.length == 0) - ffStrbufAppendS(&result.error, "No bluetooth device found"); ) } diff --git a/src/detection/bluetooth/bluetooth.h b/src/detection/bluetooth/bluetooth.h index 6fb09415d..ccd6ecd22 100644 --- a/src/detection/bluetooth/bluetooth.h +++ b/src/detection/bluetooth/bluetooth.h @@ -5,13 +5,19 @@ #include "fastfetch.h" -typedef struct FFBluetoothResult +typedef struct FFBluetoothDevice { - FFstrbuf error; FFstrbuf name; FFstrbuf address; FFstrbuf type; uint8_t battery; // 0-100% + bool connected; +} FFBluetoothDevice; + +typedef struct FFBluetoothResult +{ + FFstrbuf error; + FFlist devices; // List of FFBluetoothDevice } FFBluetoothResult; const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance); diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index 6ed0ab7bc..4751db6c0 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -39,7 +39,7 @@ array [ //root ] */ -static void detectBluetoothProperty(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter, bool* connected) +static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device) { if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) return; @@ -81,68 +81,66 @@ static void detectBluetoothProperty(FFBluetoothResult* bluetooth, FFDBusData* db dbus->lib->ffdbus_message_iter_next(&deviceIter); if(strcmp(deviceProperty, "Address") == 0) - ffDBusGetValue(dbus, &deviceIter, &bluetooth->address); + ffDBusGetValue(dbus, &deviceIter, &device->address); else if(strcmp(deviceProperty, "Name") == 0) - ffDBusGetValue(dbus, &deviceIter, &bluetooth->name); + ffDBusGetValue(dbus, &deviceIter, &device->name); else if(strcmp(deviceProperty, "Icon") == 0) - ffDBusGetValue(dbus, &deviceIter, &bluetooth->type); + ffDBusGetValue(dbus, &deviceIter, &device->type); else if(strcmp(deviceProperty, "Percentage") == 0) - ffDBusGetByte(dbus, &deviceIter, &bluetooth->battery); + ffDBusGetByte(dbus, &deviceIter, &device->battery); else if(strcmp(deviceProperty, "Connected") == 0) - { - ffDBusGetBool(dbus, &deviceIter, connected); - if(!*connected) - return; //Just for performance, we don't need to continue if we're not connected - } + ffDBusGetBool(dbus, &deviceIter, &device->connected); FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); } } -static bool detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter) +static void detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter) { if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) - return false; + return; DBusMessageIter dictIter; dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH) - return false; + return; const char* objectPath; dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath); //We don't want adapter objects if(strstr(objectPath, "dev_") == NULL) - return false; + return; dbus->lib->ffdbus_message_iter_next(&dictIter); if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) - return false; + return; DBusMessageIter arrayIter; dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); - bool connected = false; + FFBluetoothDevice* device = ffListAdd(&bluetooth->devices); + ffStrbufInit(&device->name); + ffStrbufInit(&device->address); + ffStrbufInit(&device->type); + device->battery = 0; + device->connected = false; while(true) { - detectBluetoothProperty(bluetooth, dbus, &arrayIter, &connected); + detectBluetoothProperty(dbus, &arrayIter, device); FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); } - if(!connected || bluetooth->name.length == 0) + if(device->name.length == 0) { - ffStrbufClear(&bluetooth->address); - ffStrbufClear(&bluetooth->name); - ffStrbufClear(&bluetooth->type); - bluetooth->battery = 0; - return false; + ffStrbufDestroy(&device->name); + ffStrbufDestroy(&device->address); + ffStrbufDestroy(&device->type); + --bluetooth->devices.length; } - - return true; } static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter) @@ -155,9 +153,7 @@ static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, while(true) { - if(detectBluetoothObject(bluetooth, dbus, &arrayIter)) - return; - + detectBluetoothObject(bluetooth, dbus, &arrayIter); FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); } diff --git a/src/fastfetch.c b/src/fastfetch.c index f93b95893..8cf0233e5 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1310,6 +1310,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.diskShowSubvolumes = optionParseBoolean(value); else if(strcasecmp(key, "--disk-show-unknown") == 0) instance->config.diskShowUnknown = optionParseBoolean(value); + else if(strcasecmp(key, "--bluetooth-show-disconnected") == 0) + instance->config.bluetoothShowDisconnected = optionParseBoolean(value); else if(strcasecmp(key, "--battery-dir") == 0) optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index c72f3e19b..caf2fc8d6 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -184,6 +184,8 @@ typedef struct FFconfig bool diskShowUnknown; bool diskShowSubvolumes; + bool bluetoothShowDisconnected; + FFstrbuf batteryDir; FFstrbuf separatorString; diff --git a/src/modules/bluetooth.c b/src/modules/bluetooth.c index c68e90380..c4c483e1e 100644 --- a/src/modules/bluetooth.c +++ b/src/modules/bluetooth.c @@ -4,6 +4,29 @@ #define FF_BLUETOOTH_MODULE_NAME "Bluetooth" #define FF_BLUETOOTH_NUM_FORMAT_ARGS 4 +static void printDevice(FFinstance* instance, const FFBluetoothDevice* device, uint8_t index) +{ + if(instance->config.bluetooth.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_BLUETOOTH_MODULE_NAME, index, &instance->config.bluetooth.key); + ffStrbufWriteTo(&device->name, stdout); + + if(device->battery > 0) + printf(" (%d%%)", device->battery); + + putchar('\n'); + } + else + { + ffPrintFormat(instance, FF_BLUETOOTH_MODULE_NAME, index, &instance->config.bluetooth, FF_BLUETOOTH_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->address}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->type}, + {FF_FORMAT_ARG_TYPE_UINT8, &device->battery} + }); + } +} + void ffPrintBluetooth(FFinstance* instance) { const FFBluetoothResult* bluetooth = ffDetectBluetooth(instance); @@ -14,23 +37,26 @@ void ffPrintBluetooth(FFinstance* instance) return; } - if(instance->config.bluetooth.outputFormat.length == 0) + FFlist filtered; + ffListInit(&filtered, sizeof(FFBluetoothDevice*)); + + FF_LIST_FOR_EACH(FFBluetoothDevice, device, bluetooth->devices) { - ffPrintLogoAndKey(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth.key); - ffStrbufWriteTo(&bluetooth->name, stdout); + if(!device->connected && !instance->config.bluetoothShowDisconnected) + continue; - if(bluetooth->battery > 0) - printf(" (%d%%)", bluetooth->battery); - - putchar('\n'); + *(FFBluetoothDevice**)ffListAdd(&filtered) = device; } - else + + if(filtered.length == 0) { - ffPrintFormat(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth, FF_BLUETOOTH_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->name}, - {FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->address}, - {FF_FORMAT_ARG_TYPE_STRBUF, &bluetooth->type}, - {FF_FORMAT_ARG_TYPE_UINT8, &bluetooth->battery} - }); + ffPrintError(instance, FF_BLUETOOTH_MODULE_NAME, 0, &instance->config.bluetooth, "No bluetooth devices found"); + return; + } + + for(uint32_t i = 0; i < filtered.length; i++) + { + uint8_t index = (uint8_t) (filtered.length == 1 ? 0 : i + 1); + printDevice(instance, *(FFBluetoothDevice**)ffListGet(&filtered, i), index); } } From 85599fcf53232f2c753d8660c70f0b7dd3d4c0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Jan 2023 21:01:21 +0800 Subject: [PATCH 004/119] Bluetooth (Windows): add support Limitation: no HLE devices, no battery level --- CMakeLists.txt | 3 +- src/detection/bluetooth/bluetooth_windows.c | 109 ++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/detection/bluetooth/bluetooth_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 47543fab6..d585a6b1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -477,7 +477,7 @@ elseif(WIN32) src/common/processing_windows.c src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c - src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetooth/bluetooth_windows.c src/detection/board/board_windows.c src/detection/brightness/brightness_windows.cpp src/detection/chassis/chassis_nosupport.c @@ -682,6 +682,7 @@ if(APPLE) elseif(WIN32) target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601) target_link_libraries(libfastfetch + PRIVATE "bthprops" PRIVATE "dwmapi" PRIVATE "gdi32" PRIVATE "iphlpapi" diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c new file mode 100644 index 000000000..61af30d67 --- /dev/null +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -0,0 +1,109 @@ +#include "bluetooth.h" +#include "util/windows/unicode.h" + +#include + +void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth) +{ + BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { + .fReturnConnected = TRUE, + .fReturnRemembered = TRUE, + .fReturnAuthenticated = TRUE, + .fReturnUnknown = TRUE, + .dwSize = sizeof(btsp) + }; + + BLUETOOTH_DEVICE_INFO btdi = { + .dwSize = sizeof(btdi) + }; + HBLUETOOTH_DEVICE_FIND hFind = BluetoothFindFirstDevice(&btsp, &btdi); + if(!hFind) + ffStrbufAppendS(&bluetooth->error, "BluetoothFindFirstDevice() failed or no devices found"); + + do { + FFBluetoothDevice* device = ffListAdd(&bluetooth->devices); + ffStrbufInit(&device->name); + ffStrbufInit(&device->address); + ffStrbufInit(&device->type); + device->battery = 0; + device->connected = !!btdi.fConnected; + + ffStrbufSetWS(&device->name, btdi.szName); + for (uint32_t i = 0; i < sizeof(btdi.Address.rgBytes) / sizeof(btdi.Address.rgBytes); ++i) + ffStrbufAppendF(&device->address, "%X:", btdi.Address.rgBytes[i]); + ffStrbufTrimRight(&device->name, ':'); + //https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf + + if(BitTest(&btdi.ulClassofDevice, 13)) + ffStrbufAppendS(&device->type, "Limited Discoverable Mode, "); + if(BitTest(&btdi.ulClassofDevice, 14)) + ffStrbufAppendS(&device->type, "LE audio, "); + if(BitTest(&btdi.ulClassofDevice, 15)) + ffStrbufAppendS(&device->type, "Reserved for future use, "); + if(BitTest(&btdi.ulClassofDevice, 16)) + ffStrbufAppendS(&device->type, "Positioning, "); + if(BitTest(&btdi.ulClassofDevice, 17)) + ffStrbufAppendS(&device->type, "Networking, "); + if(BitTest(&btdi.ulClassofDevice, 18)) + ffStrbufAppendS(&device->type, "Rendering, "); + if(BitTest(&btdi.ulClassofDevice, 19)) + ffStrbufAppendS(&device->type, "Capturing, "); + if(BitTest(&btdi.ulClassofDevice, 20)) + ffStrbufAppendS(&device->type, "Object Transfer, "); + if(BitTest(&btdi.ulClassofDevice, 21)) + ffStrbufAppendS(&device->type, "Audio, "); + if(BitTest(&btdi.ulClassofDevice, 22)) + ffStrbufAppendS(&device->type, "Telephony, "); + if(BitTest(&btdi.ulClassofDevice, 23)) + ffStrbufAppendS(&device->type, "Information, "); + + if(device->type.length == 0) + { + uint32_t majorDeviceClasses = (btdi.ulClassofDevice >> 8) & ~(UINT32_MAX << 5); + switch(majorDeviceClasses) + { + case 0b00000: + ffStrbufAppendS(&device->type, "Miscellaneous"); + break; + case 0b00001: + ffStrbufAppendS(&device->type, "Computer"); + break; + case 0b00010: + ffStrbufAppendS(&device->type, "Phone"); + break; + case 0b00011: + ffStrbufAppendS(&device->type, "LAN/Network Access point"); + break; + case 0b00100: + ffStrbufAppendS(&device->type, "Audio/Video"); + break; + case 0b00101: + ffStrbufAppendS(&device->type, "Peripheral"); + break; + case 0b00110: + ffStrbufAppendS(&device->type, "Imaging"); + break; + case 0b00111: + ffStrbufAppendS(&device->type, "Wearable"); + break; + case 0b01000: + ffStrbufAppendS(&device->type, "Toy"); + break; + case 0b01001: + ffStrbufAppendS(&device->type, "Health"); + break; + case 0b11111: + ffStrbufAppendS(&device->type, "Uncategorized"); + break; + default: + ffStrbufAppendS(&device->type, "Unknown"); + break; + } + } + else + { + ffStrbufTrimRight(&device->type, ' '); + ffStrbufTrimRight(&device->type, ','); + } + } while (BluetoothFindNextDevice(hFind, &btdi)); +} From e598598ca8d5db9c32148b47b677ed048efe13be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Jan 2023 22:13:53 +0800 Subject: [PATCH 005/119] Bluetooth (macOS): add support Limitation: no battery level --- CMakeLists.txt | 3 +- src/detection/bluetooth/bluetooth_apple.m | 93 +++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/detection/bluetooth/bluetooth_apple.m diff --git a/CMakeLists.txt b/CMakeLists.txt index d585a6b1c..e1fc0fdae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -438,7 +438,7 @@ elseif(APPLE) src/common/sysctl.c src/detection/battery/battery_apple.c src/detection/bios/bios_apple.c - src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetooth/bluetooth_apple.m src/detection/board/board_nosupport.c src/detection/brightness/brightness_apple.c src/detection/chassis/chassis_nosupport.c @@ -676,6 +676,7 @@ if(APPLE) PRIVATE "-framework Cocoa" PRIVATE "-framework CoreWLAN" PRIVATE "-framework CoreVideo" + PRIVATE "-framework IOBluetooth" PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks" PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks" ) diff --git a/src/detection/bluetooth/bluetooth_apple.m b/src/detection/bluetooth/bluetooth_apple.m new file mode 100644 index 000000000..8affb9074 --- /dev/null +++ b/src/detection/bluetooth/bluetooth_apple.m @@ -0,0 +1,93 @@ +#include "bluetooth.h" + +#import + +void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth) +{ + NSArray* ioDevices = IOBluetoothDevice.pairedDevices; + if(!ioDevices) + { + ffStrbufAppendS(&bluetooth->error, "IOBluetoothDevice.pairedDevices failed"); + return; + } + + for(IOBluetoothDevice* ioDevice in ioDevices) + { + FFBluetoothDevice* device = ffListAdd(&bluetooth->devices); + ffStrbufInitS(&device->name, ioDevice.name.UTF8String); + ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String); + ffStrbufInit(&device->type); + device->battery = 0; + device->connected = !!ioDevice.isConnected; + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode) + ffStrbufAppendS(&device->type, "Limited Discoverable Mode, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved1) + ffStrbufAppendS(&device->type, "LE audio, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved2) + ffStrbufAppendS(&device->type, "Reserved for future use, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorPositioning) + ffStrbufAppendS(&device->type, "Positioning, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorNetworking) + ffStrbufAppendS(&device->type, "Networking, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorRendering) + ffStrbufAppendS(&device->type, "Rendering, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorCapturing) + ffStrbufAppendS(&device->type, "Capturing, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorObjectTransfer) + ffStrbufAppendS(&device->type, "Object Transfer, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorAudio) + ffStrbufAppendS(&device->type, "Audio, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorTelephony) + ffStrbufAppendS(&device->type, "Telephony, "); + if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorInformation) + ffStrbufAppendS(&device->type, "Information, "); + + if(device->type.length == 0) + { + switch(ioDevice.deviceClassMajor) + { + case kBluetoothDeviceClassMajorMiscellaneous: + ffStrbufAppendS(&device->type, "Miscellaneous"); + break; + case kBluetoothDeviceClassMajorComputer: + ffStrbufAppendS(&device->type, "Computer"); + break; + case kBluetoothDeviceClassMajorPhone: + ffStrbufAppendS(&device->type, "Phone"); + break; + case kBluetoothDeviceClassMajorLANAccessPoint: + ffStrbufAppendS(&device->type, "LAN/Network Access point"); + break; + case kBluetoothDeviceClassMajorAudio: + ffStrbufAppendS(&device->type, "Audio/Video"); + break; + case kBluetoothDeviceClassMajorPeripheral: + ffStrbufAppendS(&device->type, "Peripheral"); + break; + case kBluetoothDeviceClassMajorImaging: + ffStrbufAppendS(&device->type, "Imaging"); + break; + case kBluetoothDeviceClassMajorWearable: + ffStrbufAppendS(&device->type, "Wearable"); + break; + case kBluetoothDeviceClassMajorToy: + ffStrbufAppendS(&device->type, "Toy"); + break; + case kBluetoothDeviceClassMajorHealth: + ffStrbufAppendS(&device->type, "Health"); + break; + case kBluetoothDeviceClassMajorUnclassified: + ffStrbufAppendS(&device->type, "Uncategorized"); + break; + default: + ffStrbufAppendS(&device->type, "Unknown"); + break; + } + } + else + { + ffStrbufTrimRight(&device->type, ' '); + ffStrbufTrimRight(&device->type, ','); + } + } +} From 0f2022bd4036d10cc21be88726ebe3a0647c9825 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 25 Jan 2023 00:02:54 +0100 Subject: [PATCH 006/119] Bluetooth: Don't leak memory --- src/modules/bluetooth.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/bluetooth.c b/src/modules/bluetooth.c index c4c483e1e..6038acf01 100644 --- a/src/modules/bluetooth.c +++ b/src/modules/bluetooth.c @@ -59,4 +59,6 @@ void ffPrintBluetooth(FFinstance* instance) uint8_t index = (uint8_t) (filtered.length == 1 ? 0 : i + 1); printDevice(instance, *(FFBluetoothDevice**)ffListGet(&filtered, i), index); } + + ffListDestroy(&filtered); } From d83232430635da16d5d91584762f51f4454f5edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Jan 2023 14:28:13 +0800 Subject: [PATCH 007/119] Sound (macOS): new module --- CMakeLists.txt | 7 +++ presets/all | 2 +- src/common/init.c | 3 ++ src/data/config_user.txt | 9 ++++ src/data/help.txt | 1 + src/detection/sound/sound.h | 18 +++++++ src/detection/sound/sound_apple.c | 77 +++++++++++++++++++++++++++ src/detection/sound/sound_nosupport.c | 6 +++ src/fastfetch.c | 5 ++ src/fastfetch.h | 4 ++ src/modules/sound.c | 68 +++++++++++++++++++++++ 11 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/detection/sound/sound.h create mode 100644 src/detection/sound/sound_apple.c create mode 100644 src/detection/sound/sound_nosupport.c create mode 100644 src/modules/sound.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e1fc0fdae..83a3591fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,6 +289,7 @@ set(LIBFASTFETCH_SRC src/modules/display.c src/modules/separator.c src/modules/shell.c + src/modules/sound.c src/modules/media.c src/modules/terminal.c src/modules/terminalfont.c @@ -341,6 +342,7 @@ if(LINUX) src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_linux.c src/detection/qt.c + src/detection/sound/sound_nosupport.c src/detection/swap/swap_linux.c src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c @@ -377,6 +379,7 @@ elseif(ANDROID) src/detection/packages/packages_linux.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_linux.c + src/detection/sound/sound_nosupport.c src/detection/swap/swap_linux.c src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_android.c @@ -421,6 +424,7 @@ elseif(BSD) src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_bsd.c src/detection/qt.c + src/detection/sound/sound_nosupport.c src/detection/swap/swap_bsd.c src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c @@ -459,6 +463,7 @@ elseif(APPLE) src/detection/packages/packages_apple.c src/detection/poweradapter/poweradapter_apple.c src/detection/processes/processes_bsd.c + src/detection/sound/sound_apple.c src/detection/swap/swap_apple.c src/detection/temps/temps_apple.c src/detection/terminalfont/terminalfont_apple.m @@ -497,6 +502,7 @@ elseif(WIN32) src/detection/packages/packages_windows.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_windows.cpp + src/detection/sound/sound_nosupport.c src/detection/swap/swap_windows.cpp src/detection/terminalfont/terminalfont_windows.c src/detection/terminalshell/terminalshell_windows.cpp @@ -675,6 +681,7 @@ if(APPLE) PRIVATE "-framework OpenCL" PRIVATE "-framework Cocoa" PRIVATE "-framework CoreWLAN" + PRIVATE "-framework CoreAudio" PRIVATE "-framework CoreVideo" PRIVATE "-framework IOBluetooth" PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks" diff --git a/presets/all b/presets/all index 7a44f5bad..dfcaccc44 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Weather:Break:Colors diff --git a/src/common/init.c b/src/common/init.c index 67ce0a35e..63f866282 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -116,6 +116,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.openCL); initModuleArg(&instance->config.users); initModuleArg(&instance->config.bluetooth); + initModuleArg(&instance->config.sound); ffStrbufInitA(&instance->config.libPCI, 0); ffStrbufInitA(&instance->config.libVulkan, 0); @@ -162,6 +163,8 @@ static void defaultConfig(FFinstance* instance) instance->config.bluetoothShowDisconnected = false; + instance->config.soundShowAll = false; + ffStrbufInitA(&instance->config.batteryDir, 0); ffStrbufInitA(&instance->config.separatorString, 0); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 39cba21e8..7bf147397 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -253,6 +253,12 @@ # Default is false. #--bluetooth-show-disconnected false +# Sound show all option +# Sets if all sound devices should be printed +# Must be either true or false +# Default is false ( only main device should be printed ). +#--sound-show-all false + # Percentage output type option # Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported. # Only works with default format ( without --module-format option ). @@ -302,6 +308,7 @@ #--opencl-key OpenCL #--users-key Users #--bluetooth-key Bluetooth +#--sound-key Sound # Format options: # Sets the format string for module values. @@ -347,6 +354,7 @@ #--opencl-format #--users-format #--bluetooth-format +#--sound-format # Error options: # Sets the format string to use if an error occured @@ -392,6 +400,7 @@ #--opencl-error #--users-error #--bluetooth-error +#--sound-error # Library options: # Sets an user specific path to a library to load. diff --git a/src/data/help.txt b/src/data/help.txt index 0a335e660..d91b442ba 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -111,6 +111,7 @@ Module specific options: --disk-show-subvolumes : Set if subvolumes should be printed. Default is false --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false --bluetooth-show-disconnected: : Set if disconnected bluetooth devices should be printed. Default is false + --sound-show-all: : Set if all sound devices should be printed. Default is false --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ --cpu-temp : Detect and display CPU temperature if supported. Default is false --gpu-temp : Detect and display GPU temperature if supported. Default is false diff --git a/src/detection/sound/sound.h b/src/detection/sound/sound.h new file mode 100644 index 000000000..ecbc53db5 --- /dev/null +++ b/src/detection/sound/sound.h @@ -0,0 +1,18 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_sound_sound +#define FF_INCLUDED_detection_sound_sound + +#include "fastfetch.h" + +typedef struct FFSoundDevice +{ + FFstrbuf name; + FFstrbuf manufacturer; + uint8_t volume; // 0-100% + bool main; +} FFSoundDevice; + +const char* ffDetectSound(const FFinstance* instance, FFlist* devices /* List of FFSoundDevice */); + +#endif diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c new file mode 100644 index 000000000..8ede08f28 --- /dev/null +++ b/src/detection/sound/sound_apple.c @@ -0,0 +1,77 @@ +#include "sound.h" +#include "util/apple/cf_helpers.h" + +#include + +const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFSoundDevice */) +{ + AudioDeviceID mainDeviceId; + UInt32 dataSize = sizeof(mainDeviceId); + if(AudioObjectGetPropertyData(kAudioObjectSystemObject, &(AudioObjectPropertyAddress){ + kAudioHardwarePropertyDefaultOutputDevice, + kAudioDevicePropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &mainDeviceId) != kAudioHardwareNoError) + return "AudioObjectGetPropertyData(kAudioHardwarePropertyDefaultOutputDevice) failed"; + + AudioDeviceID deviceIds[32]; + dataSize = sizeof(deviceIds); + if(AudioObjectGetPropertyData(kAudioObjectSystemObject, &(AudioObjectPropertyAddress){ + kAudioHardwarePropertyDevices, + kAudioDevicePropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &deviceIds) != kAudioHardwareNoError) + return "AudioObjectGetPropertyData(kAudioHardwarePropertyDevices) failed"; + + for(uint32_t index = 0, length = dataSize / sizeof(*deviceIds); index < length; ++index) + { + AudioDeviceID deviceId = deviceIds[index]; + + uint32_t muted; + dataSize = sizeof(muted); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyMute, + kAudioDevicePropertyScopeOutput, + 0 + }, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError) + continue; + + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); + device->main = deviceId == mainDeviceId; + device->volume = 0; + ffStrbufInit(&device->name); + ffStrbufInit(&device->manufacturer); + + if (!muted) + { + float volume; + dataSize = sizeof(volume); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyVolumeScalar, + kAudioDevicePropertyScopeOutput, + 0 + }, 0, NULL, &dataSize, &volume) == kAudioHardwareNoError) + device->volume = (uint8_t) (volume * 100 + 0.5); + } + + CFStringRef name; + dataSize = sizeof(name); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioObjectPropertyName, + kAudioDevicePropertyScopeOutput, + 0 + }, 0, NULL, &dataSize, &name) == kAudioHardwareNoError) + ffCfStrGetString(name, &device->name); + + CFStringRef manufacturer; + dataSize = sizeof(manufacturer); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioObjectPropertyManufacturer, + kAudioDevicePropertyScopeOutput, + 0 + }, 0, NULL, &dataSize, &manufacturer) == kAudioHardwareNoError) + ffCfStrGetString(manufacturer, &device->manufacturer); + } + + return NULL; +} diff --git a/src/detection/sound/sound_nosupport.c b/src/detection/sound/sound_nosupport.c new file mode 100644 index 000000000..8f8014341 --- /dev/null +++ b/src/detection/sound/sound_nosupport.c @@ -0,0 +1,6 @@ +#include "sound.h" + +const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */) +{ + return "Not supported on this platform"; +} diff --git a/src/fastfetch.c b/src/fastfetch.c index 8cf0233e5..1febd5f8b 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1220,6 +1220,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "opencl", &instance->config.openCL)) {} else if(optionParseModuleArgs(key, value, "users", &instance->config.users)) {} else if(optionParseModuleArgs(key, value, "bluetooth", &instance->config.bluetooth)) {} + else if(optionParseModuleArgs(key, value, "sound", &instance->config.sound)) {} /////////////////// //Library options// @@ -1312,6 +1313,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.diskShowUnknown = optionParseBoolean(value); else if(strcasecmp(key, "--bluetooth-show-disconnected") == 0) instance->config.bluetoothShowDisconnected = optionParseBoolean(value); + else if(strcasecmp(key, "--sound-show-all") == 0) + instance->config.soundShowAll = optionParseBoolean(value); else if(strcasecmp(key, "--battery-dir") == 0) optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) @@ -1519,6 +1522,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintCommand(instance); else if(strcasecmp(line, "bluetooth") == 0) ffPrintBluetooth(instance); + else if(strcasecmp(line, "sound") == 0) + ffPrintSound(instance); else ffPrintErrorString(instance, line, 0, NULL, NULL, ""); } diff --git a/src/fastfetch.h b/src/fastfetch.h index caf2fc8d6..54a27f85e 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -140,6 +140,7 @@ typedef struct FFconfig FFModuleArgs openCL; FFModuleArgs users; FFModuleArgs bluetooth; + FFModuleArgs sound; FFstrbuf libPCI; FFstrbuf libVulkan; @@ -201,6 +202,8 @@ typedef struct FFconfig FFstrbuf weatherOutputFormat; uint32_t weatherTimeout; + bool soundShowAll; + FFstrbuf osFile; FFstrbuf playerName; @@ -314,5 +317,6 @@ void ffPrintOpenCL(FFinstance* instance); void ffPrintUsers(FFinstance* instance); void ffPrintCommand(FFinstance* instance); void ffPrintBluetooth(FFinstance* instance); +void ffPrintSound(FFinstance* instance); #endif diff --git a/src/modules/sound.c b/src/modules/sound.c new file mode 100644 index 000000000..7b68c0f81 --- /dev/null +++ b/src/modules/sound.c @@ -0,0 +1,68 @@ +#include "common/printing.h" +#include "detection/sound/sound.h" + +#define FF_SOUND_MODULE_NAME "Sound" +#define FF_SOUND_NUM_FORMAT_ARGS 4 + +static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8_t index) +{ + if(instance->config.sound.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_SOUND_MODULE_NAME, index, &instance->config.sound.key); + ffStrbufWriteTo(&device->name, stdout); + + if(device->volume > 0) + printf(" (%d%%)", device->volume); + else + fputs(" (muted)", stdout); + if(device->main && instance->config.soundShowAll) + puts(" (*)"); + else + putchar('\n'); + } + else + { + ffPrintFormat(instance, FF_SOUND_MODULE_NAME, index, &instance->config.sound, FF_SOUND_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_BOOL, &device->main}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, + {FF_FORMAT_ARG_TYPE_UINT8, &device->volume}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->manufacturer} + }); + } +} + +void ffPrintSound(FFinstance* instance) +{ + FF_LIST_AUTO_DESTROY result; + ffListInit(&result, sizeof(FFSoundDevice)); + const char* error = ffDetectSound(instance, &result); + + if(error) + { + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &instance->config.sound, "%s", error); + return; + } + + if(result.length == 0) + { + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &instance->config.sound, "No sound devices found"); + return; + } + + if(instance->config.soundShowAll) + { + uint8_t index = 0; + FF_LIST_FOR_EACH(FFSoundDevice, device, result) + { + printDevice(instance, device, result.length == 1 ? 0 : ++index); + } + } + else + { + FF_LIST_FOR_EACH(FFSoundDevice, device, result) + { + if (!device->main) continue; + printDevice(instance, device, 0); + } + } +} From 11634b9a6749a65409d2cfa286bbb3d9c10d07ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Jan 2023 15:49:31 +0800 Subject: [PATCH 008/119] Windows: add com helper --- CMakeLists.txt | 2 +- src/util/windows/com.cpp | 51 ++++++++++++++++++++++++++++++++++++++++ src/util/windows/com.hpp | 25 ++++++++++++++++++++ src/util/windows/wmi.cpp | 44 +++++++--------------------------- src/util/windows/wmi.hpp | 1 + 5 files changed, 87 insertions(+), 36 deletions(-) create mode 100644 src/util/windows/com.cpp create mode 100644 src/util/windows/com.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 83a3591fc..be8be1a71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -511,6 +511,7 @@ elseif(WIN32) src/detection/wifi/wifi_windows.c src/detection/wmtheme/wmtheme_windows.c src/util/windows/getline.c + src/util/windows/com.cpp src/util/windows/registry.c src/util/windows/unicode.c src/util/windows/wmi.cpp @@ -697,7 +698,6 @@ elseif(WIN32) PRIVATE "ole32" PRIVATE "oleaut32" PRIVATE "opengl32" - PRIVATE "wbemuuid" PRIVATE "ws2_32" PRIVATE "ntdll" PRIVATE "version" diff --git a/src/util/windows/com.cpp b/src/util/windows/com.cpp new file mode 100644 index 000000000..c11cccf95 --- /dev/null +++ b/src/util/windows/com.cpp @@ -0,0 +1,51 @@ +#include "com.hpp" +#include "fastfetch.h" + +#include +#include + +//https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer +//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/computer-system-hardware-classes +static void CoUninitializeWrap() +{ + CoUninitialize(); +} + +static BOOL CALLBACK InitHandleFunction(FF_MAYBE_UNUSED PINIT_ONCE lpInitOnce, FF_MAYBE_UNUSED PVOID lpParameter, PVOID* lpContext) +{ + // Initialize COM + if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) + { + *lpContext = (PVOID) "CoInitializeEx() failed"; + return FALSE; + } + + // Set general COM security levels + if (FAILED(CoInitializeSecurity( + NULL, + -1, // COM authentication + NULL, // Authentication services + NULL, // Reserved + RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication + RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation + NULL, // Authentication info + EOAC_NONE, // Additional capabilities + NULL // Reserved + ))) + { + CoUninitialize(); + *lpContext = (PVOID) "CoInitializeSecurity() failed"; + return FALSE; + } + + atexit(CoUninitializeWrap); + return TRUE; +} + +const char* ffInitCom(void) +{ + const char* error = NULL; + static INIT_ONCE s_InitOnce; + InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, NULL, (void**)&error); + return error; +} diff --git a/src/util/windows/com.hpp b/src/util/windows/com.hpp new file mode 100644 index 000000000..e0f1051ae --- /dev/null +++ b/src/util/windows/com.hpp @@ -0,0 +1,25 @@ +#pragma once + +#ifndef FF_INCLUDED_util_windows_com +#define FF_INCLUDED_util_windows_com + +#ifdef __cplusplus + +#include + +const char* ffInitCom(void); + +static inline void ffReleaseComObject(void* ppUnknown) +{ + IUnknown* pUnknown = *(IUnknown**) ppUnknown; + if (pUnknown) pUnknown->Release(); +} + +#define FF_AUTO_RELEASE_COM_OBJECT __attribute__((__cleanup__(ffReleaseComObject))) + +#else + // Win32 COM headers requires C++ compiler + #error Must be included in C++ source file +#endif + +#endif diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 1da4ac0ff..65e54d422 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -1,4 +1,5 @@ #include "wmi.hpp" +#include "util/windows/com.hpp" #include #include @@ -19,40 +20,10 @@ namespace }; } -//https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer -//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/computer-system-hardware-classes -static void CoUninitializeWrap() -{ - CoUninitialize(); -} - static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lpContext) { HRESULT hres; - // Initialize COM - hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED); - - // Set general COM security levels - hres = CoInitializeSecurity( - nullptr, - -1, // COM authentication - nullptr, // Authentication services - nullptr, // Reserved - RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication - RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation - nullptr, // Authentication info - EOAC_NONE, // Additional capabilities - nullptr // Reserved - ); - - if (FAILED(hres)) - { - CoUninitialize(); - *((const char**)lpContext) = "Failed to initialize security"; - return FALSE; - } - // Obtain the initial locator to WMI IWbemLocator* pLoc = nullptr; hres = CoCreateInstance( @@ -64,7 +35,6 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp if (FAILED(hres)) { - CoUninitialize(); *((const char**)lpContext) = "Failed to create IWbemLocator object"; return FALSE; } @@ -90,7 +60,6 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp if (FAILED(hres)) { - CoUninitialize(); *((const char**)lpContext) = "Could not connect WMI server"; return FALSE; } @@ -110,21 +79,26 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp if (FAILED(hres)) { pSvc->Release(); - CoUninitialize(); *((const char**)lpContext) = "Could not set proxy blanket"; return FALSE; } *((IWbemServices**)lpContext) = pSvc; - atexit(CoUninitializeWrap); return TRUE; } FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs) : pEnumerator(nullptr) { + const char* context = ffInitCom(); + if (context) + { + if (error) + ffStrbufAppendS(error, context); + return; + } + static INIT_ONCE s_InitOnce[(int) FFWmiNamespace::LAST] = {}; - const char* context; if (InitOnceExecuteOnce( &s_InitOnce[(int)wmiNs], &InitHandleFunction, diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 25bef6e91..c4ece40f6 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -9,6 +9,7 @@ extern "C" { #include "util/FFstrbuf.h" } +#include #include enum class FFWmiNamespace { From dd9047c4e93960ae85c682612b88de4fb85cab7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Jan 2023 17:17:31 +0800 Subject: [PATCH 009/119] Sound (Windows): add support --- CMakeLists.txt | 2 +- src/detection/sound/sound_windows.cpp | 87 +++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/detection/sound/sound_windows.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index be8be1a71..021c508f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -502,7 +502,7 @@ elseif(WIN32) src/detection/packages/packages_windows.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_windows.cpp - src/detection/sound/sound_nosupport.c + src/detection/sound/sound_windows.cpp src/detection/swap/swap_windows.cpp src/detection/terminalfont/terminalfont_windows.c src/detection/terminalshell/terminalshell_windows.cpp diff --git a/src/detection/sound/sound_windows.cpp b/src/detection/sound/sound_windows.cpp new file mode 100644 index 000000000..a75c800e1 --- /dev/null +++ b/src/detection/sound/sound_windows.cpp @@ -0,0 +1,87 @@ +extern "C" { + #include "sound.h" + #include "util/windows/unicode.h" +} +#include "util/windows/com.hpp" + +#include +#include +#include +#include + +const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */) +{ + const char* error = ffInitCom(); + if (error) + return error; + + IMMDeviceEnumerator* FF_AUTO_RELEASE_COM_OBJECT pEnum = NULL; + + if (FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&pEnum))) + return "CoCreateInstance(__uuidof(MMDeviceEnumerator)) failed"; + + LPWSTR mainDeviceId = NULL; + + { + IMMDevice* FF_AUTO_RELEASE_COM_OBJECT pDefaultDevice = NULL; + + if (FAILED(pEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDefaultDevice))) + return "GetDefaultAudioEndpoint() failed"; + + if (FAILED(pDefaultDevice->GetId(&mainDeviceId))) + return "pDefaultDevice->GetId() failed"; + } + + IMMDeviceCollection* FF_AUTO_RELEASE_COM_OBJECT pDevices = NULL; + + if (FAILED(pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices))) + return "EnumAudioEndpoints() failed"; + + uint32_t deviceCount; + if (FAILED(pDevices->GetCount(&deviceCount))) + return "pDevices->GetCount() failed"; + + for (uint32_t deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx) + { + IMMDevice* FF_AUTO_RELEASE_COM_OBJECT immDevice = NULL; + if (FAILED(pDevices->Item(deviceIdx, &immDevice))) + continue; + + LPWSTR immDeviceId = NULL; + if (FAILED(immDevice->GetId(&immDeviceId))) + continue; + + IPropertyStore* FF_AUTO_RELEASE_COM_OBJECT immPropStore; + if (FAILED(immDevice->OpenPropertyStore(STGM_READ, &immPropStore))) + continue; + + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); + device->main = wcscmp(mainDeviceId, immDeviceId) == 0; + device->volume = 0; + ffStrbufInit(&device->name); + ffStrbufInit(&device->manufacturer); + + { + PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName; + PropVariantInit(&friendlyName); + if (SUCCEEDED(immPropStore->GetValue(PKEY_Device_DeviceDesc, &friendlyName))) + ffStrbufSetWS(&device->name, friendlyName.pwszVal); + if (SUCCEEDED(immPropStore->GetValue(PKEY_DeviceInterface_FriendlyName, &friendlyName))) + ffStrbufSetWS(&device->manufacturer, friendlyName.pwszVal); + } + + IAudioEndpointVolume* FF_AUTO_RELEASE_COM_OBJECT immEndpointVolume; + if(SUCCEEDED(immDevice->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**) &immEndpointVolume))) + { + BOOL muted; + if (FAILED(immEndpointVolume->GetMute(&muted)) || !muted) + { + FLOAT volume; + if (SUCCEEDED(immEndpointVolume->GetMasterVolumeLevelScalar(&volume))) + device->volume = (uint8_t) (volume * 100 + 0.5); + } + } + } + + return NULL; +} From aa36a83182b63736f755755cebd2002bab70d5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Jan 2023 17:25:05 +0800 Subject: [PATCH 010/119] Windows: silense some warnings --- src/common/parsing.c | 6 ++++++ src/detection/bluetooth/bluetooth_windows.c | 5 +++++ src/detection/os/os_windows.cpp | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/common/parsing.c b/src/common/parsing.c index 95bba4720..bcaebc3c7 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -1,8 +1,12 @@ #include "fastfetch.h" #include "common/parsing.h" + #include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat=" + void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch) { if(major->length > 0) @@ -164,3 +168,5 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co ffStrbufAppendS(buffer, " [GTK4]"); } } + +#pragma GCC diagnostic pop diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c index 61af30d67..e713302b4 100644 --- a/src/detection/bluetooth/bluetooth_windows.c +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -3,6 +3,9 @@ #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-sign" + void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth) { BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { @@ -107,3 +110,5 @@ void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoo } } while (BluetoothFindNextDevice(hFind, &btdi)); } + +#pragma GCC diagnostic pop diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index 7b4c6ea2f..aa25e90ae 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -31,7 +31,7 @@ static const char* getOsNameByWinbrand(FFstrbuf* osName) //https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string if(HMODULE __attribute__((__cleanup__(wrapFreeLibrary))) hWinbrand = LoadLibraryW(L"winbrand.dll")) { - auto BrandingFormatString = (PWSTR(WINAPI*)(PCWSTR))GetProcAddress(hWinbrand, "BrandingFormatString"); + auto BrandingFormatString = (PWSTR(WINAPI*)(PCWSTR))(void*)GetProcAddress(hWinbrand, "BrandingFormatString"); if(!BrandingFormatString) return "GetProcAddress(BrandingFormatString) failed"; From f2dd288a0db83ac14eb99bea18078afdc377853d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Jan 2023 00:36:45 +0800 Subject: [PATCH 011/119] Sound: don't leak memory --- src/modules/sound.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/sound.c b/src/modules/sound.c index 7b68c0f81..8c2b82395 100644 --- a/src/modules/sound.c +++ b/src/modules/sound.c @@ -65,4 +65,10 @@ void ffPrintSound(FFinstance* instance) printDevice(instance, device, 0); } } + + FF_LIST_FOR_EACH(FFSoundDevice, device, result) + { + ffStrbufDestroy(&device->name); + ffStrbufDestroy(&device->manufacturer); + } } From c4c9f024336b25a82f33e6dd0285560558e28f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Jan 2023 00:49:43 +0800 Subject: [PATCH 012/119] Sound (Linux): add dirty support --- CMakeLists.txt | 7 ++- completions/bash | 1 + src/common/init.c | 5 ++ src/data/config_user.txt | 1 + src/data/help.txt | 2 + src/detection/sound/sound_linux.c | 89 +++++++++++++++++++++++++++++++ src/fastfetch.h | 1 + 7 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/detection/sound/sound_linux.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 021c508f2..4d51173fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF) cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) +cmake_dependent_option(ENABLE_ALSA "Enable alsa-lib" ON "LINUX" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF) cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF) @@ -342,7 +343,7 @@ if(LINUX) src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_linux.c src/detection/qt.c - src/detection/sound/sound_nosupport.c + src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c @@ -662,6 +663,10 @@ ff_lib_enable(FREETYPE "freetype2" "FreeType2" ) +ff_lib_enable(ALSA + "alsa" + "ALSA" +) if(ENABLE_THREADS) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS) diff --git a/completions/bash b/completions/bash index 2542c6887..2b6db37c6 100644 --- a/completions/bash +++ b/completions/bash @@ -379,6 +379,7 @@ __fastfetch_completion() "--lib-glx" "--lib-osmesa" "--lib-opencl" + "--lib-alsa" "--battery-dir" ) diff --git a/src/common/init.c b/src/common/init.c index 63f866282..fc47c0888 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -140,6 +140,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.libOpenCL, 0); ffStrbufInitA(&instance->config.libcJSON, 0); ffStrbufInitA(&instance->config.libfreetype, 0); + ffStrbufInit(&instance->config.libAlsa); ffStrbufInit(&instance->config.libwlanapi); ffStrbufInit(&instance->config.libnm); @@ -407,6 +408,7 @@ static void destroyConfig(FFinstance* instance) ffStrbufDestroy(&instance->config.libOpenCL); ffStrbufDestroy(&instance->config.libcJSON); ffStrbufDestroy(&instance->config.libfreetype); + ffStrbufDestroy(&instance->config.libAlsa); ffStrbufDestroy(&instance->config.libwlanapi); ffStrbufDestroy(&instance->config.libnm); @@ -512,6 +514,9 @@ void ffListFeatures() #ifdef FF_HAVE_FREETYPE "freetype\n" #endif + #ifdef FF_HAVE_ALSA + "alsa-lib\n" + #endif #ifdef FF_HAVE_LIBNM "libnm\n" #endif diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 7bf147397..5ace73f0b 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -426,4 +426,5 @@ #--lib-osmesa /usr/lib/libOSMesa.so #--lib-opencl /usr/lib/libOpenCL.so #--lib-cjson /usr/lib/libcjson.so +#--lib-cjson /usr/lib/libasound.so #--lib-freetype /data/data/com.termux/files/usr/lib diff --git a/src/data/help.txt b/src/data/help.txt index d91b442ba..a8325cdc4 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -98,6 +98,8 @@ Library options: Set the path of a library to load --lib-osmesa --lib-opencl --lib-cjson + --lib-alsa + --lib-freetype Module specific options: --title-fqdn : Set if the title should use fully qualified domain name. Default is false diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c new file mode 100644 index 000000000..bf5a421d0 --- /dev/null +++ b/src/detection/sound/sound_linux.c @@ -0,0 +1,89 @@ +#include "sound.h" + +#ifdef FF_HAVE_ALSA + +#include "common/library.h" +#include "common/io.h" + +#include + +static const char* doDetectSound(const FFinstance* instance, FFlist* devices) +{ + FF_LIBRARY_LOAD(asound, &instance->config.libAlsa, "dlopen asound failed", "libasound" FF_LIBRARY_EXTENSION, 2); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_open); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_attach); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_register); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_load); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_first_elem); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_elem_next); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_is_active); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_playback_volume_range); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_playback_volume); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_name); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_close); + + snd_mixer_t *mixer; + if (ffsnd_mixer_open(&mixer, 0) < 0) + return "snd_mixer_open() failed"; + + if (ffsnd_mixer_attach(mixer, "default") < 0) + { + ffsnd_mixer_close(mixer); + return "snd_mixer_attach(\"default\") failed"; + } + + if (ffsnd_mixer_selem_register(mixer, NULL, NULL) < 0) + { + ffsnd_mixer_close(mixer); + return "snd_mixer_selem_register() failed"; + } + + if (ffsnd_mixer_load(mixer) < 0) + { + ffsnd_mixer_close(mixer); + return "snd_mixer_load() failed"; + } + + for (snd_mixer_elem_t* elem = ffsnd_mixer_first_elem(mixer); elem; elem = ffsnd_mixer_elem_next(elem)) + { + if (!ffsnd_mixer_selem_is_active(elem)) + continue; + + long min, max; + if (ffsnd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0) + continue; + + long volume; + if (ffsnd_mixer_selem_get_playback_volume(elem, 0, &volume) < 0) + continue; + + const char* name = ffsnd_mixer_selem_get_name(elem); + + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); + device->main = strcmp(name, "Master") == 0; + device->volume = (uint8_t) ((double)(volume - min) * 100.0 / (double)(max - min) + 0.5); + ffStrbufInitS(&device->name, name); + ffStrbufInit(&device->manufacturer); + } + + ffsnd_mixer_close(mixer); + return NULL; +} + +#endif // FF_HAVE_ALSA + +const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */) +{ + #ifdef FF_HAVE_ALSA + + ffSuppressIO(true); + const char* error = doDetectSound(instance, devices); + ffSuppressIO(false); + return error; + + #else + + return "Fastfetch was built without alsa support"; + + #endif +} diff --git a/src/fastfetch.h b/src/fastfetch.h index 54a27f85e..ffd30d30c 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -164,6 +164,7 @@ typedef struct FFconfig FFstrbuf libOpenCL; FFstrbuf libcJSON; FFstrbuf libfreetype; + FFstrbuf libAlsa; FFstrbuf libwlanapi; FFstrbuf libnm; From 10468a559a70aac930ee5a6e3dc4030d0d1b4230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Jan 2023 00:52:58 +0800 Subject: [PATCH 013/119] Doc: document Sound module support --- CHANGELOG.md | 1 + README.md | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c3361722..4992e1913 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Features: * Bluetooth module +* Sound module # 1.9.1 diff --git a/README.md b/README.md index 45a092552..4ebf8ac58 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,8 @@ The following libraries are used if present at runtime: * [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count. * [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE. * [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ). -* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection on Linux. +* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection. +* [`libalsa`](https://www.alsa-project.org/alsa-doc/alsa-lib/): Used for Sound detection. ### macOS @@ -88,7 +89,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme ``` ##### Builtin logos From f3fba8a3892123cd7bb6cd628fb06e1493c892ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Jan 2023 00:55:02 +0800 Subject: [PATCH 014/119] CI: build with alsa enabled --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 3fefdb776..c415aa866 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v3 - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev + run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev libasound2-dev - name: Initialize CodeQL uses: github/codeql-action/init@v2 From 856c9d58b8dc4d07c50ee4100cfc6ae437f65486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Jan 2023 01:15:33 +0800 Subject: [PATCH 015/119] TerminalFont: tweaks --- src/detection/terminalfont/terminalfont.c | 2 +- src/detection/terminalfont/terminalfont_android.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 41ff5428b..002169f82 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -285,7 +285,7 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbu static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbuf* terminalExe, FFTerminalFontResult* terminalFont) { FF_UNUSED(instance, terminalExe, terminalFont); - ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support"); + ffStrbufAppendS(&terminalFont->error, "Fastfetch was built without libcjson support"); } #endif diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index eaa4fa52d..6c6a224a0 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -49,7 +49,7 @@ exit: #else FF_UNUSED(terminalFont); - return "fastfetch is built without freetype2 support"; + return "Fastfetch was built without freetype2 support"; #endif } From 184ada6ae8a6e72b77079cdd66f740a08a6d7e52 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 26 Jan 2023 15:48:28 +0100 Subject: [PATCH 016/119] Sound(linux): Implement using libpulse Also differentiate between active and main device(s) --- CMakeLists.txt | 10 +- README.md | 2 +- completions/bash | 2 +- src/common/init.c | 8 +- src/data/config_user.txt | 1 + src/data/help.txt | 2 +- src/detection/sound/sound.h | 1 + src/detection/sound/sound_apple.c | 1 + src/detection/sound/sound_linux.c | 169 ++++++++++++++++---------- src/detection/sound/sound_windows.cpp | 1 + src/fastfetch.c | 2 + src/fastfetch.h | 2 +- src/modules/sound.c | 56 +++++---- 13 files changed, 156 insertions(+), 101 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d51173fa..927448737 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF) cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) -cmake_dependent_option(ENABLE_ALSA "Enable alsa-lib" ON "LINUX" OFF) +cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF) cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF) @@ -425,7 +425,7 @@ elseif(BSD) src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_bsd.c src/detection/qt.c - src/detection/sound/sound_nosupport.c + src/detection/sound/sound_linux.c src/detection/swap/swap_bsd.c src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c @@ -663,9 +663,9 @@ ff_lib_enable(FREETYPE "freetype2" "FreeType2" ) -ff_lib_enable(ALSA - "alsa" - "ALSA" +ff_lib_enable(PULSE + "libpulse" + "Pulse" ) if(ENABLE_THREADS) diff --git a/README.md b/README.md index 4ebf8ac58..34ba5e726 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ The following libraries are used if present at runtime: * [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE. * [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ). * [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection. -* [`libalsa`](https://www.alsa-project.org/alsa-doc/alsa-lib/): Used for Sound detection. +* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection. ### macOS diff --git a/completions/bash b/completions/bash index 2b6db37c6..93386be34 100644 --- a/completions/bash +++ b/completions/bash @@ -379,7 +379,7 @@ __fastfetch_completion() "--lib-glx" "--lib-osmesa" "--lib-opencl" - "--lib-alsa" + "--lib-pulse" "--battery-dir" ) diff --git a/src/common/init.c b/src/common/init.c index fc47c0888..7eabe0948 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -140,7 +140,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.libOpenCL, 0); ffStrbufInitA(&instance->config.libcJSON, 0); ffStrbufInitA(&instance->config.libfreetype, 0); - ffStrbufInit(&instance->config.libAlsa); + ffStrbufInit(&instance->config.libPulse); ffStrbufInit(&instance->config.libwlanapi); ffStrbufInit(&instance->config.libnm); @@ -408,7 +408,7 @@ static void destroyConfig(FFinstance* instance) ffStrbufDestroy(&instance->config.libOpenCL); ffStrbufDestroy(&instance->config.libcJSON); ffStrbufDestroy(&instance->config.libfreetype); - ffStrbufDestroy(&instance->config.libAlsa); + ffStrbufDestroy(&instance->config.libPulse); ffStrbufDestroy(&instance->config.libwlanapi); ffStrbufDestroy(&instance->config.libnm); @@ -514,8 +514,8 @@ void ffListFeatures() #ifdef FF_HAVE_FREETYPE "freetype\n" #endif - #ifdef FF_HAVE_ALSA - "alsa-lib\n" + #ifdef FF_HAVE_PULSE + "libpulse\n" #endif #ifdef FF_HAVE_LIBNM "libnm\n" diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 5ace73f0b..1b9ac9635 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -428,3 +428,4 @@ #--lib-cjson /usr/lib/libcjson.so #--lib-cjson /usr/lib/libasound.so #--lib-freetype /data/data/com.termux/files/usr/lib +#--lib-pulse /usr/lib/libpulse.so diff --git a/src/data/help.txt b/src/data/help.txt index a8325cdc4..c4fd1acd3 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -98,7 +98,7 @@ Library options: Set the path of a library to load --lib-osmesa --lib-opencl --lib-cjson - --lib-alsa + --lib-pulse --lib-freetype Module specific options: diff --git a/src/detection/sound/sound.h b/src/detection/sound/sound.h index ecbc53db5..6247ed299 100644 --- a/src/detection/sound/sound.h +++ b/src/detection/sound/sound.h @@ -11,6 +11,7 @@ typedef struct FFSoundDevice FFstrbuf manufacturer; uint8_t volume; // 0-100% bool main; + bool active; } FFSoundDevice; const char* ffDetectSound(const FFinstance* instance, FFlist* devices /* List of FFSoundDevice */); diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index 8ede08f28..78ab54740 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -38,6 +38,7 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = deviceId == mainDeviceId; + device->active = device->main; device->volume = 0; ffStrbufInit(&device->name); ffStrbufInit(&device->manufacturer); diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index bf5a421d0..ef7cd2f00 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -1,89 +1,134 @@ #include "sound.h" -#ifdef FF_HAVE_ALSA +#ifdef FF_HAVE_PULSE +#include +#include -#include "common/library.h" -#include "common/io.h" - -#include - -static const char* doDetectSound(const FFinstance* instance, FFlist* devices) +static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) { - FF_LIBRARY_LOAD(asound, &instance->config.libAlsa, "dlopen asound failed", "libasound" FF_LIBRARY_EXTENSION, 2); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_open); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_attach); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_register); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_load); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_first_elem); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_elem_next); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_is_active); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_playback_volume_range); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_playback_volume); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_selem_get_name); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(asound, snd_mixer_close); + FF_UNUSED(c); - snd_mixer_t *mixer; - if (ffsnd_mixer_open(&mixer, 0) < 0) - return "snd_mixer_open() failed"; + if(eol > 0 || !i) + return; - if (ffsnd_mixer_attach(mixer, "default") < 0) + FFSoundDevice* device = ffListAdd(userdata); + ffStrbufInitS(&device->name, i->description); + ffStrbufInitS(&device->manufacturer, i->name); + device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM); + device->active = i->active_port && i->active_port->available == PA_PORT_AVAILABLE_YES; + device->main = false; +} + +static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *userdata) +{ + FF_UNUSED(c); + + if(!i) + return; + + FF_LIST_FOR_EACH(FFSoundDevice, device, *(FFlist*)userdata) { - ffsnd_mixer_close(mixer); - return "snd_mixer_attach(\"default\") failed"; + if(ffStrbufEqualS(&device->manufacturer, i->default_sink_name)) + { + device->main = true; + break; + } + } +} + +static const char* detectSound(const FFinstance* instance, FFlist* devices) +{ + FF_LIBRARY_LOAD(pulse, &instance->config.libPulse, "Failed to load libpulse.so.0", "libpulse.so.0", 0) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_new) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_get_api) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_iterate) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_free) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_new) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_connect) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_get_state) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_get_sink_info_list) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_get_server_info) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_context_unref) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_operation_get_state) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_operation_unref) + + pa_mainloop* mainloop = ffpa_mainloop_new(); + if(!mainloop) + return "Failed to create pulseaudio mainloop"; + + pa_mainloop_api* mainloopApi = ffpa_mainloop_get_api(mainloop); + if(!mainloopApi) + { + ffpa_mainloop_free(mainloop); + return "Failed to get pulseaudio mainloop api"; } - if (ffsnd_mixer_selem_register(mixer, NULL, NULL) < 0) + pa_context* context = ffpa_context_new(mainloopApi, "fastfetch"); + if(!context) { - ffsnd_mixer_close(mixer); - return "snd_mixer_selem_register() failed"; + ffpa_mainloop_free(mainloop); + return "Failed to create pulseaudio context"; } - if (ffsnd_mixer_load(mixer) < 0) + if(ffpa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) { - ffsnd_mixer_close(mixer); - return "snd_mixer_load() failed"; + ffpa_context_unref(context); + ffpa_mainloop_free(mainloop); + return "Failed to connect to pulseaudio context"; } - for (snd_mixer_elem_t* elem = ffsnd_mixer_first_elem(mixer); elem; elem = ffsnd_mixer_elem_next(elem)) + int state; + while((state = ffpa_context_get_state(context)) != PA_CONTEXT_READY) { - if (!ffsnd_mixer_selem_is_active(elem)) - continue; + if(!PA_CONTEXT_IS_GOOD(state)) + { + ffpa_context_unref(context); + ffpa_mainloop_free(mainloop); + return "Failed to get pulseaudio context state"; + } - long min, max; - if (ffsnd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0) - continue; - - long volume; - if (ffsnd_mixer_selem_get_playback_volume(elem, 0, &volume) < 0) - continue; - - const char* name = ffsnd_mixer_selem_get_name(elem); - - FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); - device->main = strcmp(name, "Master") == 0; - device->volume = (uint8_t) ((double)(volume - min) * 100.0 / (double)(max - min) + 0.5); - ffStrbufInitS(&device->name, name); - ffStrbufInit(&device->manufacturer); + ffpa_mainloop_iterate(mainloop, 1, NULL); } - ffsnd_mixer_close(mixer); + pa_operation* operation = ffpa_context_get_sink_info_list(context, paSinkInfoCallback, devices); + if(!operation) + { + ffpa_context_unref(context); + ffpa_mainloop_free(mainloop); + return "Failed to get pulseaudio sink info list"; + } + + while(ffpa_operation_get_state(operation) == PA_OPERATION_RUNNING) + ffpa_mainloop_iterate(mainloop, 1, NULL); + + ffpa_operation_unref(operation); + + operation = ffpa_context_get_server_info(context, paServerInfoCallback, devices); + if(!operation) + { + ffpa_context_unref(context); + ffpa_mainloop_free(mainloop); + return "Failed to get pulseaudio server info"; + } + + while(ffpa_operation_get_state(operation) == PA_OPERATION_RUNNING) + ffpa_mainloop_iterate(mainloop, 1, NULL); + + ffpa_operation_unref(operation); + + ffpa_context_unref(context); + ffpa_mainloop_free(mainloop); return NULL; } -#endif // FF_HAVE_ALSA +#endif // FF_HAVE_PULSE -const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFSoundDevice */) +const char* ffDetectSound(const FFinstance* instance, FFlist* devices) { - #ifdef FF_HAVE_ALSA - - ffSuppressIO(true); - const char* error = doDetectSound(instance, devices); - ffSuppressIO(false); - return error; - + #ifdef FF_HAVE_PULSE + return detectSound(instance, devices); #else - - return "Fastfetch was built without alsa support"; - + FF_UNUSED(instance, devices); + return "Fastfetch was built without libpulse support"; #endif } diff --git a/src/detection/sound/sound_windows.cpp b/src/detection/sound/sound_windows.cpp index a75c800e1..23f094feb 100644 --- a/src/detection/sound/sound_windows.cpp +++ b/src/detection/sound/sound_windows.cpp @@ -57,6 +57,7 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = wcscmp(mainDeviceId, immDeviceId) == 0; + device->active = device->main; device->volume = 0; ffStrbufInit(&device->name); ffStrbufInit(&device->manufacturer); diff --git a/src/fastfetch.c b/src/fastfetch.c index 1febd5f8b..c49a3d408 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1275,6 +1275,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.libcJSON); else if(strcasecmp(subkey, "-wlanapi") == 0) optionParseString(key, value, &instance->config.libwlanapi); + else if(strcasecmp(key, "-pulse") == 0) + optionParseString(key, value, &instance->config.libPulse); else if(strcasecmp(subkey, "-nm") == 0) optionParseString(key, value, &instance->config.libnm); else diff --git a/src/fastfetch.h b/src/fastfetch.h index ffd30d30c..e1d5be954 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -164,7 +164,7 @@ typedef struct FFconfig FFstrbuf libOpenCL; FFstrbuf libcJSON; FFstrbuf libfreetype; - FFstrbuf libAlsa; + FFstrbuf libPulse; FFstrbuf libwlanapi; FFstrbuf libnm; diff --git a/src/modules/sound.c b/src/modules/sound.c index 8c2b82395..3bc478145 100644 --- a/src/modules/sound.c +++ b/src/modules/sound.c @@ -15,10 +15,11 @@ static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8 printf(" (%d%%)", device->volume); else fputs(" (muted)", stdout); - if(device->main && instance->config.soundShowAll) - puts(" (*)"); - else - putchar('\n'); + + if(device->main && index > 0) + fputs(" (*)", stdout); + + putchar('\n'); } else { @@ -31,6 +32,30 @@ static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8 } } +static void printSound(FFinstance* instance, FFlist* devices) +{ + FF_LIST_AUTO_DESTROY filtered; + ffListInit(&filtered, sizeof(FFSoundDevice*)); + + FF_LIST_FOR_EACH(FFSoundDevice, device, *devices) + { + if(!device->active && !instance->config.soundShowAll) + continue; + + *(FFSoundDevice**)ffListAdd(&filtered) = device; + } + + if(filtered.length == 0) + { + ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &instance->config.sound, "No active sound devices found"); + return; + } + + uint8_t index = 1; + FF_LIST_FOR_EACH(FFSoundDevice*, device, filtered) + printDevice(instance, *device, filtered.length == 1 ? 0 : index++); +} + void ffPrintSound(FFinstance* instance) { FF_LIST_AUTO_DESTROY result; @@ -43,28 +68,7 @@ void ffPrintSound(FFinstance* instance) return; } - if(result.length == 0) - { - ffPrintError(instance, FF_SOUND_MODULE_NAME, 0, &instance->config.sound, "No sound devices found"); - return; - } - - if(instance->config.soundShowAll) - { - uint8_t index = 0; - FF_LIST_FOR_EACH(FFSoundDevice, device, result) - { - printDevice(instance, device, result.length == 1 ? 0 : ++index); - } - } - else - { - FF_LIST_FOR_EACH(FFSoundDevice, device, result) - { - if (!device->main) continue; - printDevice(instance, device, 0); - } - } + printSound(instance, &result); FF_LIST_FOR_EACH(FFSoundDevice, device, result) { From 7adb1606f1782960f2732e9abffae6cb96504262 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 26 Jan 2023 15:50:35 +0100 Subject: [PATCH 017/119] GH Actions: build with libpulse --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index c415aa866..350b6902b 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v3 - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev libasound2-dev + run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev libpulse-dev - name: Initialize CodeQL uses: github/codeql-action/init@v2 From 33f3744a634a80d6491eccedf4beacea1383e3ba Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 26 Jan 2023 17:25:14 +0100 Subject: [PATCH 018/119] Sound(Linux): Treat default port as always active This fixes no shown sound devices when no audio is currently played --- src/detection/sound/sound_linux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index ef7cd2f00..e36bf2963 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -31,6 +31,7 @@ static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *u if(ffStrbufEqualS(&device->manufacturer, i->default_sink_name)) { device->main = true; + device->active = true; // Treat the default sink as always active break; } } From cb466aec0872b2a309fac1634992576c1bd74bf7 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 26 Jan 2023 22:08:55 +0100 Subject: [PATCH 019/119] Linux: Fix build without dbus #405 --- src/common/dbus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/dbus.c b/src/common/dbus.c index e053be9a5..38869668d 100644 --- a/src/common/dbus.c +++ b/src/common/dbus.c @@ -1,5 +1,7 @@ #include "dbus.h" +#ifdef FF_HAVE_DBUS + #include "common/thread.h" static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib) @@ -199,3 +201,5 @@ void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* dbus->lib->ffdbus_message_unref(reply); } + +#endif //FF_DBUS_H From 205e664b4d820aa3b047c035266f32b4b81a0414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Jan 2023 13:08:07 +0800 Subject: [PATCH 020/119] Sound (Windows): show more detailed information --- src/detection/sound/sound_windows.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/detection/sound/sound_windows.cpp b/src/detection/sound/sound_windows.cpp index 23f094feb..57b8fa45b 100644 --- a/src/detection/sound/sound_windows.cpp +++ b/src/detection/sound/sound_windows.cpp @@ -34,7 +34,7 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U IMMDeviceCollection* FF_AUTO_RELEASE_COM_OBJECT pDevices = NULL; - if (FAILED(pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices))) + if (FAILED(pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &pDevices))) return "EnumAudioEndpoints() failed"; uint32_t deviceCount; @@ -55,9 +55,13 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U if (FAILED(immDevice->OpenPropertyStore(STGM_READ, &immPropStore))) continue; + DWORD immState; + if (FAILED(immDevice->GetState(&immState))) + continue; + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = wcscmp(mainDeviceId, immDeviceId) == 0; - device->active = device->main; + device->active = !!(immState & DEVICE_STATE_ACTIVE); device->volume = 0; ffStrbufInit(&device->name); ffStrbufInit(&device->manufacturer); @@ -65,7 +69,7 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U { PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName; PropVariantInit(&friendlyName); - if (SUCCEEDED(immPropStore->GetValue(PKEY_Device_DeviceDesc, &friendlyName))) + if (SUCCEEDED(immPropStore->GetValue(PKEY_Device_FriendlyName, &friendlyName))) ffStrbufSetWS(&device->name, friendlyName.pwszVal); if (SUCCEEDED(immPropStore->GetValue(PKEY_DeviceInterface_FriendlyName, &friendlyName))) ffStrbufSetWS(&device->manufacturer, friendlyName.pwszVal); From b0c19256f0b2a35d3894716b245999346346d8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Jan 2023 13:10:06 +0800 Subject: [PATCH 021/119] Bluetooth: silense warnings --- src/detection/bluetooth/bluetooth_nosupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/bluetooth/bluetooth_nosupport.c b/src/detection/bluetooth/bluetooth_nosupport.c index 1bb524a02..f8cafe045 100644 --- a/src/detection/bluetooth/bluetooth_nosupport.c +++ b/src/detection/bluetooth/bluetooth_nosupport.c @@ -1,6 +1,6 @@ #include "bluetooth.h" -void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth) +void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth) { ffStrbufAppendS(&bluetooth->error, "Bluetooth not supported on this platform"); } From 672e309d893375a263e57d23f3d17d2d17406299 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 27 Jan 2023 11:21:01 +0100 Subject: [PATCH 022/119] Small fixes --- src/common/dbus.c | 2 +- src/detection/sound/sound_linux.c | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/common/dbus.c b/src/common/dbus.c index 38869668d..1d2840b2f 100644 --- a/src/common/dbus.c +++ b/src/common/dbus.c @@ -202,4 +202,4 @@ void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* dbus->lib->ffdbus_message_unref(reply); } -#endif //FF_DBUS_H +#endif //FF_HAVE_DBUS diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index e36bf2963..0e25d5629 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -105,20 +105,17 @@ static const char* detectSound(const FFinstance* instance, FFlist* devices) ffpa_operation_unref(operation); operation = ffpa_context_get_server_info(context, paServerInfoCallback, devices); - if(!operation) + if(operation) { - ffpa_context_unref(context); - ffpa_mainloop_free(mainloop); - return "Failed to get pulseaudio server info"; + while(ffpa_operation_get_state(operation) == PA_OPERATION_RUNNING) + ffpa_mainloop_iterate(mainloop, 1, NULL); + + ffpa_operation_unref(operation); } - while(ffpa_operation_get_state(operation) == PA_OPERATION_RUNNING) - ffpa_mainloop_iterate(mainloop, 1, NULL); - - ffpa_operation_unref(operation); - ffpa_context_unref(context); ffpa_mainloop_free(mainloop); + dlclose(pulse); return NULL; } From 00fc3f1a1dc738b0a9e1b9bb84caad6d800ca5c5 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 27 Jan 2023 12:56:36 +0100 Subject: [PATCH 023/119] Add a workflow that tests different build config combinations --- .github/workflows/push.yml | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 350b6902b..a52706c66 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -5,6 +5,57 @@ on: - pull_request jobs: + linux-buildtest: + name: Linux build test + permissions: + contents: read + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + compiler: [gcc, clang] + enable_libpci: [ON, OFF] + enable_vulkan: [ON, OFF] + enable_wayland: [ON, OFF] + enable_xrandr: [ON, OFF] + enable_xcb: [ON, OFF] + enable_dconf: [ON, OFF] + enable_dbus: [ON, OFF] + enable_magick: [ON, OFF] + enable_xfconf: [ON, OFF] + enable_sqlite: [ON, OFF] + enable_rpm: [ON, OFF] + enable_egl: [ON, OFF] + enable_glx: [ON, OFF] + enable_osmesa: [ON, OFF] + enable_opencl: [ON, OFF] + enable_nm: [ON, OFF] + enable_pulse: [ON, OFF] + runs-on: ${{ matrix.os }} + steps: + - name: checkout repository + uses: actions/checkout@v3 + + - name: install required packages + run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev libpulse-dev + + - name: configure project + env: + CC: ${{ matrix.compiler }} + run: cmake -DENABLE_LIBPCI=${{ matrix.enable_libpci }} -DENABLE_VULKAN=${{ matrix.enable_vulkan }} -DENABLE_WAYLAND=${{ matrix.enable_wayland }} -DENABLE_XRANDR=${{ matrix.enable_xrandr }} -DENABLE_XCB=${{ matrix.enable_xcb }} -DENABLE_DCONF=${{ matrix.enable_dconf }} -DENABLE_DBUS=${{ matrix.enable_dbus }} -DENABLE_MAGICK=${{ matrix.enable_magick }} -DENABLE_XFCONF=${{ matrix.enable_xfconf }} -DENABLE_SQLITE=${{ matrix.enable_sqlite }} -DENABLE_RPM=${{ matrix.enable_rpm }} -DENABLE_EGL=${{ matrix.enable_egl }} -DENABLE_GLX=${{ matrix.enable_glx }} -DENABLE_OSMESA=${{ matrix.enable_osmesa }} -DENABLE_OPENCL=${{ matrix.enable_opencl }} -DENABLE_NM=${{ matrix.enable_nm }} -DENABLE_PULSE=${{ matrix.enable_pulse }} + + - name: build project + run: cmake --build . + + - name: run tests + run: ctest + + - name: run fastfetch + run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all + + - name: run flashfetch + run: ./flashfetch + linux: name: Linux runs-on: ubuntu-latest From 0c256e290875fa386541cd6389d6c8801bc6db8c Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 27 Jan 2023 13:01:24 +0100 Subject: [PATCH 024/119] Just try with all on and all of --- .github/workflows/push.yml | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index a52706c66..b93c6e922 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -14,23 +14,7 @@ jobs: matrix: os: [ubuntu-latest] compiler: [gcc, clang] - enable_libpci: [ON, OFF] - enable_vulkan: [ON, OFF] - enable_wayland: [ON, OFF] - enable_xrandr: [ON, OFF] - enable_xcb: [ON, OFF] - enable_dconf: [ON, OFF] - enable_dbus: [ON, OFF] - enable_magick: [ON, OFF] - enable_xfconf: [ON, OFF] - enable_sqlite: [ON, OFF] - enable_rpm: [ON, OFF] - enable_egl: [ON, OFF] - enable_glx: [ON, OFF] - enable_osmesa: [ON, OFF] - enable_opencl: [ON, OFF] - enable_nm: [ON, OFF] - enable_pulse: [ON, OFF] + enableFeatures: [ON, OFF] runs-on: ${{ matrix.os }} steps: - name: checkout repository @@ -42,7 +26,7 @@ jobs: - name: configure project env: CC: ${{ matrix.compiler }} - run: cmake -DENABLE_LIBPCI=${{ matrix.enable_libpci }} -DENABLE_VULKAN=${{ matrix.enable_vulkan }} -DENABLE_WAYLAND=${{ matrix.enable_wayland }} -DENABLE_XRANDR=${{ matrix.enable_xrandr }} -DENABLE_XCB=${{ matrix.enable_xcb }} -DENABLE_DCONF=${{ matrix.enable_dconf }} -DENABLE_DBUS=${{ matrix.enable_dbus }} -DENABLE_MAGICK=${{ matrix.enable_magick }} -DENABLE_XFCONF=${{ matrix.enable_xfconf }} -DENABLE_SQLITE=${{ matrix.enable_sqlite }} -DENABLE_RPM=${{ matrix.enable_rpm }} -DENABLE_EGL=${{ matrix.enable_egl }} -DENABLE_GLX=${{ matrix.enable_glx }} -DENABLE_OSMESA=${{ matrix.enable_osmesa }} -DENABLE_OPENCL=${{ matrix.enable_opencl }} -DENABLE_NM=${{ matrix.enable_nm }} -DENABLE_PULSE=${{ matrix.enable_pulse }} + run: cmake -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBCJSON=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} . - name: build project run: cmake --build . From cf78216d782f2268dfb03f786625d220092901ba Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 27 Jan 2023 18:03:57 +0100 Subject: [PATCH 025/119] Sound(Linux): Don't abuse manufactor --- src/detection/bluetooth/bluetooth_linux.c | 56 ++++++++++++----------- src/detection/sound/sound.h | 1 + src/detection/sound/sound_linux.c | 5 +- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index 4751db6c0..ba0ba3bf8 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -8,32 +8,36 @@ array [ //root dict entry( //object object path "/org/bluez/hci0/dev_03_21_8B_91_16_4D" array [ - dict entry( //property - string "org.bluez.Device1" - array [ - dict entry( - string "Address" - variant string "03:21:8B:91:16:4D" - ) - dict entry( - string "Name" - variant string "JBL TUNE160BT" - ) - dict entry( - string "Connected" - variant boolean true - ) - ] - ) - dict entry( //property - string "org.bluez.Battery1" - array [ - dict entry( - string "Percentage" - variant byte 100 - ) - ] - ) + dict entry( //property + string "org.bluez.Device1" + array [ + dict entry( + string "Address" + variant string "03:21:8B:91:16:4D" + ) + dict entry( + string "Name" + variant string "JBL TUNE160BT" + ) + dict entry( + string "Icon" + variant string "audio-headset" + ) + dict entry( + string "Connected" + variant boolean true + ) + ] + ) + dict entry( //property + string "org.bluez.Battery1" + array [ + dict entry( + string "Percentage" + variant byte 100 + ) + ] + ) ] ) ] diff --git a/src/detection/sound/sound.h b/src/detection/sound/sound.h index 6247ed299..f40f6af5c 100644 --- a/src/detection/sound/sound.h +++ b/src/detection/sound/sound.h @@ -7,6 +7,7 @@ typedef struct FFSoundDevice { + FFstrbuf identifier; // Used internally, not guaranteed to be initialized FFstrbuf name; FFstrbuf manufacturer; uint8_t volume; // 0-100% diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index 0e25d5629..0aa10b753 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -12,8 +12,9 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo return; FFSoundDevice* device = ffListAdd(userdata); + ffStrbufInitS(&device->identifier, i->name); ffStrbufInitS(&device->name, i->description); - ffStrbufInitS(&device->manufacturer, i->name); + ffStrbufInitS(&device->manufacturer, i->driver); device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM); device->active = i->active_port && i->active_port->available == PA_PORT_AVAILABLE_YES; device->main = false; @@ -28,7 +29,7 @@ static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *u FF_LIST_FOR_EACH(FFSoundDevice, device, *(FFlist*)userdata) { - if(ffStrbufEqualS(&device->manufacturer, i->default_sink_name)) + if(ffStrbufEqualS(&device->identifier, i->default_sink_name)) { device->main = true; device->active = true; // Treat the default sink as always active From 14dcafe2ca06cd372d403ad3efaddaaea8f15e12 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 27 Jan 2023 18:21:42 +0100 Subject: [PATCH 026/119] Bluetooth(Linux): Refactor code a bit --- src/detection/bluetooth/bluetooth_linux.c | 66 ++++++++++++----------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index ba0ba3bf8..82aba4e77 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -11,19 +11,19 @@ array [ //root dict entry( //property string "org.bluez.Device1" array [ - dict entry( + dict entry( //value string "Address" variant string "03:21:8B:91:16:4D" ) - dict entry( + dict entry( //value string "Name" variant string "JBL TUNE160BT" ) - dict entry( + dict entry( //value string "Icon" variant string "audio-headset" ) - dict entry( + dict entry( //value string "Connected" variant boolean true ) @@ -32,7 +32,7 @@ array [ //root dict entry( //property string "org.bluez.Battery1" array [ - dict entry( + dict entry( //value string "Percentage" variant byte 100 ) @@ -43,6 +43,34 @@ array [ //root ] */ +static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) + return; + + DBusMessageIter dictIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) + return; + + const char* deviceProperty; + dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty); + + dbus->lib->ffdbus_message_iter_next(&dictIter); + + if(strcmp(deviceProperty, "Address") == 0) + ffDBusGetValue(dbus, &dictIter, &device->address); + else if(strcmp(deviceProperty, "Name") == 0) + ffDBusGetValue(dbus, &dictIter, &device->name); + else if(strcmp(deviceProperty, "Icon") == 0) + ffDBusGetValue(dbus, &dictIter, &device->type); + else if(strcmp(deviceProperty, "Percentage") == 0) + ffDBusGetByte(dbus, &dictIter, &device->battery); + else if(strcmp(deviceProperty, "Connected") == 0) + ffDBusGetBool(dbus, &dictIter, &device->connected); +} + static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device) { if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) @@ -70,31 +98,7 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB while(true) { - if(dbus->lib->ffdbus_message_iter_get_arg_type(&arrayIter) != DBUS_TYPE_DICT_ENTRY) - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter) - - DBusMessageIter deviceIter; - dbus->lib->ffdbus_message_iter_recurse(&arrayIter, &deviceIter); - - if(dbus->lib->ffdbus_message_iter_get_arg_type(&deviceIter) != DBUS_TYPE_STRING) - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter) - - const char* deviceProperty; - dbus->lib->ffdbus_message_iter_get_basic(&deviceIter, &deviceProperty); - - dbus->lib->ffdbus_message_iter_next(&deviceIter); - - if(strcmp(deviceProperty, "Address") == 0) - ffDBusGetValue(dbus, &deviceIter, &device->address); - else if(strcmp(deviceProperty, "Name") == 0) - ffDBusGetValue(dbus, &deviceIter, &device->name); - else if(strcmp(deviceProperty, "Icon") == 0) - ffDBusGetValue(dbus, &deviceIter, &device->type); - else if(strcmp(deviceProperty, "Percentage") == 0) - ffDBusGetByte(dbus, &deviceIter, &device->battery); - else if(strcmp(deviceProperty, "Connected") == 0) - ffDBusGetBool(dbus, &deviceIter, &device->connected); - + detectBluetoothValue(dbus, &arrayIter, device); FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); } } @@ -160,8 +164,6 @@ static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, detectBluetoothObject(bluetooth, dbus, &arrayIter); FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); } - - return; } static const char* detectBluetooth(const FFinstance* instance, FFBluetoothResult* bluetooth) From 1c38ebb55103c8bf4ee976bba4c6392f5c69fef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Jan 2023 13:32:53 +0800 Subject: [PATCH 027/119] Parsing: only disable warning when necessary --- src/common/parsing.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/parsing.c b/src/common/parsing.c index bcaebc3c7..5761206d3 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -4,8 +4,10 @@ #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat=" +#ifdef _WIN32 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wformat" +#endif void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch) { @@ -169,4 +171,6 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co } } -#pragma GCC diagnostic pop +#ifdef _WIN32 + #pragma GCC diagnostic pop +#endif From f4cefe955bc8e143a0deeead54db73535db9dc33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Jan 2023 13:45:24 +0800 Subject: [PATCH 028/119] Sound: always initialize identifier and destroy it to avoid memleaks --- src/detection/sound/sound.h | 2 +- src/detection/sound/sound_apple.c | 1 + src/detection/sound/sound_windows.cpp | 3 +++ src/modules/sound.c | 6 ++++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/detection/sound/sound.h b/src/detection/sound/sound.h index f40f6af5c..76c17627c 100644 --- a/src/detection/sound/sound.h +++ b/src/detection/sound/sound.h @@ -7,7 +7,7 @@ typedef struct FFSoundDevice { - FFstrbuf identifier; // Used internally, not guaranteed to be initialized + FFstrbuf identifier; FFstrbuf name; FFstrbuf manufacturer; uint8_t volume; // 0-100% diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index 78ab54740..305e991bf 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -40,6 +40,7 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de device->main = deviceId == mainDeviceId; device->active = device->main; device->volume = 0; + ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId); ffStrbufInit(&device->name); ffStrbufInit(&device->manufacturer); diff --git a/src/detection/sound/sound_windows.cpp b/src/detection/sound/sound_windows.cpp index 57b8fa45b..2b9e95be1 100644 --- a/src/detection/sound/sound_windows.cpp +++ b/src/detection/sound/sound_windows.cpp @@ -63,9 +63,12 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U device->main = wcscmp(mainDeviceId, immDeviceId) == 0; device->active = !!(immState & DEVICE_STATE_ACTIVE); device->volume = 0; + ffStrbufInit(&device->identifier); ffStrbufInit(&device->name); ffStrbufInit(&device->manufacturer); + ffStrbufSetWS(&device->identifier, immDeviceId); + { PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName; PropVariantInit(&friendlyName); diff --git a/src/modules/sound.c b/src/modules/sound.c index 3bc478145..d9ee35d37 100644 --- a/src/modules/sound.c +++ b/src/modules/sound.c @@ -2,7 +2,7 @@ #include "detection/sound/sound.h" #define FF_SOUND_MODULE_NAME "Sound" -#define FF_SOUND_NUM_FORMAT_ARGS 4 +#define FF_SOUND_NUM_FORMAT_ARGS 5 static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8_t index) { @@ -27,7 +27,8 @@ static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8 {FF_FORMAT_ARG_TYPE_BOOL, &device->main}, {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, {FF_FORMAT_ARG_TYPE_UINT8, &device->volume}, - {FF_FORMAT_ARG_TYPE_STRBUF, &device->manufacturer} + {FF_FORMAT_ARG_TYPE_STRBUF, &device->manufacturer}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier} }); } } @@ -72,6 +73,7 @@ void ffPrintSound(FFinstance* instance) FF_LIST_FOR_EACH(FFSoundDevice, device, result) { + ffStrbufDestroy(&device->identifier); ffStrbufDestroy(&device->name); ffStrbufDestroy(&device->manufacturer); } From 4afba798baa90185ad8bb7dc412aae1e629447d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Jan 2023 13:45:40 +0800 Subject: [PATCH 029/119] Sound: add missing command helpers --- src/fastfetch.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/fastfetch.c b/src/fastfetch.c index c49a3d408..979f37b62 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -457,6 +457,16 @@ static inline void printCommandHelp(const char* command) "Battery percentage" ); } + else if(strcasecmp(command, "sound-format") == 0) + { + constructAndPrintCommandHelpFormat("sound", "{2} (3%)", 4, + "Main", + "Name", + "Volume", + "Manufacturer", + "Identifier" + ); + } else fprintf(stderr, "No specific help for command %s provided\n", command); } From 9bb6d8fd6e38a0d4dc4aec37787baf1e554edfc7 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 28 Jan 2023 11:14:16 +0100 Subject: [PATCH 030/119] Allow loading images from data dirs too #375 --- src/logo/image/image.c | 46 +++++++++++++---------- src/logo/logo.c | 84 +++++++++++++++++++++++++----------------- src/logo/logo.h | 2 +- 3 files changed, 78 insertions(+), 54 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index b2bfff6b5..f3cb90da1 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -673,7 +673,7 @@ static bool getCharacterPixelDimensions(FFLogoRequestData* requestData) return requestData->characterPixelWidth > 1.0 && requestData->characterPixelHeight > 1.0; } -static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type) +static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type, bool printError) { FFLogoRequestData requestData; requestData.type = type; @@ -684,7 +684,8 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type) (type != FF_LOGO_TYPE_IMAGE_CHAFA || instance->config.logo.width == 0 || instance->config.logo.height == 0) && !getCharacterPixelDimensions(&requestData) ) { - fputs("Logo: getCharacterPixelDimensions() failed", stderr); + if(printError) + fputs("Logo: getCharacterPixelDimensions() failed", stderr); return false; } @@ -700,7 +701,8 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type) { //We can safely return here, because if realpath failed, we surely won't be able to read the file ffStrbufDestroy(&requestData.cacheDir); - fputs("Logo: Querying realpath of the image source failed", stderr); + if(printError) + fputs("Logo: Querying realpath of the image source failed", stderr); return false; } ffStrbufRecalculateLength(&requestData.cacheDir); @@ -730,26 +732,28 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type) ffStrbufDestroy(&requestData.cacheDir); - switch(result) + if(result == FF_LOGO_IMAGE_RESULT_SUCCESS) + return true; + + if(printError) { - case FF_LOGO_IMAGE_RESULT_INIT_ERROR: - fputs("Logo: Init Image Magick library failed\n", stderr); - return false; - case FF_LOGO_IMAGE_RESULT_RUN_ERROR: + if(result == FF_LOGO_IMAGE_RESULT_INIT_ERROR) + fputs("Logo: Image Magick library not found\n", stderr); + else fputs("Logo: Failed to load / convert the image source\n", stderr); - return false; - default: - return true; } + + return false; } #endif //FF_HAVE_IMAGEMAGICK{6, 7} -bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type) +bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type, bool printError) { - if(!ffFileExists(instance->config.logo.source.chars, S_IFREG)) + if(!ffFileExists(instance->config.logo.source.chars, S_IFREG & S_IFLNK)) { - fputs("Logo: Image file not found\n", stderr); + if(printError) + fprintf(stderr, "Logo: Image source \"%s\" does not exist\n", instance->config.logo.source.chars); return false; } @@ -764,18 +768,20 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type) ) return printImageKittyDirect(instance); - #ifndef FF_HAVE_CHAFA + #if !defined(FF_HAVE_CHAFA) if(type == FF_LOGO_TYPE_IMAGE_CHAFA) { - fputs("Logo: Fastfetch was built without Chafa support\n", stderr); + if(printError) + fputs("Logo: Chafa support is not compiled in\n", stderr); return false; } #endif - #if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6) - return printImageIfExistsSlowPath(instance, type); - #else - fputs("Logo: Fastfetch was built without ImageMagick support\n", stderr); + #if !defined(FF_HAVE_IMAGEMAGICK7) && !defined(FF_HAVE_IMAGEMAGICK6) + if(printError) + fputs("Logo: Image Magick support is not compiled in\n", stderr); return false; + #else + return printImageIfExistsSlowPath(instance, type, printError); #endif } diff --git a/src/logo/logo.c b/src/logo/logo.c index 60cbdf8bb..5531a9942 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -280,15 +280,19 @@ static inline void logoPrintDetected(FFinstance* instance) logoPrintStruct(instance, logoGetBuiltinDetected(instance)); } -static void logoPrintData(FFinstance* instance, bool doColorReplacement) { +static bool logoPrintData(FFinstance* instance, bool doColorReplacement) { + if(instance->config.logo.source.length == 0) + return false; + ffLogoPrintChars(instance, instance->config.logo.source.chars, doColorReplacement); logoApplyColorsDetected(instance); + return true; } -static bool loadLogoFile(const FFinstance* instance, FFstrbuf* buffer) +static void updateLogoPath(FFinstance* instance) { - if(ffAppendFileBuffer(instance->config.logo.source.chars, buffer)) - return true; + if(ffFileExists(instance->config.logo.source.chars, S_IFREG & S_IFLNK)) + return; FFstrbuf fullPath; ffStrbufInit(&fullPath); @@ -300,15 +304,14 @@ static bool loadLogoFile(const FFinstance* instance, FFstrbuf* buffer) ffStrbufAppendS(&fullPath, "fastfetch/logos/"); ffStrbufAppend(&fullPath, &instance->config.logo.source); - if(ffAppendFileBuffer(fullPath.chars, buffer)) + if(ffFileExists(fullPath.chars, S_IFREG & S_IFLNK)) { - ffStrbufDestroy(&fullPath); - return true; + ffStrbufSet(&instance->config.logo.source, &fullPath); + break; } } ffStrbufDestroy(&fullPath); - return false; } static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement, bool raw) @@ -316,7 +319,7 @@ static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement, FFstrbuf content; ffStrbufInit(&content); - if(!loadLogoFile(instance, &content)) + if(!ffAppendFileBuffer(instance->config.logo.source.chars, &content)) { ffStrbufDestroy(&content); fputs("Logo: Failed to load file content from logo source\n", stderr); @@ -332,45 +335,57 @@ static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement, return true; } -static bool logoPrintImageIfExists(FFinstance* instance, FFLogoType logo) +static bool logoPrintImageIfExists(FFinstance* instance, FFLogoType logo, bool printError) { - if(!ffLogoPrintImageIfExists(instance, logo)) + if(!ffLogoPrintImageIfExists(instance, logo, printError)) return false; logoApplyColorsDetected(instance); return true; } -static void logoPrintKnownType(FFinstance* instance) +static bool logoTryKnownType(FFinstance* instance) { - bool successfull = true; + if(instance->config.logo.type == FF_LOGO_TYPE_NONE) + { + logoApplyColorsDetected(instance); + return true; + } if(instance->config.logo.type == FF_LOGO_TYPE_BUILTIN) - successfull = logoPrintBuiltinIfExists(instance, instance->config.logo.source.chars); - else if(instance->config.logo.type == FF_LOGO_TYPE_FILE) - successfull = logoPrintFileIfExists(instance, true, false); - else if(instance->config.logo.type == FF_LOGO_TYPE_FILE_RAW) - successfull = logoPrintFileIfExists(instance, false, false); - else if(instance->config.logo.type == FF_LOGO_TYPE_DATA) - logoPrintData(instance, true); - else if(instance->config.logo.type == FF_LOGO_TYPE_DATA_RAW) - logoPrintData(instance, false); - else if(instance->config.logo.type == FF_LOGO_TYPE_IMAGE_RAW) + return logoPrintBuiltinIfExists(instance, instance->config.logo.source.chars); + + if(instance->config.logo.type == FF_LOGO_TYPE_DATA) + return logoPrintData(instance, true); + + if(instance->config.logo.type == FF_LOGO_TYPE_DATA_RAW) + return logoPrintData(instance, false); + + updateLogoPath(instance); //We sure have a file, resolve relative paths + + if(instance->config.logo.type == FF_LOGO_TYPE_FILE) + return logoPrintFileIfExists(instance, true, false); + + if(instance->config.logo.type == FF_LOGO_TYPE_FILE_RAW) + return logoPrintFileIfExists(instance, false, false); + + if(instance->config.logo.type == FF_LOGO_TYPE_IMAGE_RAW) { if(instance->config.logo.width == 0 || instance->config.logo.height == 0) { fputs("both `--logo-width` and `--logo-height` must be specified\n", stderr); - successfull = false; + return false; } - else - successfull = logoPrintFileIfExists(instance, false, true); - } - else if(instance->config.logo.type == FF_LOGO_TYPE_NONE) - logoApplyColorsDetected(instance); - else //image - successfull = logoPrintImageIfExists(instance, instance->config.logo.type); - if(!successfull) + return logoPrintFileIfExists(instance, false, true); + } + + return logoPrintImageIfExists(instance, instance->config.logo.type, true); +} + +static void logoPrintKnownType(FFinstance* instance) +{ + if(!logoTryKnownType(instance)) logoPrintDetected(instance); } @@ -404,6 +419,9 @@ void ffLogoPrint(FFinstance* instance) if(logoPrintBuiltinIfExists(instance, instance->config.logo.source.chars)) return; + //Make sure the logo path is set correctly. + updateLogoPath(instance); + const FFTerminalShellResult* terminalShell = ffDetectTerminalShell(instance); //Terminal emulators that support kitty graphics protocol. @@ -414,7 +432,7 @@ void ffLogoPrint(FFinstance* instance) ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0; //Try to load the logo as an image. If it succeeds, print it and return. - if(logoPrintImageIfExists(instance, supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA)) + if(logoPrintImageIfExists(instance, supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false)) return; //Try to load the logo as a file. If it succeeds, print it and return. diff --git a/src/logo/logo.h b/src/logo/logo.h index 4bdc6a54a..0664f6f98 100644 --- a/src/logo/logo.h +++ b/src/logo/logo.h @@ -24,6 +24,6 @@ const FFlogo* ffLogoBuiltinGetUnknown(); GetLogoMethod* ffLogoBuiltinGetAll(); //image/image.c -bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type); +bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type, bool printError); #endif From 3b0e1a583348763286838e75c61c5633ea47bb3b Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 28 Jan 2023 11:28:05 +0100 Subject: [PATCH 031/119] Image: Use correct cache dir --- src/logo/image/image.c | 2 +- src/util/platform/FFPlatform_unix.c | 2 -- src/util/platform/FFPlatform_windows.c | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index f3cb90da1..8eda37811 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -694,7 +694,7 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type, bo ffStrbufInit(&requestData.cacheDir); ffStrbufAppend(&requestData.cacheDir, &instance->state.platform.cacheDir); - ffStrbufAppendS(&requestData.cacheDir, "fastfetch"); + ffStrbufAppendS(&requestData.cacheDir, "fastfetch/images"); ffStrbufEnsureFree(&requestData.cacheDir, PATH_MAX); if(realpath(instance->config.logo.source.chars, requestData.cacheDir.chars + requestData.cacheDir.length) == NULL) diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 393d2290b..65dad8d8b 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -29,8 +29,6 @@ static void getCacheDir(FFPlatform* platform) ffStrbufAppend(&platform->cacheDir, &platform->homeDir); ffStrbufAppendS(&platform->cacheDir, ".cache/"); } - - ffStrbufAppendS(&platform->cacheDir, "fastfetch/"); } static void getConfigDirs(FFPlatform* platform) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 2fff50ef5..0e5e8a078 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -33,8 +33,6 @@ static void getCacheDir(FFPlatform* platform) ffStrbufAppendS(&platform->cacheDir, "AppData/Local/"); } CoTaskMemFree(pPath); - - ffStrbufAppendS(&platform->cacheDir, "fastfetch/"); } static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) From 2c51d55ba243443c85523522ef0d8fb3c201120e Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 28 Jan 2023 11:52:23 +0100 Subject: [PATCH 032/119] IO: don't require posix specific stuff for ffPathExists --- src/common/io.c | 40 ++++++++++++++++++- src/common/io.h | 15 +++++-- src/common/settings.c | 2 +- src/detection/cpu/cpu_linux.c | 2 +- src/detection/displayserver/linux/wmde.c | 2 +- src/detection/packages/packages_linux.c | 4 +- .../terminalfont/terminalfont_android.c | 2 +- src/detection/wifi/wifi_linux.c | 2 +- src/fastfetch.c | 4 +- src/logo/image/image.c | 2 +- src/logo/logo.c | 4 +- 11 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/common/io.c b/src/common/io.c index 1c2fb918b..02edf5143 100644 --- a/src/common/io.c +++ b/src/common/io.c @@ -7,6 +7,7 @@ #ifdef _WIN32 #include #else + #include #include #include #endif @@ -231,12 +232,47 @@ void ffSuppressIO(bool suppress) dup2(suppress ? nullFile : origErr, STDERR_FILENO); } -bool ffFileExists(const char* fileName, mode_t mode) +#ifndef _WIN32 +bool ffPathExists(const char* path, FFPathType type) { struct stat fileStat; - return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode); + if(stat(path, &fileStat) != 0) + return false; + + int mode = fileStat.st_mode & S_IFMT; + + if(type & FF_PATHTYPE_REGULAR && mode == S_IFREG) + return true; + + if(type & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR) + return true; + + if(type & FF_PATHTYPE_LINK && mode == S_IFLNK) + return true; + + return false; } +#else +bool ffPathExists(const char* path, FFPathType type) +{ + DWORD attr = GetFileAttributesA(path); + if(attr == INVALID_FILE_ATTRIBUTES) + return false; + + if(type & FF_PATHTYPE_REGULAR && !(attr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + if(type & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + if(type & FF_PATHTYPE_LINK && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) + return true; + + return false; +} +#endif + void ffGetTerminalResponse(const char* request, const char* format, ...) { #ifndef WIN32 diff --git a/src/common/io.h b/src/common/io.h index b5446f455..c30765d9c 100644 --- a/src/common/io.h +++ b/src/common/io.h @@ -5,8 +5,6 @@ #include "fastfetch.h" -#include //mode_t, fstat, stat - bool ffWriteFDBuffer(int fd, const FFstrbuf* content); bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data); bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer); @@ -20,7 +18,18 @@ bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer); bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer); #endif -bool ffFileExists(const char* fileName, mode_t mode); +//Bit flags, combine with | +typedef enum FFPathType +{ + FF_PATHTYPE_REGULAR = 1, + FF_PATHTYPE_LINK = 2, + FF_PATHTYPE_DIRECTORY = 4 +} FFPathType; + +#define FF_PATHTYPE_FILE (FF_PATHTYPE_REGULAR | FF_PATHTYPE_LINK) +#define FF_PATHTYPE_ANY (FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY) + +bool ffPathExists(const char* path, FFPathType pathType); // Not thread safe! void ffSuppressIO(bool suppress); diff --git a/src/common/settings.c b/src/common/settings.c index 38cbd4b36..6c2725692 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -309,7 +309,7 @@ static const SQLiteData* getSQLiteData(const FFinstance* instance) int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query) { - if(!ffFileExists(dbPath, S_IFREG)) + if(!ffPathExists(dbPath, FF_PATHTYPE_FILE)) return 0; const SQLiteData* data = getSQLiteData(instance); diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 73ce6eaca..b06569b9d 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -131,7 +131,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu) cpu->coresOnline = (uint16_t) get_nprocs(); #define BP "/sys/devices/system/cpu/cpufreq/policy0/" - if(ffFileExists(BP, S_IFDIR)) + if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY)) { cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq"); cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq"); diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 4d9d79b6a..b45c06cf9 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -48,7 +48,7 @@ static const char* parseEnv() if( getenv("WAYLAND_DISPLAY") != NULL && - ffFileExists("/mnt/wslg/", S_IFDIR) + ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY) ) return "WSLg"; return NULL; diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index ace7d637e..9b8243f3f 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -88,7 +88,7 @@ static uint32_t countFilesRecursiveImpl(FFstrbuf* baseDirPath, const char* filen ffStrbufAppendC(baseDirPath, '/'); ffStrbufAppendS(baseDirPath, filename); - bool exists = ffFileExists(baseDirPath->chars, S_IFREG); + bool exists = ffPathExists(baseDirPath->chars, FF_PATHTYPE_FILE); ffStrbufSubstrBefore(baseDirPath, baseDirPathLength); if(exists) return 1; @@ -129,7 +129,7 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons static uint32_t getNixPackagesImpl(char* path) { //Nix detection is kinda slow, so we only do it if the dir exists - if(!ffFileExists(path, S_IFDIR)) + if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY)) return 0; FFstrbuf output; diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 6c6a224a0..55e74ea6b 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -62,7 +62,7 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh return; } - if(!ffFileExists(FF_TERMUX_FONT_PATH, S_IFREG)) + if(!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE)) { ffFontInitCopy(&terminalFont->font, "monospace"); return; diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index a8f70620d..2db259ecb 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -219,7 +219,7 @@ static const char* detectWifiWithIoctls(FF_MAYBE_UNUSED const FFinstance* instan for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i) { ffStrbufSetF(&path, "/sys/class/net/%s/phy80211", i->if_name); - if(!ffFileExists(path.chars, S_IFDIR)) + if(!ffPathExists(path.chars, FF_PATHTYPE_DIRECTORY)) continue; FFWifiResult* item = (FFWifiResult*)ffListAdd(result); diff --git a/src/fastfetch.c b/src/fastfetch.c index 979f37b62..cd48b0540 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -556,7 +556,7 @@ static void listConfigPaths(FFinstance* instance) FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.platform.configDirs) { ffStrbufAppendS(folder, "fastfetch/config.conf"); - printf("%s%s\n", folder->chars, ffFileExists(folder->chars, S_IFREG) ? " (*)" : ""); + printf("%s%s\n", folder->chars, ffPathExists(folder->chars, FF_PATHTYPE_FILE) ? " (*)" : ""); } } @@ -640,7 +640,7 @@ static void generateConfigFile(FFinstance* instance, bool force) // Paths generated in `init.c/initConfigDirs` end with `/` ffStrbufAppendS(filename, "fastfetch/config.conf"); - if (!force && ffFileExists(filename->chars, S_IFREG)) + if (!force && ffPathExists(filename->chars, FF_PATHTYPE_FILE)) { fprintf(stderr, "Config file exists in `%s`, use `--gen-config-force` to overwrite\n", filename->chars); exit(1); diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 8eda37811..5f81782cc 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -750,7 +750,7 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type, bo bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type, bool printError) { - if(!ffFileExists(instance->config.logo.source.chars, S_IFREG & S_IFLNK)) + if(!ffPathExists(instance->config.logo.source.chars, FF_PATHTYPE_FILE)) { if(printError) fprintf(stderr, "Logo: Image source \"%s\" does not exist\n", instance->config.logo.source.chars); diff --git a/src/logo/logo.c b/src/logo/logo.c index 5531a9942..f64f7187f 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -291,7 +291,7 @@ static bool logoPrintData(FFinstance* instance, bool doColorReplacement) { static void updateLogoPath(FFinstance* instance) { - if(ffFileExists(instance->config.logo.source.chars, S_IFREG & S_IFLNK)) + if(ffPathExists(instance->config.logo.source.chars, FF_PATHTYPE_FILE)) return; FFstrbuf fullPath; @@ -304,7 +304,7 @@ static void updateLogoPath(FFinstance* instance) ffStrbufAppendS(&fullPath, "fastfetch/logos/"); ffStrbufAppend(&fullPath, &instance->config.logo.source); - if(ffFileExists(fullPath.chars, S_IFREG & S_IFLNK)) + if(ffPathExists(fullPath.chars, FF_PATHTYPE_FILE)) { ffStrbufSet(&instance->config.logo.source, &fullPath); break; From a1ea7804f3bebd923ef6142776bc83d4f8e53488 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 28 Jan 2023 12:40:12 +0100 Subject: [PATCH 033/119] IO: Separate platform specific implementations --- CMakeLists.txt | 6 +- src/common/io.h | 39 ---- src/common/io/io.h | 64 ++++++ src/common/{io.c => io/io_unix.c} | 196 +++--------------- src/common/io/io_windows.c | 117 +++++++++++ src/common/processing_linux.c | 2 +- src/common/settings.c | 2 +- src/detection/battery/battery_linux.c | 2 +- src/detection/bios/bios_linux.c | 2 +- src/detection/board/board_linux.c | 2 +- src/detection/brightness/brightness_linux.c | 2 +- src/detection/chassis/chassis_linux.c | 2 +- src/detection/cpu/cpu_linux.c | 2 +- src/detection/displayserver/linux/wayland.c | 2 +- src/detection/displayserver/linux/wmde.c | 2 +- src/detection/font/font_apple.m | 2 +- src/detection/host/host_linux.c | 2 +- src/detection/packages/packages_linux.c | 2 +- src/detection/temps/temps_linux.c | 2 +- src/detection/terminalfont/terminalfont.c | 2 +- .../terminalfont/terminalfont_android.c | 2 +- .../terminalfont/terminalfont_windows.c | 2 +- src/detection/terminalshell/terminalshell.c | 2 +- .../terminalshell/terminalshell_linux.c | 2 +- src/detection/vulkan.c | 2 +- src/detection/wifi/wifi_linux.c | 2 +- src/fastfetch.c | 2 +- src/logo/image/image.c | 2 +- src/logo/logo.c | 2 +- 29 files changed, 243 insertions(+), 227 deletions(-) delete mode 100644 src/common/io.h create mode 100644 src/common/io/io.h rename src/common/{io.c => io/io_unix.c} (54%) create mode 100644 src/common/io/io_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 927448737..a2e5c3957 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,7 +227,6 @@ set(LIBFASTFETCH_SRC src/common/font.c src/common/format.c src/common/init.c - src/common/io.c src/common/library.c src/common/parsing.c src/common/printing.c @@ -313,6 +312,7 @@ set(LIBFASTFETCH_SRC if(LINUX) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c + src/common/io/io_unix.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_linux.c @@ -356,6 +356,7 @@ if(LINUX) ) elseif(ANDROID) list(APPEND LIBFASTFETCH_SRC + src/common/io/io_unix.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_android.c @@ -394,6 +395,7 @@ elseif(ANDROID) elseif(BSD) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c + src/common/io/io_unix.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -438,6 +440,7 @@ elseif(BSD) ) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC + src/common/io/io_unix.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -479,6 +482,7 @@ elseif(APPLE) ) elseif(WIN32) list(APPEND LIBFASTFETCH_SRC + src/common/io/io_windows.c src/common/networking_windows.c src/common/processing_windows.c src/detection/battery/battery_windows.c diff --git a/src/common/io.h b/src/common/io.h deleted file mode 100644 index c30765d9c..000000000 --- a/src/common/io.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#ifndef FF_INCLUDED_common_io -#define FF_INCLUDED_common_io - -#include "fastfetch.h" - -bool ffWriteFDBuffer(int fd, const FFstrbuf* content); -bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data); -bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer); - -bool ffAppendFDBuffer(int fd, FFstrbuf* buffer); -ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data); -bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer); -bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer); - -#ifdef _WIN32 -bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer); -#endif - -//Bit flags, combine with | -typedef enum FFPathType -{ - FF_PATHTYPE_REGULAR = 1, - FF_PATHTYPE_LINK = 2, - FF_PATHTYPE_DIRECTORY = 4 -} FFPathType; - -#define FF_PATHTYPE_FILE (FF_PATHTYPE_REGULAR | FF_PATHTYPE_LINK) -#define FF_PATHTYPE_ANY (FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY) - -bool ffPathExists(const char* path, FFPathType pathType); - -// Not thread safe! -void ffSuppressIO(bool suppress); - -FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...); - -#endif diff --git a/src/common/io/io.h b/src/common/io/io.h new file mode 100644 index 000000000..25762a51b --- /dev/null +++ b/src/common/io/io.h @@ -0,0 +1,64 @@ +#pragma once + +#ifndef FF_INCLUDED_common_io_io +#define FF_INCLUDED_common_io_io + +#include "fastfetch.h" + +#ifdef _WIN32 + #include + typedef HANDLE FFNativeFD; +#else + #include + typedef int FFNativeFD; +#endif + +static inline bool ffWriteFDBuffer(FFNativeFD fd, const FFstrbuf* content) +{ + #ifndef _WIN32 + return write(fd, content->chars, content->length) != -1; + #else + DWORD written; + return WriteFile(fd, content->chars, content->length, &written, NULL) && written == content->length; + #endif +} + +bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data); + +static inline bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer) +{ + return ffWriteFileData(fileName, buffer->length, buffer->chars); +} + +bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer); +ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data); +bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer); + +static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer) +{ + ffStrbufClear(buffer); + return ffAppendFileBuffer(fileName, buffer); +} + +//Bit flags, combine with | +typedef enum FFPathType +{ + FF_PATHTYPE_REGULAR = 1, + FF_PATHTYPE_LINK = 2, + FF_PATHTYPE_DIRECTORY = 4 +} FFPathType; + +#define FF_PATHTYPE_FILE (FF_PATHTYPE_REGULAR | FF_PATHTYPE_LINK) +#define FF_PATHTYPE_ANY (FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY) + +bool ffPathExists(const char* path, FFPathType pathType); + +#ifndef _WIN32 + FF_C_SCANF(2, 3) + void ffGetTerminalResponse(const char* request, const char* format, ...); +#endif + +// Not thread safe! +void ffSuppressIO(bool suppress); + +#endif // FF_INCLUDED_common_io_io diff --git a/src/common/io.c b/src/common/io/io_unix.c similarity index 54% rename from src/common/io.c rename to src/common/io/io_unix.c index 02edf5143..c4846525f 100644 --- a/src/common/io.c +++ b/src/common/io/io_unix.c @@ -1,16 +1,9 @@ -#include "fastfetch.h" -#include "common/io.h" +#include "io.h" -#include #include - -#ifdef _WIN32 - #include -#else - #include - #include - #include -#endif +#include +#include +#include static void createSubfolders(const char* fileName) { @@ -21,41 +14,15 @@ static void createSubfolders(const char* fileName) { ffStrbufAppendC(&path, *fileName); if(*fileName == '/') - { - mkdir(path.chars - #ifndef WIN32 - , S_IRWXU | S_IRGRP | S_IROTH - #endif - ); - } + mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH); ++fileName; } ffStrbufDestroy(&path); } -bool ffWriteFDBuffer(int fd, const FFstrbuf* content) -{ - return write(fd, content->chars, content->length) != -1; -} - bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) { - #ifdef _WIN32 - HANDLE handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if(handle == INVALID_HANDLE_VALUE) - { - createSubfolders(fileName); - handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if(handle == INVALID_HANDLE_VALUE) - return false; - } - - DWORD written; - bool ret = !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL); - - CloseHandle(handle); - #else int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC; int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; @@ -71,52 +38,10 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) bool ret = write(fd, data, dataSize) != -1; close(fd); - #endif return ret; } -bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer) -{ - return ffWriteFileData(fileName, buffer->length, buffer->chars); -} - -#ifdef _WIN32 - -bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer) -{ - DWORD readed = 0; - - LARGE_INTEGER fileSize; - if(!GetFileSizeEx(handle, &fileSize)) - fileSize.QuadPart = 0; - - ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31); - uint32_t free = ffStrbufGetFree(buffer); - - bool success; - while( - (success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) && - (uint32_t) readed == free - ) { - buffer->length += (uint32_t) readed; - ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. - free = ffStrbufGetFree(buffer); - } - - if(readed > 0) - buffer->length += (uint32_t) readed; - - buffer->chars[buffer->length] = '\0'; - - ffStrbufTrimRight(buffer, '\n'); - ffStrbufTrimRight(buffer, ' '); - - return success; -} - -#endif - bool ffAppendFDBuffer(int fd, FFstrbuf* buffer) { ssize_t readed = 0; @@ -151,17 +76,6 @@ bool ffAppendFDBuffer(int fd, FFstrbuf* buffer) ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) { - #ifdef _WIN32 - HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if(handle == INVALID_HANDLE_VALUE) - return false; - - DWORD readed; - if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL)) - return -1; - - return (ssize_t)readed; - #else int fd = open(fileName, O_RDONLY); if(fd == -1) return -1; @@ -171,20 +85,10 @@ ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) close(fd); return readed; - #endif } bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) { - #ifdef _WIN32 - HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if(handle == INVALID_HANDLE_VALUE) - return false; - - bool ret = ffAppendHandleBuffer(handle, buffer); - - CloseHandle(handle); - #else int fd = open(fileName, O_RDONLY); if(fd == -1) return false; @@ -192,47 +96,10 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) bool ret = ffAppendFDBuffer(fd, buffer); close(fd); - #endif return ret; } -bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer) -{ - ffStrbufClear(buffer); - return ffAppendFileBuffer(fileName, buffer); -} - -// Not thread safe! -void ffSuppressIO(bool suppress) -{ - static bool init = false; - static int origOut = -1; - static int origErr = -1; - static int nullFile = -1; - - if(!init) - { - if(!suppress) - return; - - origOut = dup(STDOUT_FILENO); - origErr = dup(STDERR_FILENO); - nullFile = open("/dev/null", O_WRONLY); - init = true; - } - - if(nullFile == -1) - return; - - fflush(stdout); - fflush(stderr); - - dup2(suppress ? nullFile : origOut, STDOUT_FILENO); - dup2(suppress ? nullFile : origErr, STDERR_FILENO); -} - -#ifndef _WIN32 bool ffPathExists(const char* path, FFPathType type) { struct stat fileStat; @@ -253,29 +120,8 @@ bool ffPathExists(const char* path, FFPathType type) return false; } -#else -bool ffPathExists(const char* path, FFPathType type) -{ - DWORD attr = GetFileAttributesA(path); - if(attr == INVALID_FILE_ATTRIBUTES) - return false; - - if(type & FF_PATHTYPE_REGULAR && !(attr & FILE_ATTRIBUTE_DIRECTORY)) - return true; - - if(type & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY)) - return true; - - if(type & FF_PATHTYPE_LINK && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) - return true; - - return false; -} -#endif - void ffGetTerminalResponse(const char* request, const char* format, ...) { - #ifndef WIN32 struct termios oldTerm, newTerm; if(tcgetattr(STDIN_FILENO, &oldTerm) == -1) return; @@ -314,8 +160,32 @@ void ffGetTerminalResponse(const char* request, const char* format, ...) va_start(args, format); vsscanf(buffer, format, args); va_end(args); - #else - //Unimplemented - FF_UNUSED(request, format); - #endif +} + +void ffSuppressIO(bool suppress) +{ + static bool init = false; + static int origOut = -1; + static int origErr = -1; + static int nullFile = -1; + + if(!init) + { + if(!suppress) + return; + + origOut = dup(STDOUT_FILENO); + origErr = dup(STDERR_FILENO); + nullFile = open("/dev/null", O_WRONLY); + init = true; + } + + if(nullFile == -1) + return; + + fflush(stdout); + fflush(stderr); + + dup2(suppress ? nullFile : origOut, STDOUT_FILENO); + dup2(suppress ? nullFile : origErr, STDERR_FILENO); } diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c new file mode 100644 index 000000000..7ac79c392 --- /dev/null +++ b/src/common/io/io_windows.c @@ -0,0 +1,117 @@ +#include "io.h" + +static void createSubfolders(const char* fileName) +{ + FFstrbuf path; + ffStrbufInit(&path); + + while(*fileName != '\0') + { + ffStrbufAppendC(&path, *fileName); + if(*fileName == '/') + CreateDirectoryA(path.chars, NULL); + ++fileName; + } + + ffStrbufDestroy(&path); +} + +bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) +{ + HANDLE handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if(handle == INVALID_HANDLE_VALUE) + { + createSubfolders(fileName); + handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if(handle == INVALID_HANDLE_VALUE) + return false; + } + + DWORD written; + bool ret = !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL); + + CloseHandle(handle); + + return ret; +} + +bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer) +{ + DWORD readed = 0; + + LARGE_INTEGER fileSize; + if(!GetFileSizeEx(handle, &fileSize)) + fileSize.QuadPart = 0; + + ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31); + uint32_t free = ffStrbufGetFree(buffer); + + bool success; + while( + (success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) && + (uint32_t) readed == free + ) { + buffer->length += (uint32_t) readed; + ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. + free = ffStrbufGetFree(buffer); + } + + if(readed > 0) + buffer->length += (uint32_t) readed; + + buffer->chars[buffer->length] = '\0'; + + ffStrbufTrimRight(buffer, '\n'); + ffStrbufTrimRight(buffer, ' '); + + return success; +} + +ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) +{ + HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(handle == INVALID_HANDLE_VALUE) + return false; + + DWORD readed; + if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL)) + return -1; + + return (ssize_t)readed; +} + +bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) +{ + HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(handle == INVALID_HANDLE_VALUE) + return false; + + bool ret = ffAppendFDBuffer(handle, buffer); + + CloseHandle(handle); + + return ret; +} + +bool ffPathExists(const char* path, FFPathType type) +{ + DWORD attr = GetFileAttributesA(path); + if(attr == INVALID_FILE_ATTRIBUTES) + return false; + + if(type & FF_PATHTYPE_REGULAR && !(attr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + if(type & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + if(type & FF_PATHTYPE_LINK && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) + return true; + + return false; +} + +void ffSuppressIO(bool suppress) +{ + FF_UNUSED(suppress); +} diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index a628aeb3d..74502ef52 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/processing.h" -#include "common/io.h" +#include "common/io/io.h" #include #include diff --git a/src/common/settings.c b/src/common/settings.c index 6c2725692..280557358 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -2,7 +2,7 @@ #include "common/settings.h" #include "common/library.h" #include "common/thread.h" -#include "common/io.h" +#include "common/io/io.h" #include diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 756dd9c8a..b78a6cf7f 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "common/io.h" +#include "common/io/io.h" #include "battery.h" #include diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index 10bbab589..ce23edf89 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -1,5 +1,5 @@ #include "bios.h" -#include "common/io.h" +#include "common/io/io.h" #include diff --git a/src/detection/board/board_linux.c b/src/detection/board/board_linux.c index 8e92eec4e..8f5bcd2ff 100644 --- a/src/detection/board/board_linux.c +++ b/src/detection/board/board_linux.c @@ -1,5 +1,5 @@ #include "board.h" -#include "common/io.h" +#include "common/io/io.h" #include diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index 0f2a9d5fd..97f3ea4f9 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -1,5 +1,5 @@ #include "brightness.h" -#include "common/io.h" +#include "common/io/io.h" #include diff --git a/src/detection/chassis/chassis_linux.c b/src/detection/chassis/chassis_linux.c index 192747e7d..0898fa4b8 100644 --- a/src/detection/chassis/chassis_linux.c +++ b/src/detection/chassis/chassis_linux.c @@ -1,5 +1,5 @@ #include "chassis.h" -#include "common/io.h" +#include "common/io/io.h" #include diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index b06569b9d..202317033 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -1,5 +1,5 @@ #include "cpu.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/properties.h" #include "detection/temps/temps_linux.h" diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 27a5c09d3..71dd0b07b 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -5,7 +5,7 @@ #ifdef FF_HAVE_WAYLAND #include "common/library.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/thread.h" #include #include diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index b45c06cf9..779e296d9 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -1,5 +1,5 @@ #include "displayserver_linux.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/properties.h" #include "common/parsing.h" #include "common/processing.h" diff --git a/src/detection/font/font_apple.m b/src/detection/font/font_apple.m index 773c7705b..6f26803b0 100644 --- a/src/detection/font/font_apple.m +++ b/src/detection/font/font_apple.m @@ -1,5 +1,5 @@ #include "common/font.h" -#include "common/io.h" +#include "common/io/io.h" #include "font.h" #import diff --git a/src/detection/host/host_linux.c b/src/detection/host/host_linux.c index e4e7dfef1..04ae3aa27 100644 --- a/src/detection/host/host_linux.c +++ b/src/detection/host/host_linux.c @@ -1,5 +1,5 @@ #include "host.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/processing.h" #include diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 9b8243f3f..c3cd1381d 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -1,5 +1,5 @@ #include "packages.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/parsing.h" #include "common/processing.h" #include "common/properties.h" diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 913e6f037..0ade8180f 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/thread.h" #include "temps_linux.h" diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 002169f82..1d3503da2 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -182,7 +182,7 @@ exit: } #ifdef _WIN32 - #include "common/io.h" + #include "common/io/io.h" #include #endif diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 55e74ea6b..f3f6a38d6 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -1,7 +1,7 @@ #include "fastfetch.h" #include "terminalfont.h" #include "detection/terminalshell/terminalshell.h" -#include "common/io.h" +#include "common/io/io.h" #ifdef FF_HAVE_FREETYPE #include "common/library.h" diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index 060108290..e84d73d9e 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -1,5 +1,5 @@ #include "common/properties.h" -#include "common/io.h" +#include "common/io/io.h" #include "detection/terminalshell/terminalshell.h" #include "terminalfont.h" #include "util/windows/unicode.h" diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index aa9d221f3..435885329 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/processing.h" #include "common/properties.h" diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 1f30866c2..e6b765ba9 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/parsing.h" #include "common/processing.h" #include "common/thread.h" diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index dbda127bb..c61e6f8f8 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -5,7 +5,7 @@ #ifdef FF_HAVE_VULKAN #include "common/library.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/parsing.h" #include #include diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 2db259ecb..5bc789cdb 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -200,7 +200,7 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul #endif -#include "common/io.h" +#include "common/io/io.h" #include #include diff --git a/src/fastfetch.c b/src/fastfetch.c index cd48b0540..f62205616 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -2,7 +2,7 @@ #include "util/FFvaluestore.h" #include "common/printing.h" #include "common/parsing.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/time.h" #include diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 5f81782cc..25df0e9ff 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -1,5 +1,5 @@ #include "image.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/printing.h" #ifdef __APPLE__ diff --git a/src/logo/logo.c b/src/logo/logo.c index f64f7187f..43d39bc97 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -1,5 +1,5 @@ #include "logo.h" -#include "common/io.h" +#include "common/io/io.h" #include "common/printing.h" #include "detection/os/os.h" #include "detection/terminalshell/terminalshell.h" From e4973b32624a774ae6c8a6767d4de7e2d0d73a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Jan 2023 22:05:23 +0800 Subject: [PATCH 034/119] IO: fix Windows part; silense warnings --- src/common/io/io.h | 37 +++++++++++++++++++++++++++++++++---- src/common/io/io_unix.c | 2 +- src/common/io/io_windows.c | 10 +++++----- src/logo/image/image.c | 6 +++--- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/common/io/io.h b/src/common/io/io.h index 25762a51b..9c135f5fd 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -7,22 +7,37 @@ #ifdef _WIN32 #include + #include typedef HANDLE FFNativeFD; #else #include typedef int FFNativeFD; #endif -static inline bool ffWriteFDBuffer(FFNativeFD fd, const FFstrbuf* content) +static inline FFNativeFD FFUnixFD2NativeFD(int unixfd) { #ifndef _WIN32 - return write(fd, content->chars, content->length) != -1; + return unixfd; + #else + return (FFNativeFD) _get_osfhandle(unixfd); + #endif +} + +static inline bool ffWriteFDData(FFNativeFD fd, size_t dataSize, const void* data) +{ + #ifndef _WIN32 + return write(fd, data, dataSize) != -1; #else DWORD written; - return WriteFile(fd, content->chars, content->length, &written, NULL) && written == content->length; + return WriteFile(fd, data, (DWORD) dataSize, &written, NULL) && written == dataSize; #endif } +static inline bool ffWriteFDBuffer(FFNativeFD fd, const FFstrbuf* content) +{ + return ffWriteFDData(fd, content->length, content->chars); +} + bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data); static inline bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer) @@ -30,8 +45,22 @@ static inline bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffe return ffWriteFileData(fileName, buffer->length, buffer->chars); } -bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer); +static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data) +{ + #ifndef _WIN32 + return read(fd, data, dataSize); + #else + DWORD readed; + if(!ReadFile(fd, data, (DWORD)dataSize, &readed, NULL)) + return -1; + + return (ssize_t)readed; + #endif +} + ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data); + +bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer); bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer); static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index c4846525f..79dcd7e04 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -80,7 +80,7 @@ ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) if(fd == -1) return -1; - ssize_t readed = read(fd, data, dataSize); + ssize_t readed = ffReadFDData(fd, dataSize, data); close(fd); diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 7ac79c392..56d6ccf60 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -71,13 +71,13 @@ ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) { HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(handle == INVALID_HANDLE_VALUE) - return false; - - DWORD readed; - if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL)) return -1; - return (ssize_t)readed; + ssize_t readed = ffReadFDData(handle, dataSize, data); + + CloseHandle(handle); + + return readed; } bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 25df0e9ff..96be2d049 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -229,7 +229,7 @@ static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestDat ffPrintCharTimes('\n', instance->config.logo.paddingTop); ffPrintCharTimes(' ', instance->config.logo.paddingLeft); fflush(stdout); - ffWriteFDBuffer(STDOUT_FILENO, result); + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), result); //Go to upper left corner fputs("\033[9999999D", stdout); @@ -614,8 +614,8 @@ static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestDat char buffer[32768]; ssize_t readBytes; - while((readBytes = read(fd, buffer, sizeof(buffer))) > 0) - FF_UNUSED(write(STDOUT_FILENO, buffer, (size_t) readBytes)); + while((readBytes = ffReadFDData(FFUnixFD2NativeFD(fd), sizeof(buffer), buffer)) > 0) + ffWriteFDData(FFUnixFD2NativeFD(STDOUT_FILENO), (size_t) readBytes, buffer); close(fd); From 679162c76228baed1966ec1768652530d6f0d716 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 28 Jan 2023 17:19:45 +0100 Subject: [PATCH 035/119] --list-logos: list custom logos too --- src/common/io/io.h | 2 + src/common/io/io_unix.c | 46 +++++++++++++++++++ src/common/io/io_windows.c | 45 +++++++++++++++++++ src/fastfetch.c | 90 ++++++-------------------------------- 4 files changed, 107 insertions(+), 76 deletions(-) diff --git a/src/common/io/io.h b/src/common/io/io.h index 9c135f5fd..c078b4122 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -90,4 +90,6 @@ bool ffPathExists(const char* path, FFPathType pathType); // Not thread safe! void ffSuppressIO(bool suppress); +void ffListFilesRecursively(const char* path); + #endif // FF_INCLUDED_common_io_io diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 79dcd7e04..f343eb120 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -4,6 +4,7 @@ #include #include #include +#include static void createSubfolders(const char* fileName) { @@ -189,3 +190,48 @@ void ffSuppressIO(bool suppress) dup2(suppress ? nullFile : origOut, STDOUT_FILENO); dup2(suppress ? nullFile : origErr, STDERR_FILENO); } + +void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) +{ + DIR* dir = opendir(folder->chars); + if(dir == NULL) + return; + + uint32_t folderLength = folder->length; + + if(folderName != NULL) + printf("%s/\n", folderName); + + struct dirent* entry; + + while((entry = readdir(dir)) != NULL) + { + if(entry->d_type == DT_DIR) + { + if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + ffStrbufAppendS(folder, entry->d_name); + ffStrbufAppendC(folder, '/'); + listFilesRecursively(folder, (uint8_t) (indentation + 1), entry->d_name); + ffStrbufSubstrBefore(folder, folderLength); + continue; + } + + for(uint8_t i = 0; i < indentation; i++) + fputs(" | ", stdout); + + puts(entry->d_name); + } + + closedir(dir); +} + +void ffListFilesRecursively(const char* path) +{ + FFstrbuf folder; + ffStrbufInitS(&folder, path); + ffStrbufEnsureEndsWithC(&folder, '/'); + listFilesRecursively(&folder, 0, NULL); + ffStrbufDestroy(&folder); +} diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 56d6ccf60..ddd1dfb6f 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -115,3 +115,48 @@ void ffSuppressIO(bool suppress) { FF_UNUSED(suppress); } + +void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) +{ + uint32_t folderLength = folder->length; + + if(folderName != NULL) + printf("%s/\n", folderName); + + ffStrbufAppendC(folder, '*'); + WIN32_FIND_DATAA entry; + HANDLE hFind = FindFirstFileA(folder->chars, &entry); + if(hFind == INVALID_HANDLE_VALUE) + return; + + do + { + if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if(strcmp(entry.cFileName, ".") == 0 || strcmp(entry.cFileName, "..") == 0) + continue; + + ffStrbufSubstrBefore(folder, folderLength); + ffStrbufAppendS(folder, entry.cFileName); + ffStrbufAppendC(folder, '/'); + listFilesRecursively(folder, (uint8_t) (indentation + 1), entry.cFileName); + ffStrbufSubstrBefore(folder, folderLength); + continue; + } + + for(uint8_t i = 0; i < indentation; i++) + fputs(" | ", stdout); + + puts(entry.cFileName); + } while (FindNextFileA(hFind, &entry)); + FindClose(hFind); +} + +void ffListFilesRecursively(const char* path) +{ + FFstrbuf folder; + ffStrbufInitS(&folder, path); + ffStrbufEnsureEndsWithC(&folder, '/'); + listFilesRecursively(&folder, 0, NULL); + ffStrbufDestroy(&folder); +} diff --git a/src/fastfetch.c b/src/fastfetch.c index f62205616..012f5da68 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -12,9 +12,6 @@ #ifdef WIN32 #include "util/windows/getline.h" - #include -#else - #include #endif typedef struct CustomValue @@ -471,83 +468,21 @@ static inline void printCommandHelp(const char* command) fprintf(stderr, "No specific help for command %s provided\n", command); } -static inline void listAvailablePresetsFromFolder(FFstrbuf* folder, uint8_t indentation, const char* folderName) -{ - #ifndef _WIN32 - DIR* dir = opendir(folder->chars); - if(dir == NULL) - return; - - uint32_t folderLength = folder->length; - - if(folderName != NULL) - printf("%s/\n", folderName); - - struct dirent* entry; - - while((entry = readdir(dir)) != NULL) - { - if(entry->d_type == DT_DIR) - { - if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - ffStrbufAppendS(folder, entry->d_name); - ffStrbufAppendC(folder, '/'); - listAvailablePresetsFromFolder(folder, (uint8_t) (indentation + 1), entry->d_name); - ffStrbufSubstrBefore(folder, folderLength); - continue; - } - - for(uint8_t i = 0; i < indentation; i++) - fputs(" | ", stdout); - - puts(entry->d_name); - } - - closedir(dir); - #else - uint32_t folderLength = folder->length; - - if(folderName != NULL) - printf("%s/\n", folderName); - - ffStrbufAppendC(folder, '*'); - WIN32_FIND_DATAA entry; - HANDLE hFind = FindFirstFileA(folder->chars, &entry); - if(hFind == INVALID_HANDLE_VALUE) - return; - - do - { - if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if(strcmp(entry.cFileName, ".") == 0 || strcmp(entry.cFileName, "..") == 0) - continue; - - ffStrbufSubstrBefore(folder, folderLength); - ffStrbufAppendS(folder, entry.cFileName); - ffStrbufAppendC(folder, '/'); - listAvailablePresetsFromFolder(folder, (uint8_t) (indentation + 1), entry.cFileName); - ffStrbufSubstrBefore(folder, folderLength); - continue; - } - - for(uint8_t i = 0; i < indentation; i++) - fputs(" | ", stdout); - - puts(entry.cFileName); - } while (FindNextFileA(hFind, &entry)); - FindClose(hFind); - #endif -} - -static inline void listAvailablePresets(FFinstance* instance) +static void listAvailablePresets(FFinstance* instance) { FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs) { ffStrbufAppendS(path, "fastfetch/presets/"); - listAvailablePresetsFromFolder(path, 0, NULL); + ffListFilesRecursively(path->chars); + } +} + +static void listAvailableLogos(FFinstance* instance) +{ + FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs) + { + ffStrbufAppendS(path, "fastfetch/logos/"); + ffListFilesRecursively(path->chars); } } @@ -972,7 +907,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con } else if(strcasecmp(subkey, "-logos") == 0) { + puts("Builtin logos:"); ffLogoBuiltinList(); + puts("\nCustom logos:"); + listAvailableLogos(instance); exit(0); } else if(strcasecmp(subkey, "-logos-autocompletion") == 0) From 517e3fcff9acd86d7e77617c957a2082731b49ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Jan 2023 10:10:31 +0800 Subject: [PATCH 036/119] WMI: add timeout to prevent CI from hanging Hard coded 5 seconds --- src/util/windows/wmi.cpp | 4 +--- src/util/windows/wmi.hpp | 6 +++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 65e54d422..b8e576fd5 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -111,9 +111,7 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace } // Use the IWbemServices pointer to make requests of WMI - HRESULT hres; - - hres = ((IWbemServices*)context)->ExecQuery( + HRESULT hres = ((IWbemServices*)context)->ExecQuery( bstr_t(L"WQL"), bstr_t(queryStr), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index c4ece40f6..32ce0bcb4 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -18,6 +18,10 @@ enum class FFWmiNamespace { LAST, }; +enum { + FF_WMI_QUERY_TIMEOUT = 5000 +}; + struct FFWmiRecord { IWbemClassObject* obj; @@ -26,7 +30,7 @@ struct FFWmiRecord if(!pEnumerator) return; ULONG ret; - bool ok = SUCCEEDED(pEnumerator->Next((LONG)WBEM_INFINITE, 1, &obj, &ret)) && ret; + bool ok = SUCCEEDED(pEnumerator->Next(FF_WMI_QUERY_TIMEOUT, 1, &obj, &ret)) && ret; if(!ok) obj = nullptr; } FFWmiRecord(const FFWmiRecord&) = delete; From ebe26eddf01f7c435663040a14d7c291f2140261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Jan 2023 10:21:23 +0800 Subject: [PATCH 037/119] Windows: minify included headers --- src/util/windows/registry.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/windows/registry.h b/src/util/windows/registry.h index 22aa6f9ce..e21dfdb66 100644 --- a/src/util/windows/registry.h +++ b/src/util/windows/registry.h @@ -5,8 +5,7 @@ #include "fastfetch.h" -#define WIN32_LEAN_AND_MEAN -#include +#include static inline void wrapRegCloseKey(HKEY* phKey) { From 212e7aa47e9c482d545122d2edfb01e504c6f1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Jan 2023 13:12:50 +0800 Subject: [PATCH 038/119] CI: test for memleaks --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index b93c6e922..ef6d86833 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -26,7 +26,7 @@ jobs: - name: configure project env: CC: ${{ matrix.compiler }} - run: cmake -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBCJSON=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} . + run: cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBCJSON=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} . - name: build project run: cmake --build . From a14ef06d14671165c54f465f7bb8459ff43e6fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Jan 2023 20:30:13 +0800 Subject: [PATCH 039/119] TerminalShell (Windows): fix a rare case that fails to detect terminal --- CHANGELOG.md | 4 + src/detection/terminalshell/terminalshell.h | 2 + .../terminalshell/terminalshell_linux.c | 4 + .../terminalshell/terminalshell_windows.cpp | 93 ++++++++++++++++++- 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4992e1913..5d79318a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Features: * Bluetooth module * Sound module +Bugfixes: + +* Fix a rare case that fails to detect terminal + # 1.9.1 Bugfixes: diff --git a/src/detection/terminalshell/terminalshell.h b/src/detection/terminalshell/terminalshell.h index a2a1f4200..f506381bb 100644 --- a/src/detection/terminalshell/terminalshell.h +++ b/src/detection/terminalshell/terminalshell.h @@ -12,12 +12,14 @@ typedef struct FFTerminalShellResult const char* shellExeName; //pointer to a char in shellExe FFstrbuf shellPrettyName; FFstrbuf shellVersion; + uint32_t shellPid; FFstrbuf terminalProcessName; FFstrbuf terminalExe; FFstrbuf terminalPrettyName; const char* terminalExeName; //pointer to a char in terminalExe FFstrbuf terminalVersion; + uint32_t terminalPid; FFstrbuf userShellExe; const char* userShellExeName; //pointer to a char in userShellExe diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index e6b765ba9..1a2875508 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -162,6 +162,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) ) { if (result->shellProcessName.length == 0) { + result->shellPid = (uint32_t) pid; ffStrbufSetS(&result->shellProcessName, name); getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName); } @@ -170,6 +171,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) return; } + result->terminalPid = (uint32_t) pid; ffStrbufSetS(&result->terminalProcessName, name); getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName); } @@ -336,10 +338,12 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) ffStrbufInitA(&result.shellExe, exePathLen); result.shellExeName = result.shellExe.chars; ffStrbufInit(&result.shellVersion); + result.shellPid = 0; ffStrbufInit(&result.terminalProcessName); ffStrbufInitA(&result.terminalExe, exePathLen); result.terminalExeName = result.terminalExe.chars; + result.terminalPid = 0; ffStrbufInit(&result.userShellExe); result.userShellExeName = result.userShellExe.chars; diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index b800228fa..58dc2c588 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -2,6 +2,7 @@ extern "C" { #include "terminalshell.h" #include "common/processing.h" #include "common/thread.h" +#include "util/mallocHelper.h" } #include @@ -10,6 +11,7 @@ extern "C" { #ifdef FF_USE_WIN_NTAPI +#include #include static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName) @@ -54,6 +56,45 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb return true; } +static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* result, uint32_t ppid) +{ + ULONG size = 0; + if(NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) + return false; + + size += sizeof(SystemProcessInformation) * 5; //What if new processes are created during two syscalls? + + SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PROCESS_INFORMATION*)malloc(size); + if(!pstart) + return false; + + if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, nullptr))) + return false; + + uint32_t currentProcessId = (uint32_t) GetCurrentProcessId(); + + for (auto ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset)) + { + if ((uint32_t)(uintptr_t) ptr->InheritedFromUniqueProcessId != ppid) + continue; + + uint32_t pid = (uint32_t)(uintptr_t) ptr->UniqueProcessId; + if (pid == currentProcessId) + continue; + + if(!getProcessInfo(pid, nullptr, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName)) + return false; + + result->terminalPid = pid; + ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName); + if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe")) + ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4); + + return true; + } + return false; +} + #else #include "util/windows/wmi.hpp" @@ -95,6 +136,33 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb return true; } +static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* result, uint32_t ppid) +{ + wchar_t sql[256] = {}; + swprintf(sql, 256, L"SELECT Name, ExecutablePath, ProcessId FROM Win32_Process WHERE ProcessId <> %" PRIu32 " AND ParentProcessId = %" PRIu32, + (uint32_t) GetCurrentProcessId(), + ppid); + + FFWmiQuery query(sql); + if(!query) + return false; + + if(FFWmiRecord record = query.next()) + { + record.getString(L"Name", &result->terminalProcessName); + record.getString(L"ExecutablePath", &result->terminalExe); + result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\') + 1; + uint64_t pid; + record.getUnsigned(L"ProcessId", &pid); + result->terminalPid = (uint32_t) pid; + ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName); + if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe")) + ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4); + return true; + } + return false; +} + #endif extern "C" bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version); @@ -135,6 +203,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* if(instance->config.shellVersion) fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion); + result->shellPid = pid; if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "pwsh")) ffStrbufSetS(&result->shellPrettyName, "PowerShell"); else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "powershell")) @@ -154,7 +223,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* module.dwSize = sizeof(module); for(BOOL success = Module32FirstW(snapshot, &module); success; success = Module32NextW(snapshot, &module)) { - if(wcsncmp(module.szModule, L"clink_dll_", wcslen(L"clink_dll_")) == 0) + if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0) { ffStrbufAppendS(&result->shellPrettyName, "CMD (with Clink)"); break; @@ -170,6 +239,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "explorer")) { ffStrbufSetS(&result->shellPrettyName, "Windows Explorer"); // Started without shell + // In this case, terminal process will be created by fastfetch itself. return 0; } @@ -205,6 +275,21 @@ static uint32_t getTerminalInfo(const FFinstance* instance, FFTerminalShellResul return getTerminalInfo(instance, result, ppid); } + if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "sihost") || + ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "explorer") + ) { + ffStrbufClear(&result->terminalProcessName); + ffStrbufClear(&result->terminalPrettyName); + ffStrbufClear(&result->terminalExe); + result->terminalExeName = ""; + + // Maybe terminal process is created by shell + if(!getTerminalInfoByEnumeratingChildProcesses(result, result->shellPid)) + return 0; + } + else + result->terminalPid = pid; + if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "WindowsTerminal")) ffStrbufSetS(&result->terminalPrettyName, ffStrbufContainIgnCaseS(&result->terminalExe, ".WindowsTerminalPreview_") ? "Windows Terminal Preview" @@ -288,11 +373,13 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) result.shellExeName = ""; ffStrbufInit(&result.shellPrettyName); ffStrbufInit(&result.shellVersion); + result.shellPid = 0; ffStrbufInit(&result.terminalProcessName); ffStrbufInitA(&result.terminalExe, 128); result.terminalExeName = ""; ffStrbufInit(&result.terminalPrettyName); + result.terminalPid = 0; ffStrbufInit(&result.userShellExe); result.userShellExeName = ""; @@ -303,7 +390,9 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) goto exit; ppid = getShellInfo(instance, &result, ppid); - getTerminalInfo(instance, &result, ppid); + if(ppid) + getTerminalInfo(instance, &result, ppid); + if(result.terminalProcessName.length == 0) getTerminalFromEnv(&result); From 7dc73c61ab100a251609682e03ebf13645ba2a5d Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Mon, 30 Jan 2023 18:46:39 +0100 Subject: [PATCH 040/119] WMDE: avoid the use of magick strings across the project There are probably more, but those are all i found for now. --- src/common/io/io.h | 2 +- src/detection/cursor/cursor_linux.c | 8 ++-- src/detection/displayserver/displayserver.h | 29 +++++++++++ .../displayserver/linux/displayserver_linux.h | 4 -- src/detection/displayserver/linux/wayland.c | 4 +- src/detection/displayserver/linux/wmde.c | 48 ++++++++++--------- src/detection/displayserver/linux/xcb.c | 6 +-- src/detection/displayserver/linux/xlib.c | 6 +-- src/detection/gtk.c | 12 ++--- src/detection/qt.c | 4 +- src/detection/wmtheme/wmtheme_linux.c | 14 +++--- src/modules/font.c | 2 +- src/modules/icons.c | 2 +- src/modules/theme.c | 2 +- 14 files changed, 85 insertions(+), 58 deletions(-) diff --git a/src/common/io/io.h b/src/common/io/io.h index c078b4122..c510c4e14 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -3,7 +3,7 @@ #ifndef FF_INCLUDED_common_io_io #define FF_INCLUDED_common_io_io -#include "fastfetch.h" +#include "util/FFstrbuf.h" #ifdef _WIN32 #include diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c index 63507e803..ab7104dea 100644 --- a/src/detection/cursor/cursor_linux.c +++ b/src/detection/cursor/cursor_linux.c @@ -72,13 +72,13 @@ void ffDetectCursor(const FFinstance* instance, FFCursorResult* result) { const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0) + if(ffStrbufCompS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG) == 0) ffStrbufAppendS(&result->error, "WSLg uses native windows cursor"); - else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) + else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0) ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY"); - else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0) detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result); - else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt")) + else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT)) detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result); else if( !detectCursorGTK(instance, result) && diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 17fef3ba5..271a35085 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -5,6 +5,35 @@ #include "fastfetch.h" +#define FF_DE_PRETTY_PLASMA "KDE Plasma" +#define FF_DE_PRETTY_GNOME "Gnome" +#define FF_DE_PRETTY_XFCE4 "Xfce4" +#define FF_DE_PRETTY_CINNAMON "Cinnamon" +#define FF_DE_PRETTY_MATE "Mate" +#define FF_DE_PRETTY_LXDE "LXDE" +#define FF_DE_PRETTY_LXQT "LXQT" +#define FF_DE_PRETTY_BUDGIE "Budgie" +#define FF_DE_PRETTY_UNITY "Unity" + +#define FF_WM_PRETTY_KWIN "KWin" +#define FF_WM_PRETTY_MUTTER "Mutter" +#define FF_WM_PRETTY_MUFFIN "Muffin" +#define FF_WM_PRETTY_MARCO "Marco" +#define FF_WM_PRETTY_XFWM4 "Xfwm4" +#define FF_WM_PRETTY_OPENBOX "Openbox" +#define FF_WM_PRETTY_I3 "i3" +#define FF_WM_PRETTY_WAYFIRE "Wayfire" +#define FF_WM_PRETTY_SWAY "Sway" +#define FF_WM_PRETTY_BSPWM "bspwm" +#define FF_WM_PRETTY_DWM "dwm" +#define FF_WM_PRETTY_WESTON "Weston" +#define FF_WM_PRETTY_XMONAD "XMonad" +#define FF_WM_PRETTY_WSLG "WSLg" + +#define FF_WM_PROTOCOL_TTY "TTY" +#define FF_WM_PROTOCOL_X11 "X11" +#define FF_WM_PROTOCOL_WAYLAND "Wayland" + typedef struct FFDisplayResult { uint32_t width; diff --git a/src/detection/displayserver/linux/displayserver_linux.h b/src/detection/displayserver/linux/displayserver_linux.h index 9c7588058..aee7c25ff 100644 --- a/src/detection/displayserver/linux/displayserver_linux.h +++ b/src/detection/displayserver/linux/displayserver_linux.h @@ -5,10 +5,6 @@ #include "detection/displayserver/displayserver.h" -#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland" -#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11" -#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY" - void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result); void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result); diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 71dd0b07b..2b6ed5f70 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -156,7 +156,7 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) //We successfully connected to wayland and detected the display. //So we can set set the session type to wayland. //This is used as an indicator that we are running wayland by the x11 backends. - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); return true; } #endif @@ -187,5 +187,5 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul //We are probably running a wayland compositor at this point, //but fastfetch was compiled without the required library, or loading the library failed. - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); } diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 779e296d9..33d03a20a 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -65,31 +65,33 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce strcasecmp(processName, "kwin_x11") == 0 || strcasecmp(processName, "kwin_x11_wrapper") == 0 || strcasecmp(processName, "kwin") == 0 - ) ffStrbufSetS(&result->wmPrettyName, "KWin"); + ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN); else if( strcasecmp(processName, "gnome-shell") == 0 || strcasecmp(processName, "gnome shell") == 0 || strcasecmp(processName, "gnome-session-binary") == 0 || strcasecmp(processName, "Mutter") == 0 - ) ffStrbufSetS(&result->wmPrettyName, "Mutter"); + ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER); else if( strcasecmp(processName, "cinnamon-session") == 0 || strcasecmp(processName, "Muffin") == 0 - ) ffStrbufSetS(&result->wmPrettyName, "Muffin"); + ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN); else if(strcasecmp(processName, "sway") == 0) - ffStrbufSetS(&result->wmPrettyName, "Sway"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_SWAY); else if(strcasecmp(processName, "weston") == 0) - ffStrbufSetS(&result->wmPrettyName, "Weston"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WESTON); else if(strcasecmp(processName, "wayfire") == 0) - ffStrbufSetS(&result->wmPrettyName, "Wayfire"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WAYFIRE); else if(strcasecmp(processName, "openbox") == 0) - ffStrbufSetS(&result->wmPrettyName, "Openbox"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_OPENBOX); else if(strcasecmp(processName, "xfwm4") == 0) - ffStrbufSetS(&result->wmPrettyName, "Xfwm4"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XFWM4); else if(strcasecmp(processName, "Marco") == 0) - ffStrbufSetS(&result->wmPrettyName, "Marco"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MARCO); else if(strcasecmp(processName, "xmonad") == 0) - ffStrbufSetS(&result->wmPrettyName, "XMonad"); + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XMONAD); + else if(strcasecmp(processName, "WSLg") == 0) + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WSLG); else if( // WMs where the pretty name matches the process name strcasecmp(processName, "dwm") == 0 || strcasecmp(processName, "bspwm") == 0 || @@ -119,7 +121,7 @@ static void applyBetterWM(FFDisplayServerResult* result, const char* processName static void getKDE(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "plasmashell"); - ffStrbufSetS(&result->dePrettyName, "KDE Plasma"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_PLASMA); ffParsePropFileData(instance, "xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); if(result->deVersion.length == 0) @@ -135,21 +137,21 @@ static void getKDE(const FFinstance* instance, FFDisplayServerResult* result) static void getGnome(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "gnome-shell"); - ffStrbufSetS(&result->dePrettyName, "GNOME"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME); ffParsePropFileData(instance, "gnome-shell/org.gnome.Extensions", "version :", &result->deVersion); } static void getCinnamon(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "cinnamon"); - ffStrbufSetS(&result->dePrettyName, "Cinnamon"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON); ffParsePropFileData(instance, "applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion); } static void getMate(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "mate-session"); - ffStrbufSetS(&result->dePrettyName, "MATE"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE); FFstrbuf major; ffStrbufInit(&major); @@ -188,7 +190,7 @@ static void getMate(const FFinstance* instance, FFDisplayServerResult* result) static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "xfce4-session"); - ffStrbufSetS(&result->dePrettyName, "Xfce4"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4); ffParsePropFileData(instance, "gtk-doc/html/libxfce4ui/index.html", "

Version", &result->deVersion); if(result->deVersion.length == 0 && instance->config.allowSlowOperations) @@ -209,7 +211,7 @@ static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result) static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "lxqt-session"); - ffStrbufSetS(&result->dePrettyName, "LXQt"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT); ffParsePropFileData(instance, "gconfig/lxqt.pc", "Version:", &result->deVersion); if(result->deVersion.length == 0) @@ -241,8 +243,8 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result) static void getBudgie(const FFinstance* instance, FFDisplayServerResult* result) { - ffStrbufSetS(&result->dePrettyName, "Budgie"); ffStrbufSetS(&result->deProcessName, "budgie-desktop"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE); ffParsePropFileData(instance, "budgie/budgie-version.xml", "", &result->deVersion); } @@ -307,9 +309,9 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) if(ffStrSet(env)) { if(strcasecmp(env, "x11") == 0) - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); else if(strcasecmp(env, "tty") == 0) - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); else ffStrbufSetS(&result->wmProtocolName, env); @@ -319,14 +321,14 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) env = getenv("DISPLAY"); if(ffStrSet(env)) { - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); return; } env = getenv("TERM"); - if(ffStrSet(env)) + if(ffStrSet(env) && strcasecmp(env, "linux") == 0) { - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); return; } } @@ -408,7 +410,7 @@ void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result) //We don't want to detect anything in TTY //This can't happen if a connection succeeded, so we don't need to clear wmProcessName - if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY) == 0) + if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0) return; const char* env = parseEnv(); diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 99a960894..0909d0b76 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -62,7 +62,7 @@ static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection, static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result) { - if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0) + if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0) return; xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK"); @@ -131,7 +131,7 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); } #else @@ -391,7 +391,7 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); } #else diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 12f87587c..e6fb8b930 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -39,7 +39,7 @@ static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Wi static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result) { - if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0) + if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0) return; Window* wmWindow = (Window*) x11GetProperty(data, display, DefaultRootWindow(display), "_NET_SUPPORTING_WM_CHECK"); @@ -94,7 +94,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); } #else @@ -315,7 +315,7 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) - ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); } #else diff --git a/src/detection/gtk.c b/src/detection/gtk.c index 1db344edd..3fb9b8e7c 100644 --- a/src/detection/gtk.c +++ b/src/detection/gtk.c @@ -56,7 +56,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Xfce") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Xfce4") == 0) + if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4) == 0) { themeName = ffSettingsGetXFConf(instance, "xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGetXFConf(instance, "xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue; @@ -64,7 +64,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul cursorTheme = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue; cursorSize = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; } - else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0) + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON) == 0) { themeName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; @@ -72,7 +72,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul cursorTheme = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; cursorSize = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; } - else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_MATE) == 0) { themeName = ffSettingsGet(instance, "/org/mate/interface/gtk-theme", "org.mate.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/mate/interface/icon-theme", "org.mate.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; @@ -81,9 +81,9 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul cursorSize = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; } else if( - ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || - ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 || - ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0 + ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) == 0 || + ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) == 0 || + ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) == 0 ) { themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; diff --git a/src/detection/qt.c b/src/detection/qt.c index 5ac1d943e..649a2a25b 100644 --- a/src/detection/qt.c +++ b/src/detection/qt.c @@ -152,9 +152,9 @@ const FFQtResult* ffDetectQt(const FFinstance* instance) const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) + if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0) detectPlasma(instance, &result); - else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "LXQt") == 0) + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT) == 0) detectLXQt(instance, &result); ffThreadMutexUnlock(&mutex); diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index 6efba12c5..d87757567 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -200,27 +200,27 @@ bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError) return false; } - if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, "KWin") == 0 || ffStrbufIgnCaseCompS(&wm->wmPrettyName, "KDE") == 0 || ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Plasma") == 0) + if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_KWIN) == 0) return detectWMThemeFromConfigFile(instance, "kwinrc", "theme =", "Breeze", themeOrError); - if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Xfwm4") == 0 || ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Xfwm") == 0) + if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_XFWM4) == 0) return detectXFWM4(instance, themeOrError); - if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Mutter") == 0) + if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_MUTTER) == 0) { - if(ffStrbufIgnCaseCompS(&wm->dePrettyName, "Gnome") == 0) + if(ffStrbufIgnCaseCompS(&wm->dePrettyName, FF_DE_PRETTY_GNOME) == 0) return detectMutter(instance, themeOrError); else return detectGTKThemeAsWMTheme(instance, themeOrError); } - if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Muffin") == 0) + if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_MUFFIN) == 0) return detectMuffin(instance, themeOrError); - if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Marco") == 0) + if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_MARCO) == 0) return detectWMThemeFromSettings(instance, "/org/mate/Marco/general/theme", "org.mate.Marco.general", NULL, "theme", themeOrError); - if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, "Openbox") == 0) + if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_OPENBOX) == 0) return detectOpenbox(instance, &wm->dePrettyName, themeOrError); ffStrbufAppendS(themeOrError, "Unknown WM: "); diff --git a/src/modules/font.c b/src/modules/font.c index 0b2e05e16..29d3fac15 100644 --- a/src/modules/font.c +++ b/src/modules/font.c @@ -77,7 +77,7 @@ void ffPrintFont(FFinstance* instance) const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) + if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0) { ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "Font isn't supported in TTY"); return; diff --git a/src/modules/icons.c b/src/modules/icons.c index 4597cf2e8..bb12ecc81 100644 --- a/src/modules/icons.c +++ b/src/modules/icons.c @@ -20,7 +20,7 @@ void ffPrintIcons(FFinstance* instance) const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) + if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0) { ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons aren't supported in TTY"); return; diff --git a/src/modules/theme.c b/src/modules/theme.c index 5c10ee485..1dc7c868a 100644 --- a/src/modules/theme.c +++ b/src/modules/theme.c @@ -20,7 +20,7 @@ void ffPrintTheme(FFinstance* instance) const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) + if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0) { ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, "Theme isn't supported in TTY"); return; From a37115cb0076c5f988b8df5031ce719c800315bc Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Mon, 30 Jan 2023 23:23:14 +0100 Subject: [PATCH 041/119] Fix build on windows --- src/common/io/io_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index ddd1dfb6f..3a28f19be 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -113,7 +113,7 @@ bool ffPathExists(const char* path, FFPathType type) void ffSuppressIO(bool suppress) { - FF_UNUSED(suppress); + (void) suppress; //Not implemented. } void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) From d36e827ec9d0060a2100e57b51a04e0cffb69b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Jan 2023 12:01:16 +0800 Subject: [PATCH 042/119] Fastfetch: remove `--nocache` which has been deprecated for a while --- src/fastfetch.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 012f5da68..78b86708c 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -928,8 +928,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(strcasecmp(key, "-r") == 0 || strcasecmp(key, "--recache") == 0) instance->config.recache = optionParseBoolean(value); - else if(strcasecmp(key, "--nocache") == 0) - fputs("`--nocache` are obsoleted. Caching functions other than image caching are removed.\n\n", stderr); else if(strcasecmp(key, "--load-config") == 0) optionParseConfigFile(instance, data, key, value); else if(strcasecmp(key, "--gen-config") == 0) From 2476b44300abc02f0c843d097b53e62cd3f4a849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 19:42:02 +0800 Subject: [PATCH 043/119] Global: add support for colored percentage numbers output --- src/common/bar.c | 50 ++++++++++++++++++++++++++++++++++++++++ src/common/bar.h | 8 ++++--- src/data/config_user.txt | 2 +- src/data/help.txt | 2 +- src/modules/battery.c | 3 ++- src/modules/cpuUsage.c | 2 +- src/modules/disk.c | 3 ++- src/modules/memory.c | 2 +- 8 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/common/bar.c b/src/common/bar.c index 34b14aa7a..d4a8cf0f1 100644 --- a/src/common/bar.c +++ b/src/common/bar.c @@ -47,3 +47,53 @@ void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, else ffStrbufAppendS(buffer, " ]"); } + +// if (green < yellow) +// [0, green]: print green +// (green, yellow]: print yellow +// (yellow, 100]: print red +// +// if (green > yellow) +// [green, 100]: print green +// [yellow, green): print yellow +// [0, yellow): PRINT RED +void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses) +{ + assert(green <= 100 && yellow <= 100); + + bool colored = !!(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT); + + if (parentheses) + ffStrbufAppendC(buffer, '('); + + if (colored && !instance->config.pipe) + { + if(green < yellow) + { + if (percent <= green) + ffStrbufAppendS(buffer, "\033[32m"); + else if (percent <= yellow) + ffStrbufAppendS(buffer, "\033[93m"); + else + ffStrbufAppendS(buffer, "\033[91m"); + } + else + { + if (percent >= green) + ffStrbufAppendS(buffer, "\033[32m"); + else if (percent >= yellow) + ffStrbufAppendS(buffer, "\033[93m"); + else + ffStrbufAppendS(buffer, "\033[91m"); + } + } + ffStrbufAppendF(buffer, "%u%%", (unsigned) percent); + + if (colored && !instance->config.pipe) + { + ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); + } + + if (parentheses) + ffStrbufAppendC(buffer, ')'); +} diff --git a/src/common/bar.h b/src/common/bar.h index 575adc01d..f28cbe777 100644 --- a/src/common/bar.h +++ b/src/common/bar.h @@ -7,11 +7,13 @@ enum { - FF_PERCENTAGE_TYPE_NUM_BIT = 1, - FF_PERCENTAGE_TYPE_BAR_BIT = 2, - FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 4, + FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0, + FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1, + FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2, + FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3, }; void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red); +void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses); #endif diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 1b9ac9635..e4fcef289 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -262,7 +262,7 @@ # Percentage output type option # Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported. # Only works with default format ( without --module-format option ). -# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar; 6: prints bar and hide other texts +# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar; 6: prints bar and hide other texts; 9: prints colored number #--percent-type 1 # Key options: diff --git a/src/data/help.txt b/src/data/help.txt index c4fd1acd3..37adf2eed 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -130,7 +130,7 @@ Module specific options: --weather-output-format: The output weather format to be used. It must be URI encoded. --player-name: The name of the player to use --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto - --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 + --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1 --command-shell : Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others --command-key : Set the module key to display, can be specified mulitple times --command-text : Set the command text to be executed, can be specified mulitple times diff --git a/src/modules/battery.c b/src/modules/battery.c index 79cdf4c79..6bafb0ee7 100644 --- a/src/modules/battery.c +++ b/src/modules/battery.c @@ -36,7 +36,8 @@ static void printBattery(FFinstance* instance, BatteryResult* result, uint8_t in { if(str.length > 0) ffStrbufAppendC(&str, ' '); - ffStrbufAppendF(&str, str.length > 0 ? "(%u%%)" : "%u%%", (unsigned) result->capacity); + + ffAppendPercentNum(instance, &str, (uint8_t) result->capacity, 51, 21, str.length > 0); } } diff --git a/src/modules/cpuUsage.c b/src/modules/cpuUsage.c index 3e4165b90..f46de6259 100644 --- a/src/modules/cpuUsage.c +++ b/src/modules/cpuUsage.c @@ -29,7 +29,7 @@ void ffPrintCPUUsage(FFinstance* instance) { if(str.length > 0) ffStrbufAppendC(&str, ' '); - ffStrbufAppendF(&str, "%.2lf%%", percentage); + ffAppendPercentNum(instance, &str, (uint8_t) percentage, 50, 80, str.length > 0); } ffStrbufPutTo(&str, stdout); ffStrbufDestroy(&str); diff --git a/src/modules/disk.c b/src/modules/disk.c index c1e074812..d2311f11f 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -53,7 +53,8 @@ static void printDisk(FFinstance* instance, const FFDisk* disk) if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { - ffStrbufAppendF(&str, str.length > 0 ? "(%u%%) " : "%u%% ", bytesPercentage); + ffAppendPercentNum(instance, &str, (uint8_t) bytesPercentage, 50, 80, str.length > 0); + ffStrbufAppendC(&str, ' '); } } else diff --git a/src/modules/memory.c b/src/modules/memory.c index fbb893f02..05d7c33cf 100644 --- a/src/modules/memory.c +++ b/src/modules/memory.c @@ -56,7 +56,7 @@ static void printMemory(FFinstance* instance, const char* name, const FFModuleAr ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) - ffStrbufAppendF(&str, str.length > 0 ? "(%u%%)" : "%u%%", percentage); + ffAppendPercentNum(instance, &str, (uint8_t) percentage, 50, 80, str.length > 0); ffStrbufTrimRight(&str, ' '); ffStrbufPutTo(&str, stdout); From 7132762c9cdb6b247462d014e5edebf1f31e0afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 20:55:01 +0800 Subject: [PATCH 044/119] Sound (Linux): small fixes 1. treat PA_PORT_AVAILABLE_UNKNOWN as active so that the default speaker is active now 2. load `libpulse.so` as suggested in `config_user.txt` --- src/detection/sound/sound_linux.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index 0aa10b753..658fc82c7 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -16,7 +16,7 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo ffStrbufInitS(&device->name, i->description); ffStrbufInitS(&device->manufacturer, i->driver); device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM); - device->active = i->active_port && i->active_port->available == PA_PORT_AVAILABLE_YES; + device->active = i->active_port && i->active_port->available != PA_PORT_AVAILABLE_NO; device->main = false; } @@ -32,7 +32,6 @@ static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *u if(ffStrbufEqualS(&device->identifier, i->default_sink_name)) { device->main = true; - device->active = true; // Treat the default sink as always active break; } } @@ -40,7 +39,7 @@ static void paServerInfoCallback(pa_context *c, const pa_server_info *i, void *u static const char* detectSound(const FFinstance* instance, FFlist* devices) { - FF_LIBRARY_LOAD(pulse, &instance->config.libPulse, "Failed to load libpulse.so.0", "libpulse.so.0", 0) + FF_LIBRARY_LOAD(pulse, &instance->config.libPulse, "Failed to load libpulse" FF_LIBRARY_EXTENSION, "libpulse" FF_LIBRARY_EXTENSION, 0) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_new) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_get_api) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pulse, pa_mainloop_iterate) From 00e044c431e20f62c89e2659645658ab35897e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 21:12:47 +0800 Subject: [PATCH 045/119] Sound: change option `--sound-show-all` to `--sound-type` --- src/common/init.c | 2 +- src/data/help.txt | 2 +- src/fastfetch.c | 11 +++++++++-- src/fastfetch.h | 9 ++++++++- src/modules/sound.c | 8 ++++++-- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index 7eabe0948..0125c4b75 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -164,7 +164,7 @@ static void defaultConfig(FFinstance* instance) instance->config.bluetoothShowDisconnected = false; - instance->config.soundShowAll = false; + instance->config.soundType = FF_SOUND_TYPE_MAIN; ffStrbufInitA(&instance->config.batteryDir, 0); diff --git a/src/data/help.txt b/src/data/help.txt index 37adf2eed..3eeaf662b 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -113,7 +113,7 @@ Module specific options: --disk-show-subvolumes : Set if subvolumes should be printed. Default is false --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false --bluetooth-show-disconnected: : Set if disconnected bluetooth devices should be printed. Default is false - --sound-show-all: : Set if all sound devices should be printed. Default is false + --sound-type: : Set what type of sound devices should be printed. Should be either main, active or all. Default is main --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ --cpu-temp : Detect and display CPU temperature if supported. Default is false --gpu-temp : Detect and display GPU temperature if supported. Default is false diff --git a/src/fastfetch.c b/src/fastfetch.c index 78b86708c..75431699f 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1261,8 +1261,15 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.diskShowUnknown = optionParseBoolean(value); else if(strcasecmp(key, "--bluetooth-show-disconnected") == 0) instance->config.bluetoothShowDisconnected = optionParseBoolean(value); - else if(strcasecmp(key, "--sound-show-all") == 0) - instance->config.soundShowAll = optionParseBoolean(value); + else if(strcasecmp(key, "--sound-type") == 0) + { + optionParseEnum(key, value, &instance->config.soundType, + "main", FF_SOUND_TYPE_MAIN, + "active", FF_SOUND_TYPE_ACTIVE, + "all", FF_SOUND_TYPE_ALL, + NULL + ); + } else if(strcasecmp(key, "--battery-dir") == 0) optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index e1d5be954..0d57902c6 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -34,6 +34,13 @@ typedef enum FFLogoType FF_LOGO_TYPE_NONE, //--logo none } FFLogoType; +typedef enum FFSoundType +{ + FF_SOUND_TYPE_MAIN, + FF_SOUND_TYPE_ACTIVE, + FF_SOUND_TYPE_ALL, +} FFSoundType; + typedef enum FFBinaryPrefixType { FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) @@ -203,7 +210,7 @@ typedef struct FFconfig FFstrbuf weatherOutputFormat; uint32_t weatherTimeout; - bool soundShowAll; + FFSoundType soundType; FFstrbuf osFile; diff --git a/src/modules/sound.c b/src/modules/sound.c index d9ee35d37..1bf02b824 100644 --- a/src/modules/sound.c +++ b/src/modules/sound.c @@ -40,8 +40,12 @@ static void printSound(FFinstance* instance, FFlist* devices) FF_LIST_FOR_EACH(FFSoundDevice, device, *devices) { - if(!device->active && !instance->config.soundShowAll) - continue; + switch (instance->config.soundType) + { + case FF_SOUND_TYPE_MAIN: if (!device->main) continue; break; + case FF_SOUND_TYPE_ACTIVE: if (!device->active) continue; break; + case FF_SOUND_TYPE_ALL: break; + } *(FFSoundDevice**)ffListAdd(&filtered) = device; } From a92e6b6d91b0e504374689f4e9ec120c0a66b09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 22:17:46 +0800 Subject: [PATCH 046/119] Sound (macOS): fix active device detection; fix memleaks; don't use deprecated properties --- src/detection/sound/sound_apple.c | 39 +++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index 305e991bf..b1260db2f 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -9,16 +9,16 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de UInt32 dataSize = sizeof(mainDeviceId); if(AudioObjectGetPropertyData(kAudioObjectSystemObject, &(AudioObjectPropertyAddress){ kAudioHardwarePropertyDefaultOutputDevice, - kAudioDevicePropertyScopeOutput, + kAudioObjectPropertyScopeOutput, kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &mainDeviceId) != kAudioHardwareNoError) return "AudioObjectGetPropertyData(kAudioHardwarePropertyDefaultOutputDevice) failed"; - AudioDeviceID deviceIds[32]; + AudioObjectID deviceIds[32] = {}; dataSize = sizeof(deviceIds); if(AudioObjectGetPropertyData(kAudioObjectSystemObject, &(AudioObjectPropertyAddress){ kAudioHardwarePropertyDevices, - kAudioDevicePropertyScopeOutput, + kAudioObjectPropertyScopeOutput, kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &deviceIds) != kAudioHardwareNoError) return "AudioObjectGetPropertyData(kAudioHardwarePropertyDevices) failed"; @@ -31,27 +31,36 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de dataSize = sizeof(muted); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ kAudioDevicePropertyMute, - kAudioDevicePropertyScopeOutput, - 0 + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError) continue; FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = deviceId == mainDeviceId; - device->active = device->main; + device->active = false; device->volume = 0; ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId); ffStrbufInit(&device->name); ffStrbufInit(&device->manufacturer); + uint32_t active; + dataSize = sizeof(active); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyDeviceIsAlive, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &active) == kAudioHardwareNoError) + device->active = !!active; + if (!muted) { float volume; dataSize = sizeof(volume); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ kAudioDevicePropertyVolumeScalar, - kAudioDevicePropertyScopeOutput, - 0 + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &volume) == kAudioHardwareNoError) device->volume = (uint8_t) (volume * 100 + 0.5); } @@ -60,19 +69,25 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de dataSize = sizeof(name); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ kAudioObjectPropertyName, - kAudioDevicePropertyScopeOutput, - 0 + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &name) == kAudioHardwareNoError) + { ffCfStrGetString(name, &device->name); + CFRelease(name); + } CFStringRef manufacturer; dataSize = sizeof(manufacturer); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ kAudioObjectPropertyManufacturer, - kAudioDevicePropertyScopeOutput, - 0 + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &manufacturer) == kAudioHardwareNoError) + { ffCfStrGetString(manufacturer, &device->manufacturer); + CFRelease(manufacturer); + } } return NULL; From 39f47d65a997b4f087257b75c673eb8d4ed0c77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 22:39:27 +0800 Subject: [PATCH 047/119] Sound: remove manufacturer detection as it's only implemented on macOS --- src/detection/sound/sound.h | 1 - src/detection/sound/sound_apple.c | 13 ------------- src/detection/sound/sound_linux.c | 1 - src/detection/sound/sound_windows.cpp | 3 --- src/fastfetch.c | 1 - src/modules/sound.c | 4 +--- 6 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/detection/sound/sound.h b/src/detection/sound/sound.h index 76c17627c..9a89ab694 100644 --- a/src/detection/sound/sound.h +++ b/src/detection/sound/sound.h @@ -9,7 +9,6 @@ typedef struct FFSoundDevice { FFstrbuf identifier; FFstrbuf name; - FFstrbuf manufacturer; uint8_t volume; // 0-100% bool main; bool active; diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index b1260db2f..a9ec04703 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -42,7 +42,6 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de device->volume = 0; ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId); ffStrbufInit(&device->name); - ffStrbufInit(&device->manufacturer); uint32_t active; dataSize = sizeof(active); @@ -76,18 +75,6 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de ffCfStrGetString(name, &device->name); CFRelease(name); } - - CFStringRef manufacturer; - dataSize = sizeof(manufacturer); - if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ - kAudioObjectPropertyManufacturer, - kAudioObjectPropertyScopeOutput, - kAudioObjectPropertyElementMain - }, 0, NULL, &dataSize, &manufacturer) == kAudioHardwareNoError) - { - ffCfStrGetString(manufacturer, &device->manufacturer); - CFRelease(manufacturer); - } } return NULL; diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index 658fc82c7..a752a6b5f 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -14,7 +14,6 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo FFSoundDevice* device = ffListAdd(userdata); ffStrbufInitS(&device->identifier, i->name); ffStrbufInitS(&device->name, i->description); - ffStrbufInitS(&device->manufacturer, i->driver); device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM); device->active = i->active_port && i->active_port->available != PA_PORT_AVAILABLE_NO; device->main = false; diff --git a/src/detection/sound/sound_windows.cpp b/src/detection/sound/sound_windows.cpp index 2b9e95be1..5221c8368 100644 --- a/src/detection/sound/sound_windows.cpp +++ b/src/detection/sound/sound_windows.cpp @@ -65,7 +65,6 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U device->volume = 0; ffStrbufInit(&device->identifier); ffStrbufInit(&device->name); - ffStrbufInit(&device->manufacturer); ffStrbufSetWS(&device->identifier, immDeviceId); @@ -74,8 +73,6 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U PropVariantInit(&friendlyName); if (SUCCEEDED(immPropStore->GetValue(PKEY_Device_FriendlyName, &friendlyName))) ffStrbufSetWS(&device->name, friendlyName.pwszVal); - if (SUCCEEDED(immPropStore->GetValue(PKEY_DeviceInterface_FriendlyName, &friendlyName))) - ffStrbufSetWS(&device->manufacturer, friendlyName.pwszVal); } IAudioEndpointVolume* FF_AUTO_RELEASE_COM_OBJECT immEndpointVolume; diff --git a/src/fastfetch.c b/src/fastfetch.c index 75431699f..ded937466 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -460,7 +460,6 @@ static inline void printCommandHelp(const char* command) "Main", "Name", "Volume", - "Manufacturer", "Identifier" ); } diff --git a/src/modules/sound.c b/src/modules/sound.c index 1bf02b824..4ef58cdc2 100644 --- a/src/modules/sound.c +++ b/src/modules/sound.c @@ -2,7 +2,7 @@ #include "detection/sound/sound.h" #define FF_SOUND_MODULE_NAME "Sound" -#define FF_SOUND_NUM_FORMAT_ARGS 5 +#define FF_SOUND_NUM_FORMAT_ARGS 4 static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8_t index) { @@ -27,7 +27,6 @@ static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8 {FF_FORMAT_ARG_TYPE_BOOL, &device->main}, {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, {FF_FORMAT_ARG_TYPE_UINT8, &device->volume}, - {FF_FORMAT_ARG_TYPE_STRBUF, &device->manufacturer}, {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier} }); } @@ -79,6 +78,5 @@ void ffPrintSound(FFinstance* instance) { ffStrbufDestroy(&device->identifier); ffStrbufDestroy(&device->name); - ffStrbufDestroy(&device->manufacturer); } } From 4f3b9776ae8a64715927fe7f59d02f6201395a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 23:26:50 +0800 Subject: [PATCH 048/119] WmTheme (Windows): align output format to winfetch Ref: https://github.com/lptstr/winfetch/commit/0358deea5e3ca03086be4984b905a0a534f8d1a5 --- src/detection/wmtheme/wmtheme_windows.c | 69 ++++++++++++------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/src/detection/wmtheme/wmtheme_windows.c b/src/detection/wmtheme/wmtheme_windows.c index cf070be69..0522b933b 100644 --- a/src/detection/wmtheme/wmtheme_windows.c +++ b/src/detection/wmtheme/wmtheme_windows.c @@ -60,64 +60,59 @@ const char* colorHexToString(DWORD hex) } } -bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError) +bool ffDetectWmTheme(FF_MAYBE_UNUSED FFinstance* instance, FFstrbuf* themeOrError) { - FF_UNUSED(instance); + { + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes", &hKey, NULL)) + { + FF_STRBUF_AUTO_DESTROY theme; + ffStrbufInit(&theme); + if(ffRegReadStrbuf(hKey, L"CurrentTheme", &theme, NULL)) + { + ffStrbufSubstrBeforeLastC(&theme, '.'); + ffStrbufSubstrAfterLastC(&theme, '\\'); + if(isalpha(theme.chars[0])) + theme.chars[0] = (char)toupper(theme.chars[0]); + + ffStrbufAppendF(themeOrError, "%s", theme.chars); + } + } + } do { uint32_t rgbColor; uint32_t bgrColor; DWORD bufSize = sizeof(bgrColor); if(RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", L"AccentColor", RRF_RT_REG_DWORD, NULL, &bgrColor, &bufSize) == ERROR_SUCCESS) - { - ffStrbufAppendS(themeOrError, "Accent Color - "); rgbColor = ((bgrColor & 0xFF) << 16) | (bgrColor & 0xFF00) | ((bgrColor >> 16) & 0xFF); - - } else if(RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", L"ColorizationColor", RRF_RT_REG_DWORD, NULL, &rgbColor, &bufSize) == ERROR_SUCCESS) - { - ffStrbufAppendS(themeOrError, "Colorization Color - "); rgbColor &= 0xFFFFFF; - } else break; + if(themeOrError->length > 0) ffStrbufAppendS(themeOrError, " - "); const char* text = colorHexToString(rgbColor); if(text) ffStrbufAppendS(themeOrError, text); else ffStrbufAppendF(themeOrError, "#%06lX", (long)rgbColor); - } while(false); + } while (false); - FF_HKEY_AUTO_DESTROY hKey = NULL; - if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hKey, NULL)) { - uint32_t value = 1; - if(ffRegReadUint(hKey, L"SystemUsesLightTheme", &value, NULL)) + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hKey, NULL)) { - if(themeOrError->length > 0) ffStrbufAppendS(themeOrError, ", "); - ffStrbufAppendF(themeOrError, "System - %s", value ? "Light" : "Dark"); - } - - if(ffRegReadUint(hKey, L"AppsUseLightTheme", &value, NULL)) - { - if(themeOrError->length > 0) ffStrbufAppendS(themeOrError, ", "); - ffStrbufAppendF(themeOrError, "Apps - %s", value ? "Light" : "Dark"); - } - } - else if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes", &hKey, NULL)) - { - FF_STRBUF_AUTO_DESTROY theme; - ffStrbufInit(&theme); - if(ffRegReadStrbuf(hKey, L"CurrentTheme", &theme, NULL)) - { - ffStrbufSubstrBeforeLastC(&theme, '.'); - ffStrbufSubstrAfterLastC(&theme, '\\'); - if(isalpha(theme.chars[0])) - theme.chars[0] = (char)toupper(theme.chars[0]); - - if(themeOrError->length > 0) ffStrbufAppendS(themeOrError, ", "); - ffStrbufAppendF(themeOrError, "Theme - %s", theme.chars); + uint32_t system = 1, apps = 1; + if (ffRegReadUint(hKey, L"SystemUsesLightTheme", &system, NULL) && ffRegReadUint(hKey, L"AppsUseLightTheme", &apps, NULL)) + { + bool paren = themeOrError->length > 0; + if (paren) + ffStrbufAppendS(themeOrError, " ("); + ffStrbufAppendF(themeOrError, "System: %s, Apps: %s", system ? "Light" : "Dark", apps ? "Light" : "Dark"); + if (paren) + ffStrbufAppendC(themeOrError, ')'); + } } } From f53a1f785db88932a1e2bd567922fe79060346dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 31 Jan 2023 23:32:49 +0800 Subject: [PATCH 049/119] Doc: update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d79318a8..0c7af9af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,16 @@ Features: * Bluetooth module * Sound module +* Support colored percentage numbers output Bugfixes: * Fix a rare case that fails to detect terminal +Other: + +* Simplified wmtheme output format (Windows) + # 1.9.1 Bugfixes: From df84721b5587fcd678ed59073dcdb5e1a44a1a10 Mon Sep 17 00:00:00 2001 From: CSoellinger Date: Wed, 1 Feb 2023 10:01:47 +0100 Subject: [PATCH 050/119] fix: add another mutter detection for linux mint 21.1 (cinnamon) --- src/detection/displayserver/linux/wmde.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 33d03a20a..aaad2b938 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -70,7 +70,8 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce strcasecmp(processName, "gnome-shell") == 0 || strcasecmp(processName, "gnome shell") == 0 || strcasecmp(processName, "gnome-session-binary") == 0 || - strcasecmp(processName, "Mutter") == 0 + strcasecmp(processName, "Mutter") == 0 || + strcasecmp(processName, "Mutter (Muffin)") == 0 ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER); else if( strcasecmp(processName, "cinnamon-session") == 0 || From 7a2826358ba350d090c5f64f7510d9c408fd33c5 Mon Sep 17 00:00:00 2001 From: CSoellinger Date: Wed, 1 Feb 2023 10:08:08 +0100 Subject: [PATCH 051/119] fix: spell correction --- src/detection/terminalfont/terminalfont.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 1d3503da2..d4c1359ad 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -385,7 +385,7 @@ const FFTerminalFontResult* ffDetectTerminalFont(const FFinstance* instance) const FFTerminalShellResult* terminalShell = ffDetectTerminalShell(instance); if(terminalShell->terminalProcessName.length == 0) - ffStrbufAppendS(&result.error, "Terminal font needs successfull terminal detection"); + ffStrbufAppendS(&result.error, "Terminal font needs successful terminal detection"); else if(!detectTerminalFontCommon(instance, terminalShell, &result)) ffDetectTerminalFontPlatform(instance, terminalShell, &result); From 7ee4a648d00fdb5a256e3e15cef99158c57fa1e3 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 1 Feb 2023 10:43:24 +0100 Subject: [PATCH 052/119] Small fix to muffin theme detection --- src/detection/wmtheme/wmtheme_linux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index d87757567..87a8437c1 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -104,11 +104,13 @@ static bool detectMuffin(FFinstance* instance, FFstrbuf* themeOrError) ffStrbufAppendS(themeOrError, theme); return true; } + if(theme == NULL) { - ffStrbufAppendS(themeOrError, theme); + ffStrbufAppendS(themeOrError, name); return true; } + ffStrbufAppendF(themeOrError, "%s (%s)", name, theme); return true; } From 55da030e2a5fcbb6eb55652b9a3bb90b77f1ae9c Mon Sep 17 00:00:00 2001 From: CSoellinger Date: Wed, 1 Feb 2023 10:50:31 +0100 Subject: [PATCH 053/119] fix: move mutter(muffin) detection to get FF_WM_PRETTY_MUFFIN back --- src/detection/displayserver/linux/wmde.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index aaad2b938..71b1d1474 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -70,12 +70,12 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce strcasecmp(processName, "gnome-shell") == 0 || strcasecmp(processName, "gnome shell") == 0 || strcasecmp(processName, "gnome-session-binary") == 0 || - strcasecmp(processName, "Mutter") == 0 || - strcasecmp(processName, "Mutter (Muffin)") == 0 + strcasecmp(processName, "Mutter") == 0 ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER); else if( strcasecmp(processName, "cinnamon-session") == 0 || - strcasecmp(processName, "Muffin") == 0 + strcasecmp(processName, "Muffin") == 0 || + strcasecmp(processName, "Mutter (Muffin)") == 0 ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN); else if(strcasecmp(processName, "sway") == 0) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_SWAY); From 1b23c9a030f15f921c5ff54f8622204a18248dfe Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 1 Feb 2023 11:14:54 +0100 Subject: [PATCH 054/119] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c7af9af4..98e1839c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Features: Bugfixes: * Fix a rare case that fails to detect terminal +* Fix Muffin detection (@Zerogiven, #412) Other: From 619ec921ee2dba595c308464cb3458f61d395f67 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 1 Feb 2023 11:16:01 +0100 Subject: [PATCH 055/119] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98e1839c3..e6cc76664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ Features: Bugfixes: * Fix a rare case that fails to detect terminal -* Fix Muffin detection (@Zerogiven, #412) +* Fix Muffin detection (@Zerogiven, #411) Other: From a74cbc5781f36e1bcf4aa95391190b7e13f008ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Feb 2023 13:59:21 +0800 Subject: [PATCH 056/119] Sound: fix memleak, update config file --- src/common/init.c | 1 + src/data/config_user.txt | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index 0125c4b75..42734a1a3 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -385,6 +385,7 @@ static void destroyConfig(FFinstance* instance) destroyModuleArg(&instance->config.openCL); destroyModuleArg(&instance->config.users); destroyModuleArg(&instance->config.bluetooth); + destroyModuleArg(&instance->config.sound); ffStrbufDestroy(&instance->config.libPCI); ffStrbufDestroy(&instance->config.libVulkan); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index e4fcef289..3938e0783 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -255,9 +255,9 @@ # Sound show all option # Sets if all sound devices should be printed -# Must be either true or false -# Default is false ( only main device should be printed ). -#--sound-show-all false +# Must be either main, active or all. Default is main +# Default is main. +#--sound-type main # Percentage output type option # Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported. From 7fc2c4dcf1e5afd3ae9dc891f1b4778ded3a6af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Feb 2023 14:01:39 +0800 Subject: [PATCH 057/119] Gamepad: init support for Windows --- CMakeLists.txt | 7 ++++ presets/all | 2 +- src/common/init.c | 2 + src/data/config_user.txt | 3 ++ src/detection/gamepad/gamepad.h | 16 ++++++++ src/detection/gamepad/gamepad_nosupport.c | 6 +++ src/detection/gamepad/gamepad_windows.cpp | 32 +++++++++++++++ src/fastfetch.c | 10 +++++ src/fastfetch.h | 2 + src/modules/gamepad.c | 48 +++++++++++++++++++++++ 10 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/detection/gamepad/gamepad.h create mode 100644 src/detection/gamepad/gamepad_nosupport.c create mode 100644 src/detection/gamepad/gamepad_windows.cpp create mode 100644 src/modules/gamepad.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a2e5c3957..3a97a77fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -274,6 +274,7 @@ set(LIBFASTFETCH_SRC src/modules/gpu.c src/modules/host.c src/modules/icons.c + src/modules/gamepad.c src/modules/kernel.c src/modules/locale.c src/modules/localip.c @@ -335,6 +336,7 @@ if(LINUX) src/detection/gtk.c src/detection/host/host_linux.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c src/detection/opengl/opengl_linux.c @@ -374,6 +376,7 @@ elseif(ANDROID) src/detection/gpu/gpu_nosupport.c src/detection/host/host_android.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_nosupport.c src/detection/memory/memory_linux.c src/detection/opengl/opengl_linux.c @@ -419,6 +422,7 @@ elseif(BSD) src/detection/gtk.c src/detection/host/host_bsd.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c src/detection/opengl/opengl_linux.c @@ -460,6 +464,7 @@ elseif(APPLE) src/detection/gpu/gpu_apple.c src/detection/host/host_apple.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c src/detection/opengl/opengl_apple.c @@ -500,6 +505,7 @@ elseif(WIN32) src/detection/gpu/gpu_windows.cpp src/detection/host/host_windows.c src/detection/localip/localip_windows.c + src/detection/gamepad/gamepad_windows.cpp src/detection/media/media_nosupport.c src/detection/memory/memory_windows.c src/detection/opengl/opengl_windows.c @@ -712,6 +718,7 @@ elseif(WIN32) PRIVATE "version" PRIVATE "setupapi" PRIVATE "dxgi" + PRIVATE "dinput8" PRIVATE "wtsapi32" PRIVATE "powrprof" ) diff --git a/presets/all b/presets/all index dfcaccc44..e8b10e197 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors diff --git a/src/common/init.c b/src/common/init.c index 42734a1a3..592ba17df 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -117,6 +117,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.users); initModuleArg(&instance->config.bluetooth); initModuleArg(&instance->config.sound); + initModuleArg(&instance->config.gamepad); ffStrbufInitA(&instance->config.libPCI, 0); ffStrbufInitA(&instance->config.libVulkan, 0); @@ -386,6 +387,7 @@ static void destroyConfig(FFinstance* instance) destroyModuleArg(&instance->config.users); destroyModuleArg(&instance->config.bluetooth); destroyModuleArg(&instance->config.sound); + destroyModuleArg(&instance->config.gamepad); ffStrbufDestroy(&instance->config.libPCI); ffStrbufDestroy(&instance->config.libVulkan); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 3938e0783..62aef8ad1 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -309,6 +309,7 @@ #--users-key Users #--bluetooth-key Bluetooth #--sound-key Sound +#--gamepad-key Gamepad # Format options: # Sets the format string for module values. @@ -355,6 +356,7 @@ #--users-format #--bluetooth-format #--sound-format +#--gamepad-format # Error options: # Sets the format string to use if an error occured @@ -401,6 +403,7 @@ #--users-error #--bluetooth-error #--sound-error +#--gamepad-error # Library options: # Sets an user specific path to a library to load. diff --git a/src/detection/gamepad/gamepad.h b/src/detection/gamepad/gamepad.h new file mode 100644 index 000000000..1def1b430 --- /dev/null +++ b/src/detection/gamepad/gamepad.h @@ -0,0 +1,16 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_gamepad_gamepad +#define FF_INCLUDED_detection_gamepad_gamepad + +#include "fastfetch.h" + +typedef struct FFGamepadDevice +{ + FFstrbuf identifier; + FFstrbuf name; +} FFGamepadDevice; + +const char* ffDetectGamepad(const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */); + +#endif diff --git a/src/detection/gamepad/gamepad_nosupport.c b/src/detection/gamepad/gamepad_nosupport.c new file mode 100644 index 000000000..d921d3552 --- /dev/null +++ b/src/detection/gamepad/gamepad_nosupport.c @@ -0,0 +1,6 @@ +#include "gamepad.h" + +const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFGamepadDevice */) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/gamepad/gamepad_windows.cpp b/src/detection/gamepad/gamepad_windows.cpp new file mode 100644 index 000000000..c30ef9fe4 --- /dev/null +++ b/src/detection/gamepad/gamepad_windows.cpp @@ -0,0 +1,32 @@ +extern "C" { + #include "gamepad.h" +} + +#include +#define DIRECTINPUT_VERSION 0x0800 +#include + +CALLBACK BOOL DIEnumDevicesCallback(LPCDIDEVICEINSTANCEA lpddi, LPVOID pvRef) +{ + FFlist* devices = (FFlist*) pvRef; + + FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices); + ffStrbufInitF(&device->identifier, "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", + lpddi->guidInstance.Data1, lpddi->guidInstance.Data2, lpddi->guidInstance.Data3, + lpddi->guidInstance.Data4[0], lpddi->guidInstance.Data4[1], lpddi->guidInstance.Data4[2], lpddi->guidInstance.Data4[3], + lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]); + ffStrbufInitS(&device->name, lpddi->tszInstanceName); + + return DIENUM_CONTINUE; +} + +extern "C" +const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */) +{ + IDirectInput8A* dinput; + if (!SUCCEEDED(DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8A, (void**)&dinput, NULL))) + return "DirectInput8Create() failed"; + dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, devices, DIEDFL_ALLDEVICES); + dinput->Release(); + return NULL; +} diff --git a/src/fastfetch.c b/src/fastfetch.c index ded937466..fb6d0fc27 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -463,6 +463,13 @@ static inline void printCommandHelp(const char* command) "Identifier" ); } + else if(strcasecmp(command, "gamepad-format") == 0) + { + constructAndPrintCommandHelpFormat("gamepad", "{1}", 1, + "Name", + "Identifier" + ); + } else fprintf(stderr, "No specific help for command %s provided\n", command); } @@ -1166,6 +1173,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "users", &instance->config.users)) {} else if(optionParseModuleArgs(key, value, "bluetooth", &instance->config.bluetooth)) {} else if(optionParseModuleArgs(key, value, "sound", &instance->config.sound)) {} + else if(optionParseModuleArgs(key, value, "gamepad", &instance->config.gamepad)) {} /////////////////// //Library options// @@ -1478,6 +1486,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintBluetooth(instance); else if(strcasecmp(line, "sound") == 0) ffPrintSound(instance); + else if(strcasecmp(line, "gamepad") == 0) + ffPrintGamepad(instance); else ffPrintErrorString(instance, line, 0, NULL, NULL, ""); } diff --git a/src/fastfetch.h b/src/fastfetch.h index 0d57902c6..b625611b1 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -148,6 +148,7 @@ typedef struct FFconfig FFModuleArgs users; FFModuleArgs bluetooth; FFModuleArgs sound; + FFModuleArgs gamepad; FFstrbuf libPCI; FFstrbuf libVulkan; @@ -326,5 +327,6 @@ void ffPrintUsers(FFinstance* instance); void ffPrintCommand(FFinstance* instance); void ffPrintBluetooth(FFinstance* instance); void ffPrintSound(FFinstance* instance); +void ffPrintGamepad(FFinstance* instance); #endif diff --git a/src/modules/gamepad.c b/src/modules/gamepad.c new file mode 100644 index 000000000..7b935a972 --- /dev/null +++ b/src/modules/gamepad.c @@ -0,0 +1,48 @@ +#include "common/printing.h" +#include "detection/gamepad/gamepad.h" + +#define FF_GAMEPAD_MODULE_NAME "Gamepad" +#define FF_GAMEPAD_NUM_FORMAT_ARGS 2 + +static void printDevice(FFinstance* instance, const FFGamepadDevice* device, uint8_t index) +{ + if(instance->config.sound.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.sound.key); + ffStrbufPutTo(&device->name, stdout); + } + else + { + ffPrintFormat(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.sound, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier}, + }); + } +} + +void ffPrintGamepad(FFinstance* instance) +{ + FF_LIST_AUTO_DESTROY result; + ffListInit(&result, sizeof(FFGamepadDevice)); + const char* error = ffDetectGamepad(instance, &result); + + if(error) + { + ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.sound, "%s", error); + return; + } + + if(!result.length) + { + ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.sound, "No devices detected"); + return; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFGamepadDevice, device, result) + { + printDevice(instance, device, result.length > 1 ? ++index : 0); + ffStrbufDestroy(&device->identifier); + ffStrbufDestroy(&device->name); + } +} From 0b8e8ad4f2067313d677d3c05b65b404670a8838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Feb 2023 20:23:46 +0800 Subject: [PATCH 058/119] Gamepad (macOS): add support --- CMakeLists.txt | 2 +- src/detection/gamepad/gamepad_apple.c | 41 +++++++++++++++++++++++++++ src/util/apple/cf_helpers.h | 13 +++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/detection/gamepad/gamepad_apple.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a97a77fe..27853f760 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,7 +464,7 @@ elseif(APPLE) src/detection/gpu/gpu_apple.c src/detection/host/host_apple.c src/detection/localip/localip_linux.c - src/detection/gamepad/gamepad_nosupport.c + src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c src/detection/opengl/opengl_apple.c diff --git a/src/detection/gamepad/gamepad_apple.c b/src/detection/gamepad/gamepad_apple.c new file mode 100644 index 000000000..154f1c587 --- /dev/null +++ b/src/detection/gamepad/gamepad_apple.c @@ -0,0 +1,41 @@ +#include "gamepad.h" +#include "util/apple/cf_helpers.h" + +#include +#include + +static void enumSet(const void* value, void *context) +{ + CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey)); + CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey)); + FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context); + ffStrbufInit(&device->identifier); + ffCfStrGetString(serialNumber, &device->identifier); + ffStrbufInit(&device->name); + ffCfStrGetString(product, &device->name); +} + +const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */) +{ + IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) + return "IOHIDManagerOpen() failed"; + + CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop); + CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad); + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey) + }, (const void **)(CFNumberRef[]){ + genericDesktop, + gamePad + }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + IOHIDManagerSetDeviceMatching(manager, matching); + + CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager); + if (set) + CFSetApplyFunction(set, &enumSet, devices); + IOHIDManagerClose(manager, 0); + + return NULL; +} diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index d3cb66d43..52755bb8b 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -13,4 +13,17 @@ const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result) const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result); const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result); +static inline CFNumberRef ffCfCreateInt(int value) +{ + return CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); +} + +static inline void cfReleaseWrapper(void* type) +{ + if (*(CFTypeRef*) type) + CFRelease(*(CFTypeRef*) type); +} + +#define FF_CFTYPE_AUTO_RELEASE __attribute__((__cleanup__(cfReleaseWrapper))) + #endif From b49b583e640f818e190b61b7c968cca7232ff6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Feb 2023 21:28:42 +0800 Subject: [PATCH 059/119] Gamepad (Linux): add support --- CMakeLists.txt | 2 +- src/detection/gamepad/gamepad_linux.c | 42 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/detection/gamepad/gamepad_linux.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 27853f760..40b013dde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -336,7 +336,7 @@ if(LINUX) src/detection/gtk.c src/detection/host/host_linux.c src/detection/localip/localip_linux.c - src/detection/gamepad/gamepad_nosupport.c + src/detection/gamepad/gamepad_linux.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c src/detection/opengl/opengl_linux.c diff --git a/src/detection/gamepad/gamepad_linux.c b/src/detection/gamepad/gamepad_linux.c new file mode 100644 index 000000000..ce61a5711 --- /dev/null +++ b/src/detection/gamepad/gamepad_linux.c @@ -0,0 +1,42 @@ +#include "gamepad.h" +#include "common/io/io.h" + +#include +#include + +const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */) +{ + DIR* dirp = opendir("/sys/class/input/"); + if(dirp == NULL) + return "opendir(\"/sys/class/input/\") == NULL"; + + FF_STRBUF_AUTO_DESTROY path; + ffStrbufInitS(&path, "/sys/class/input/"); + uint32_t baseLen = path.length; + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(strncmp(entry->d_name, "js", 2) != 0) + continue; + if(!isdigit(entry->d_name[2])) + continue; + + ffStrbufAppendS(&path, entry->d_name); + ffStrbufAppendS(&path, "/device/name"); + + if (ffPathExists(path.chars, FF_PATHTYPE_FILE)) + { + FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices); + ffStrbufInitS(&device->identifier, entry->d_name); + ffStrbufInit(&device->name); + ffAppendFileBuffer(path.chars, &device->name); + } + + ffStrbufSubstrBefore(&path, baseLen); + } + + closedir(dirp); + + return NULL; +} From 79c9c19b1acc81605ba63813677d35ade238910f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Feb 2023 21:47:35 +0800 Subject: [PATCH 060/119] Doc: document gamepad module support --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6cc76664..674e5b3f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Features: * Bluetooth module * Sound module +* Gamepad module * Support colored percentage numbers output Bugfixes: diff --git a/README.md b/README.md index 34ba5e726..192c498c3 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme ``` ##### Builtin logos From dc5da3c3b33c17d7b05746de489ba71e544e2fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Feb 2023 21:54:45 +0800 Subject: [PATCH 061/119] Flashfetch: add missing modules --- src/flashfetch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/flashfetch.c b/src/flashfetch.c index 0c24732e3..8737c8fcf 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -63,6 +63,9 @@ int main(int argc, char** argv) //ffPrintOpenCL(&instance); //ffPrintUsers(&instance); //ffPrintWeather(&instance); + //ffPrintBluetooth(&instance); + //ffPrintSound(&instance); + //ffPrintGamepad(&instance); ffPrintBreak(&instance); ffPrintColors(&instance); From a063cd4feb0f3a67a569332cc7b0969920340afc Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 1 Feb 2023 15:56:25 +0100 Subject: [PATCH 062/119] Correctly handle zfs pools #413 --- CMakeLists.txt | 1 + src/common/dbus.c | 1 + src/common/format.c | 1 + src/detection/cursor/cursor_linux.c | 1 + src/detection/disk/disk_linux.c | 12 ++++++++ src/detection/displayserver/linux/wmde.c | 1 + src/detection/displayserver/linux/xlib.c | 1 + src/detection/gpu/gpu_linux.c | 1 + src/detection/os/os_linux.c | 1 + .../terminalfont/terminalfont_linux.c | 1 + .../terminalshell/terminalshell_linux.c | 4 +-- src/detection/vulkan.c | 1 + src/detection/wmtheme/wmtheme.h | 2 ++ src/detection/wmtheme/wmtheme_linux.c | 4 +-- src/fastfetch.c | 3 +- src/modules/opencl.c | 1 + src/util/FFstrbuf.c | 11 ------- src/util/FFstrbuf.h | 2 -- src/util/platform/FFPlatform.c | 1 + src/util/platform/FFPlatform_unix.c | 2 +- src/util/stringUtils.c | 29 +++++++++++++++++++ src/util/stringUtils.h | 12 ++++++++ 22 files changed, 74 insertions(+), 19 deletions(-) create mode 100644 src/util/stringUtils.c create mode 100644 src/util/stringUtils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a2e5c3957..fcff26c2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -307,6 +307,7 @@ set(LIBFASTFETCH_SRC src/util/FFstrbuf.c src/util/FFvaluestore.c src/util/platform/FFPlatform.c + src/util/stringUtils.c ) if(LINUX) diff --git a/src/common/dbus.c b/src/common/dbus.c index 1d2840b2f..f974b39d9 100644 --- a/src/common/dbus.c +++ b/src/common/dbus.c @@ -3,6 +3,7 @@ #ifdef FF_HAVE_DBUS #include "common/thread.h" +#include "util/stringUtils.h" static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib) { diff --git a/src/common/format.c b/src/common/format.c index 1a4a688c5..7394822f8 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -2,6 +2,7 @@ #include "common/format.h" #include "common/parsing.h" #include "util/textModifier.h" +#include "util/stringUtils.h" #include diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c index ab7104dea..88366c935 100644 --- a/src/detection/cursor/cursor_linux.c +++ b/src/detection/cursor/cursor_linux.c @@ -5,6 +5,7 @@ #include "common/settings.h" #include "detection/gtk.h" #include "detection/displayserver/displayserver.h" +#include "util/stringUtils.h" #include diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index ec7a26abf..c15eea812 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -1,5 +1,7 @@ #include "disk.h" +#include "util/stringUtils.h" + #include #include #include @@ -19,6 +21,10 @@ static bool isPhysicalDevice(const char* device) if(strcmp(device, "drvfs") == 0) return true; + //ZFS root pool. The format is rpool/// + if(strncmp(device, "rpool/", 6) == 0) + return true; + //Pseudo filesystems don't have a device in /dev const char* devPrefix = "/dev/"; if(strncmp(device, devPrefix, strlen(devPrefix)) != 0) @@ -141,6 +147,7 @@ static bool isSubvolume(const FFlist* devices) { const FFstrbuf* currentDevie = ffListGet(devices, devices->length - 1); + //Filter all disks which device was already found. This catches BTRFS subvolumes. for(uint32_t i = 0; i < devices->length - 1; i++) { const FFstrbuf* otherDevice = ffListGet(devices, i); @@ -149,6 +156,11 @@ static bool isSubvolume(const FFlist* devices) return true; } + //ZFS subvolumes: rpool///. + //Test if the third slash is present. + if(strncmp(currentDevie->chars, "rpool/", 6) == 0 && ffStrHasNChars(currentDevie->chars, '/', 3)) + return true; + return false; } diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 71b1d1474..3c40b2e11 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -3,6 +3,7 @@ #include "common/properties.h" #include "common/parsing.h" #include "common/processing.h" +#include "util/stringUtils.h" #include #include diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index e6fb8b930..a804dd29a 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -3,6 +3,7 @@ #ifdef FF_HAVE_X11 #include "common/library.h" #include "common/parsing.h" +#include "util/stringUtils.h" #include typedef struct X11PropertyData diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index d34807df9..549d8ed40 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -6,6 +6,7 @@ #include "common/properties.h" #include "common/parsing.h" #include "detection/temps/temps_linux.h" +#include "util/stringUtils.h" #include #include #include diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 45a0f5cec..063e8455b 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -1,6 +1,7 @@ #include "os.h" #include "common/properties.h" #include "common/parsing.h" +#include "util/stringUtils.h" #include #include diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 1d06d09c1..b83724160 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -4,6 +4,7 @@ #include "common/parsing.h" #include "detection/terminalshell/terminalshell.h" #include "detection/displayserver/displayserver.h" +#include "util/stringUtils.h" static const char* getSystemMonospaceFont(const FFinstance* instance) { diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 1a2875508..460b98a09 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -1,9 +1,9 @@ -#include "fastfetch.h" +#include "terminalshell.h" #include "common/io/io.h" #include "common/parsing.h" #include "common/processing.h" #include "common/thread.h" -#include "terminalshell.h" +#include "util/stringUtils.h" #include #include diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index c61e6f8f8..b6ccd0698 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -7,6 +7,7 @@ #include "common/library.h" #include "common/io/io.h" #include "common/parsing.h" +#include "util/stringUtils.h" #include #include diff --git a/src/detection/wmtheme/wmtheme.h b/src/detection/wmtheme/wmtheme.h index e1475006f..33a15dd0f 100644 --- a/src/detection/wmtheme/wmtheme.h +++ b/src/detection/wmtheme/wmtheme.h @@ -3,6 +3,8 @@ #ifndef FASTFETCH_INCLUDED_detection_wmtheme #define FASTFETCH_INCLUDED_detection_wmtheme +#include "fastfetch.h" + bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError); #endif diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index 87a8437c1..8d2a079f6 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -1,10 +1,10 @@ -#include "fastfetch.h" +#include "wmtheme.h" #include "common/properties.h" #include "common/parsing.h" #include "common/settings.h" #include "detection/gtk.h" #include "detection/displayserver/displayserver.h" -#include "wmtheme.h" +#include "util/stringUtils.h" static bool detectWMThemeFromConfigFile(FFinstance* instance, const char* configFile, const char* themeRegex, const char* defaultValue, FFstrbuf* themeOrError) { diff --git a/src/fastfetch.c b/src/fastfetch.c index ded937466..c107f4768 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1,9 +1,10 @@ #include "fastfetch.h" -#include "util/FFvaluestore.h" #include "common/printing.h" #include "common/parsing.h" #include "common/io/io.h" #include "common/time.h" +#include "util/FFvaluestore.h" +#include "util/stringUtils.h" #include #include diff --git a/src/modules/opencl.c b/src/modules/opencl.c index debfcd45e..18e826317 100644 --- a/src/modules/opencl.c +++ b/src/modules/opencl.c @@ -7,6 +7,7 @@ #if defined(FF_HAVE_OPENCL) || defined(__APPLE__) #include "common/library.h" #include "common/parsing.h" +#include "util/stringUtils.h" #include #define CL_TARGET_OPENCL_VERSION 100 diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 375c53aaa..94f436d51 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -3,17 +3,6 @@ #include #include -bool ffStrSet(const char* str) -{ - if(str == NULL) - return false; - - while(isspace(*str)) - str++; - - return *str != '\0'; -} - static char* CHAR_NULL_PTR = ""; void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 7342cb607..7755225a7 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -18,8 +18,6 @@ #define strcasestr StrStrIA #endif -bool ffStrSet(const char* str); - #define FASTFETCH_STRBUF_DEFAULT_ALLOC 32 typedef struct FFstrbuf diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index d549b6501..2a880aed1 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -1,4 +1,5 @@ #include "FFPlatform_private.h" +#include "util/stringUtils.h" void ffPlatformInit(FFPlatform* platform) { diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 65dad8d8b..6d65defcb 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -1,5 +1,5 @@ #include "FFPlatform_private.h" - +#include "util/stringUtils.h" #include "fastfetch_config.h" #include diff --git a/src/util/stringUtils.c b/src/util/stringUtils.c new file mode 100644 index 000000000..703c81a45 --- /dev/null +++ b/src/util/stringUtils.c @@ -0,0 +1,29 @@ +#include "stringUtils.h" + +#include +#include + +bool ffStrSet(const char* str) +{ + if(str == NULL) + return false; + + while(isspace(*str)) + str++; + + return *str != '\0'; +} + +bool ffStrHasNChars(const char* str, char c, uint32_t n) +{ + for(uint32_t i = 0; i < n; i++) + { + char* current = strchr(str, c); + if(current == NULL) + return false; + + str = current + 1; + } + + return true; +} diff --git a/src/util/stringUtils.h b/src/util/stringUtils.h new file mode 100644 index 000000000..7c2475353 --- /dev/null +++ b/src/util/stringUtils.h @@ -0,0 +1,12 @@ +#pragma once + +#ifndef FF_INCLUDED_util_stringUtils_h +#define FF_INCLUDED_util_stringUtils_h + +#include +#include + +bool ffStrSet(const char* str); +bool ffStrHasNChars(const char* str, char c, uint32_t n); + +#endif From 159f4a3a3c60c972c584dc61e4302e842e9f7590 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Wed, 1 Feb 2023 18:35:06 +0100 Subject: [PATCH 063/119] Fix build on apple --- src/detection/packages/packages_apple.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/packages/packages_apple.c b/src/detection/packages/packages_apple.c index b8bc8a682..eaaf5f2fa 100644 --- a/src/detection/packages/packages_apple.c +++ b/src/detection/packages/packages_apple.c @@ -1,5 +1,6 @@ #include "packages.h" #include "common/parsing.h" +#include "util/stringUtils.h" #include From 8153c8b82c730becb4b740224c7ba465a1d241b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 2 Feb 2023 17:50:22 +0800 Subject: [PATCH 064/119] LocalIP: support `--localip-compact-type` option (#408) --- CHANGELOG.md | 3 +- completions/bash | 1 + src/common/init.c | 1 + src/data/help.txt | 1 + src/fastfetch.c | 10 ++++ src/fastfetch.h | 9 ++++ src/modules/localip.c | 109 ++++++++++++++++++++++++++++-------------- 7 files changed, 97 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 674e5b3f3..8ae796c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ Features: * Bluetooth module * Sound module * Gamepad module -* Support colored percentage numbers output +* Support colored percentage numbers output (#409) +* Support `--localip-compact-type` option (#408) Bugfixes: diff --git a/completions/bash b/completions/bash index 93386be34..5533d45a2 100644 --- a/completions/bash +++ b/completions/bash @@ -186,6 +186,7 @@ __fastfetch_completion() "--localip-show-ipv6" "--localip-show-loop" "--localip-name-prefix" + "--localip-compact-type" "--escape-bedrock" "--pipe" "--title-fqdn" diff --git a/src/common/init.c b/src/common/init.c index 592ba17df..cd1105534 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -175,6 +175,7 @@ static void defaultConfig(FFinstance* instance) instance->config.localIpShowIpV6 = false; instance->config.localIpShowLoop = false; ffStrbufInit(&instance->config.localIpNamePrefix); + instance->config.localIpCompactType = FF_LOCALIP_COMPACT_TYPE_NONE; instance->config.publicIpTimeout = 0; ffStrbufInit(&instance->config.publicIpUrl); diff --git a/src/data/help.txt b/src/data/help.txt index 3eeaf662b..b8cf324f7 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -124,6 +124,7 @@ Module specific options: --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false --localip-name-prefix : Show IPs with given name prefix only. Default is empty + --localip-compact-type : Show IPs in one line. Should be either none (disable one-line mode), default (don't sort the result), v4first (print ipv4 first) and v6first. Default is none --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) --public-ip-url: The URL of public IP detection server to be used. --weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0) diff --git a/src/fastfetch.c b/src/fastfetch.c index a977d3c47..594c5c87b 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1290,6 +1290,16 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.localIpShowLoop = optionParseBoolean(value); else if(strcasecmp(key, "--localip-name-prefix") == 0) optionParseString(key, value, &instance->config.localIpNamePrefix); + else if(strcasecmp(key, "--localip-compact-type") == 0) + { + optionParseEnum(key, value, &instance->config.localIpCompactType, + "none", FF_LOCALIP_COMPACT_TYPE_NONE, + "default", FF_LOCALIP_COMPACT_TYPE_DEFAULT, + "v4first", FF_LOCALIP_COMPACT_TYPE_V4FIRST, + "v6first", FF_LOCALIP_COMPACT_TYPE_V6FIRST, + NULL + ); + } else if(strcasecmp(key, "--os-file") == 0) optionParseString(key, value, &instance->config.osFile); else if(strcasecmp(key, "--player-name") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index b625611b1..f31562208 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -41,6 +41,14 @@ typedef enum FFSoundType FF_SOUND_TYPE_ALL, } FFSoundType; +typedef enum FFLocalIpCompactType +{ + FF_LOCALIP_COMPACT_TYPE_NONE, + FF_LOCALIP_COMPACT_TYPE_DEFAULT, + FF_LOCALIP_COMPACT_TYPE_V4FIRST, + FF_LOCALIP_COMPACT_TYPE_V6FIRST, +} FFLocalIpCompactType; + typedef enum FFBinaryPrefixType { FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) @@ -204,6 +212,7 @@ typedef struct FFconfig bool localIpShowIpV4; bool localIpShowIpV6; FFstrbuf localIpNamePrefix; + FFLocalIpCompactType localIpCompactType; FFstrbuf publicIpUrl; uint32_t publicIpTimeout; diff --git a/src/modules/localip.c b/src/modules/localip.c index 3a445c5e5..d751cbdba 100644 --- a/src/modules/localip.c +++ b/src/modules/localip.c @@ -5,9 +5,25 @@ #define FF_LOCALIP_MODULE_NAME "Local IP" #define FF_LOCALIP_NUM_FORMAT_ARGS 2 +static int sortIpsV4First(const FFLocalIpResult* left, const FFLocalIpResult* right) +{ + if (left->ipv6 != right->ipv6) + return left->ipv6 == false ? -1 : 1; + + return ffStrbufComp(&left->addr, &right->addr); +} + +static int sortIpsV6First(const FFLocalIpResult* left, const FFLocalIpResult* right) +{ + if (left->ipv6 != right->ipv6) + return left->ipv6 == true ? -1 : 1; + + return ffStrbufComp(&left->addr, &right->addr); +} + void ffPrintLocalIp(FFinstance* instance) { - FFlist results; + FF_LIST_AUTO_DESTROY results; ffListInit(&results, sizeof(FFLocalIpResult)); const char* error = ffDetectLocalIps(instance, &results); @@ -15,56 +31,77 @@ void ffPrintLocalIp(FFinstance* instance) if(error) { ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "%s", error); - goto exit; + return; } if(results.length == 0) { ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "Failed to detect any IPs"); - goto exit; + return; } - FFstrbuf key; - ffStrbufInit(&key); - - for(uint32_t i = 0; i < results.length; ++i) + if (instance->config.localIpCompactType != FF_LOCALIP_COMPACT_TYPE_NONE) { - FFLocalIpResult* ip = (FFLocalIpResult*) ffListGet(&results, i); + ffPrintLogoAndKey(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP.key); - if(instance->config.localIP.key.length == 0) + switch (instance->config.localIpCompactType) { - if(ip->name.length) - ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars); - else - ffStrbufSetS(&key, FF_LOCALIP_MODULE_NAME); - } - else - { - ffStrbufClear(&key); - ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &ip->name} - }); + case FF_LOCALIP_COMPACT_TYPE_V4FIRST: + ffListSort(&results, (void*) sortIpsV4First); + break; + case FF_LOCALIP_COMPACT_TYPE_V6FIRST: + ffListSort(&results, (void*) sortIpsV6First); + break; + default: + break; } - if(instance->config.localIP.outputFormat.length == 0) + uint32_t index = 0; + FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) { - ffPrintLogoAndKey(instance, key.chars, 0, NULL); - ffStrbufPutTo(&ip->addr, stdout); + if (index++ > 0) + putchar(' '); + ffStrbufWriteTo(&ip->addr, stdout); } - else - { - ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &ip->addr}, - {FF_FORMAT_ARG_TYPE_STRING, ip->ipv6 ? "IPv6" : "IPv4"} - }); - } - - ffStrbufDestroy(&ip->name); - ffStrbufDestroy(&ip->addr); + putchar('\n'); } + else + { + FF_STRBUF_AUTO_DESTROY key; + ffStrbufInit(&key); - ffStrbufDestroy(&key); + FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) + { + if(instance->config.localIP.key.length == 0) + { + if(ip->name.length) + ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars); + else + ffStrbufSetS(&key, FF_LOCALIP_MODULE_NAME); + } + else + { + ffStrbufClear(&key); + ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &ip->name} + }); + } -exit: - ffListDestroy(&results); + if(instance->config.localIP.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, key.chars, 0, NULL); + ffStrbufPutTo(&ip->addr, stdout); + } + else + { + ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &ip->addr}, + {FF_FORMAT_ARG_TYPE_STRING, ip->ipv6 ? "IPv6" : "IPv4"} + }); + } + + ffStrbufDestroy(&ip->name); + ffStrbufDestroy(&ip->addr); + } + } } From 8fad590f8b645368ce5aa8b143d1a84465dba4c6 Mon Sep 17 00:00:00 2001 From: CSoellinger Date: Thu, 2 Feb 2023 11:40:37 +0100 Subject: [PATCH 065/119] feat: add terminator terminal support --- src/detection/terminalfont/terminalfont.c | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index d4c1359ad..5ea2f3876 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -320,6 +320,28 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFo return true; } +static bool detectTerminator(const FFinstance* instance, FFTerminalFontResult* result) +{ + FFstrbuf fontName; + ffStrbufInit(&fontName); + + FFpropquery fontQuery[] = { + {"font =", &fontName}, + }; + + if(!ffParsePropFileConfigValues(instance, "terminator/config", 1, fontQuery)) + return false; + + if(fontName.length == 0) + ffStrbufSetS(&fontName, "Mono 8"); + + ffFontInitCopy(&result->font, fontName.chars); + + ffStrbufDestroy(&fontName); + + return true; +} + static bool detectWezterm(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminalFontResult* result) { FF_STRBUF_AUTO_DESTROY fontName; @@ -354,6 +376,8 @@ static bool detectTerminalFontCommon(const FFinstance* instance, const FFTermina { if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "alacritty")) detectAlacritty(instance, terminalFont); + else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "terminator")) + detectTerminator(instance, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui")) detectWezterm(instance, terminalFont); From f0111a8037ddbb1aa8b6fbd053d0387d5b0dffea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 2 Feb 2023 19:17:51 +0800 Subject: [PATCH 066/119] Windows: silense compiler warnings --- src/util/platform/FFPlatform_windows.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 0e5e8a078..d264926b1 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -1,4 +1,5 @@ #include "FFPlatform_private.h" +#include "util/stringUtils.h" #define WIN32_LEAN_AND_MEAN #include From cae9fee30af90c0eda0cd36652e0e336f0035f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 2 Feb 2023 21:01:50 +0800 Subject: [PATCH 067/119] LocalIP (Windows): fix ipv6 detection --- CHANGELOG.md | 1 + src/detection/localip/localip_windows.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ae796c35..52f94538d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Bugfixes: * Fix a rare case that fails to detect terminal * Fix Muffin detection (@Zerogiven, #411) +* Fix IPv6 detection (Windows) Other: diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index e23a32fe8..4125542b4 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -77,7 +77,7 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results) SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr; char addressBuffer[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN); - addNewIp(results, name, addressBuffer, false); + addNewIp(results, name, addressBuffer, true); } } } From ec3cd6cc68afbacc57bb72c33cf6e1ea4223e611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 2 Feb 2023 22:25:31 +0800 Subject: [PATCH 068/119] LocalIP: support multiline compact mode --- src/common/init.c | 1 + src/data/help.txt | 3 +- src/fastfetch.c | 7 +-- src/fastfetch.h | 6 +-- src/modules/localip.c | 100 ++++++++++++++++++++++++++++-------------- 5 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index cd1105534..cf4a46735 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -174,6 +174,7 @@ static void defaultConfig(FFinstance* instance) instance->config.localIpShowIpV4 = true; instance->config.localIpShowIpV6 = false; instance->config.localIpShowLoop = false; + instance->config.localIpV6First = false; ffStrbufInit(&instance->config.localIpNamePrefix); instance->config.localIpCompactType = FF_LOCALIP_COMPACT_TYPE_NONE; diff --git a/src/data/help.txt b/src/data/help.txt index b8cf324f7..789bfb390 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -124,7 +124,8 @@ Module specific options: --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false --localip-name-prefix : Show IPs with given name prefix only. Default is empty - --localip-compact-type : Show IPs in one line. Should be either none (disable one-line mode), default (don't sort the result), v4first (print ipv4 first) and v6first. Default is none + --localip-compact-type : Show IPs in one line. Should be either none, oneline, multiline. Default is none + --localip-v6first : Set if ipv6 should be printed first. Default is false --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) --public-ip-url: The URL of public IP detection server to be used. --weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0) diff --git a/src/fastfetch.c b/src/fastfetch.c index 594c5c87b..b5ebaf0ca 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1282,6 +1282,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) optionParseString(key, value, &instance->config.separatorString); + else if(strcasecmp(key, "--localip-v6first") == 0) + instance->config.localIpV6First = optionParseBoolean(value); else if(strcasecmp(key, "--localip-show-ipv4") == 0) instance->config.localIpShowIpV4 = optionParseBoolean(value); else if(strcasecmp(key, "--localip-show-ipv6") == 0) @@ -1294,9 +1296,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con { optionParseEnum(key, value, &instance->config.localIpCompactType, "none", FF_LOCALIP_COMPACT_TYPE_NONE, - "default", FF_LOCALIP_COMPACT_TYPE_DEFAULT, - "v4first", FF_LOCALIP_COMPACT_TYPE_V4FIRST, - "v6first", FF_LOCALIP_COMPACT_TYPE_V6FIRST, + "oneline", FF_LOCALIP_COMPACT_TYPE_ONELINE, + "multiline", FF_LOCALIP_COMPACT_TYPE_MULTILINE, NULL ); } diff --git a/src/fastfetch.h b/src/fastfetch.h index f31562208..627748c16 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -44,9 +44,8 @@ typedef enum FFSoundType typedef enum FFLocalIpCompactType { FF_LOCALIP_COMPACT_TYPE_NONE, - FF_LOCALIP_COMPACT_TYPE_DEFAULT, - FF_LOCALIP_COMPACT_TYPE_V4FIRST, - FF_LOCALIP_COMPACT_TYPE_V6FIRST, + FF_LOCALIP_COMPACT_TYPE_MULTILINE, + FF_LOCALIP_COMPACT_TYPE_ONELINE, } FFLocalIpCompactType; typedef enum FFBinaryPrefixType @@ -209,6 +208,7 @@ typedef struct FFconfig FFstrbuf separatorString; bool localIpShowLoop; + bool localIpV6First; bool localIpShowIpV4; bool localIpShowIpV6; FFstrbuf localIpNamePrefix; diff --git a/src/modules/localip.c b/src/modules/localip.c index d751cbdba..f0429e0a0 100644 --- a/src/modules/localip.c +++ b/src/modules/localip.c @@ -7,6 +7,10 @@ static int sortIpsV4First(const FFLocalIpResult* left, const FFLocalIpResult* right) { + int name = ffStrbufComp(&left->name, &right->name); + if (name != 0) + return name; + if (left->ipv6 != right->ipv6) return left->ipv6 == false ? -1 : 1; @@ -15,12 +19,62 @@ static int sortIpsV4First(const FFLocalIpResult* left, const FFLocalIpResult* ri static int sortIpsV6First(const FFLocalIpResult* left, const FFLocalIpResult* right) { + int name = ffStrbufComp(&left->name, &right->name); + if (name != 0) + return name; + if (left->ipv6 != right->ipv6) return left->ipv6 == true ? -1 : 1; return ffStrbufComp(&left->addr, &right->addr); } +static void formatKey(const FFinstance* instance, const FFLocalIpResult* ip, FFstrbuf* key) +{ + if(instance->config.localIP.key.length == 0) + { + if(ip->name.length) + ffStrbufSetF(key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars); + else + ffStrbufSetS(key, FF_LOCALIP_MODULE_NAME); + } + else + { + ffStrbufClear(key); + ffParseFormatString(key, &instance->config.localIP.key, 1, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &ip->name} + }); + } +} + +static void printIpsOneline(FFlist* ips) +{ + uint32_t index = 0; + FF_LIST_FOR_EACH(FFLocalIpResult, ip, *ips) + { + if (index++ > 0) + putchar(' '); + ffStrbufWriteTo(&ip->addr, stdout); + } +} + +static void printIpsWithKey(FFinstance* instance, FFlist* ips) +{ + FFLocalIpResult* ip = (FFLocalIpResult*) ffListGet(ips, 0); + if (instance->config.localIpCompactType == FF_LOCALIP_COMPACT_TYPE_MULTILINE) + { + FF_STRBUF_AUTO_DESTROY key; + ffStrbufInit(&key); + formatKey(instance, ip, &key); + ffPrintLogoAndKey(instance, key.chars, 0, NULL); + } + printIpsOneline(ips); + if (instance->config.localIpCompactType == FF_LOCALIP_COMPACT_TYPE_ONELINE) + printf(" (%s) ", ip->name.chars); + else + putchar('\n'); +} + void ffPrintLocalIp(FFinstance* instance) { FF_LIST_AUTO_DESTROY results; @@ -40,30 +94,26 @@ void ffPrintLocalIp(FFinstance* instance) return; } + ffListSort(&results, instance->config.localIpV6First ? (void*) sortIpsV6First : (void*) sortIpsV4First); + if (instance->config.localIpCompactType != FF_LOCALIP_COMPACT_TYPE_NONE) { - ffPrintLogoAndKey(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP.key); + if (instance->config.localIpCompactType == FF_LOCALIP_COMPACT_TYPE_ONELINE) + ffPrintLogoAndKey(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP.key); - switch (instance->config.localIpCompactType) - { - case FF_LOCALIP_COMPACT_TYPE_V4FIRST: - ffListSort(&results, (void*) sortIpsV4First); - break; - case FF_LOCALIP_COMPACT_TYPE_V6FIRST: - ffListSort(&results, (void*) sortIpsV6First); - break; - default: - break; - } + FF_LIST_AUTO_DESTROY ips; + ffListInit(&ips, sizeof(FFLocalIpResult)); // weak references - uint32_t index = 0; FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) { - if (index++ > 0) - putchar(' '); - ffStrbufWriteTo(&ip->addr, stdout); + if (ips.length > 0 && !ffStrbufEqual(&ip->name, &ip[-1].name)) + { + printIpsWithKey(instance, &ips); + ips.length = 0; + } + *(FFLocalIpResult*)ffListAdd(&ips) = *ip; } - putchar('\n'); + printIpsWithKey(instance, &ips); } else { @@ -72,21 +122,7 @@ void ffPrintLocalIp(FFinstance* instance) FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) { - if(instance->config.localIP.key.length == 0) - { - if(ip->name.length) - ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars); - else - ffStrbufSetS(&key, FF_LOCALIP_MODULE_NAME); - } - else - { - ffStrbufClear(&key); - ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &ip->name} - }); - } - + formatKey(instance, ip, &key); if(instance->config.localIP.outputFormat.length == 0) { ffPrintLogoAndKey(instance, key.chars, 0, NULL); From 84ccda45b01e0dd1607aa678cb7fd676cc409d56 Mon Sep 17 00:00:00 2001 From: CSoellinger Date: Thu, 2 Feb 2023 16:16:24 +0100 Subject: [PATCH 069/119] feat: simplify parse prop file config --- src/detection/terminalfont/terminalfont.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 5ea2f3876..daf984dad 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -325,11 +325,7 @@ static bool detectTerminator(const FFinstance* instance, FFTerminalFontResult* r FFstrbuf fontName; ffStrbufInit(&fontName); - FFpropquery fontQuery[] = { - {"font =", &fontName}, - }; - - if(!ffParsePropFileConfigValues(instance, "terminator/config", 1, fontQuery)) + if(!ffParsePropFileConfig(instance, "terminator/config", "font =", &fontName)) return false; if(fontName.length == 0) From 6de74587bd72e4d01dcb4a65b2f81ef9741f2f41 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 2 Feb 2023 17:14:53 +0100 Subject: [PATCH 070/119] Update terminator font detection --- CHANGELOG.md | 1 + README.md | 2 +- src/detection/terminalfont/terminalfont.c | 35 ++++++++++++++++------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f94538d..61326e9f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Features: * Gamepad module * Support colored percentage numbers output (#409) * Support `--localip-compact-type` option (#408) +* Terminator terminal font detection (@Zerogiven, #415) Bugfixes: diff --git a/README.md b/README.md index 192c498c3..7de10993e 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4 ##### Terminal fonts ``` -Alacritty, Apple Terminal, ConEmu, Deepin Terminal, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal +Alacritty, Apple Terminal, ConEmu, Deepin Terminal, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal ``` ## Building diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index daf984dad..e8a6fb58b 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -320,22 +320,35 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFo return true; } -static bool detectTerminator(const FFinstance* instance, FFTerminalFontResult* result) +static void detectTerminator(const FFinstance* instance, FFTerminalFontResult* result) { - FFstrbuf fontName; + FF_STRBUF_AUTO_DESTROY useSystemFont; + ffStrbufInit(&useSystemFont); + + FF_STRBUF_AUTO_DESTROY fontName; ffStrbufInit(&fontName); - if(!ffParsePropFileConfig(instance, "terminator/config", "font =", &fontName)) - return false; + FFpropquery fontQuery[] = { + {"use_system_font =", &useSystemFont}, + {"font =", &fontName}, + }; + + if(!ffParsePropFileConfigValues(instance, "terminator/config", 2, fontQuery)) + { + ffStrbufAppendS(&result->error, "Couldn't read Terminator config file"); + return; + } + + if(ffStrbufIgnCaseEqualS(&useSystemFont, "True")) + { + ffFontInitCopy(&result->font, "System"); + return; + } if(fontName.length == 0) - ffStrbufSetS(&fontName, "Mono 8"); - - ffFontInitCopy(&result->font, fontName.chars); - - ffStrbufDestroy(&fontName); - - return true; + ffFontInitValues(&result->font, "mono", "8"); + else + ffFontInitPango(&result->font, fontName.chars); } static bool detectWezterm(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminalFontResult* result) From e57f7d378ae357a90950faebbf0164ddff0edf50 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 2 Feb 2023 18:16:56 +0100 Subject: [PATCH 071/119] Wayland: support basic scale factors #414 --- presets/verbose | 2 +- src/detection/displayserver/linux/wayland.c | 129 +++++++++++++------- src/fastfetch.c | 5 +- src/modules/display.c | 2 +- 4 files changed, 88 insertions(+), 50 deletions(-) diff --git a/presets/verbose b/presets/verbose index 991fecb7f..1d4823259 100644 --- a/presets/verbose +++ b/presets/verbose @@ -5,7 +5,7 @@ --processes-format Count: {} --packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {} --shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {} ---display-format Width: {}; Height: {}; Refresh rate: {} +--display-format Width: {}; Height: {}; Refresh rate: {}; ScaledWith: {}; ScaledHeight: {} --de-format Process name: {}; Pretty name: {}; Version: {} --wm-format Process name: {}; Pretty name: {}; Protocol: {} --wm-theme-format Name: {} diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 2b6ed5f70..c5c2f13a7 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -12,13 +12,23 @@ typedef struct WaylandData { - FFlist* results; + FFDisplayServerResult* result; FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned) FF_LIBRARY_SYMBOL(wl_proxy_add_listener) FF_LIBRARY_SYMBOL(wl_proxy_destroy) + FF_LIBRARY_SYMBOL(wl_display_roundtrip) + struct wl_display* display; const struct wl_interface* ffwl_output_interface; } WaylandData; +typedef struct WaylandDisplay +{ + int32_t width; + int32_t height; + int32_t refreshRate; + int32_t scale; +} WaylandDisplay; + #ifndef __FreeBSD__ static void waylandDetectWM(int fd, FFDisplayServerResult* result) { @@ -49,25 +59,76 @@ static void stubListener(void* data, ...) static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate) { - WaylandData* wldata = data; + FF_UNUSED(output); - wldata->ffwl_proxy_destroy((struct wl_proxy*) output); + if(!(flags & WL_OUTPUT_MODE_CURRENT)) + return; - if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0) + WaylandDisplay* display = data; + display->width = width; + display->height = height; + display->refreshRate = refreshRate; +} + +#if WAYLAND_VERSION_MINOR >= 2 +static void waylandOutputScaleListener(void* data, struct wl_output* output, int32_t scale) +{ + FF_UNUSED(output); + + WaylandDisplay* display = data; + display->scale = scale; +} +#endif + +static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) +{ + struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL); + if(output == NULL) + return; + + WaylandDisplay display = { + .width = 0, + .height = 0, + .refreshRate = 0, + .scale = 1, + }; + + struct wl_output_listener outputListener = { + .mode = waylandOutputModeListener, + .geometry = (void*) stubListener, + + //https://lists.freedesktop.org/archives/wayland-devel/2013-July/010278.html + #if WAYLAND_VERSION_MINOR >= 2 + .done = (void*) stubListener, + .scale = waylandOutputScaleListener, + #endif + + //https://lists.freedesktop.org/archives/wayland-devel/2021-December/042064.html + #if WAYLAND_VERSION_MINOR >= 20 + .name = (void*) stubListener, + .description = (void*) stubListener, + #endif + }; + + wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display); + wldata->ffwl_display_roundtrip(wldata->display); + wldata->ffwl_proxy_destroy(output); + + if(display.width <= 0 || display.height <= 0) return; static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; ffThreadMutexLock(&mutex); - FFDisplayResult* result = ffListAdd(wldata->results); + ffdsAppendDisplay(wldata->result, + (uint32_t) display.width, + (uint32_t) display.height, + ffdsParseRefreshRate(display.refreshRate / 1000), + (uint32_t) (display.width * display.scale), + (uint32_t) (display.height * display.scale) + ); ffThreadMutexUnlock(&mutex); - - result->width = (uint32_t) width; - result->height = (uint32_t) height; - result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000); - result->scaledWidth = 0; - result->scaledHeight = 0; } static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) @@ -75,31 +136,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u WaylandData* wldata = data; if(strcmp(interface, wldata->ffwl_output_interface->name) == 0) - { - struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL); - if(output == NULL) - return; - - //Needs to be static, because the scope of the function will already be lost when calling the listener - static struct wl_output_listener outputListener = { - .mode = waylandOutputModeListener, - .geometry = (void*) stubListener, - - //https://lists.freedesktop.org/archives/wayland-devel/2013-July/010278.html - #if WAYLAND_VERSION_MINOR >= 2 - .done = (void*) stubListener, - .scale = (void*) stubListener, - #endif - - //https://lists.freedesktop.org/archives/wayland-devel/2021-December/042064.html - #if WAYLAND_VERSION_MINOR >= 20 - .name = (void*) stubListener, - .description = (void*) stubListener, - #endif - }; - - wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, data); - } + waylandOutputHandler(wldata, registry, name, version); } bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) @@ -109,7 +146,6 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false) FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false) FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch, false) - FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip, false) FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false) FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false) FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false) @@ -119,26 +155,27 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false) FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false) FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false) + FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false) FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false) - struct wl_display* display = ffwl_display_connect(NULL); - if(display == NULL) + data.display = ffwl_display_connect(NULL); + if(data.display == NULL) { dlclose(wayland); return false; } - waylandDetectWM(ffwl_display_get_fd(display), result); + waylandDetectWM(ffwl_display_get_fd(data.display), result); - struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL); + struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL); if(registry == NULL) { - ffwl_display_disconnect(display); + ffwl_display_disconnect(data.display); dlclose(wayland); return false; } - data.results = &result->displays; + data.result = result; struct wl_registry_listener registry_listener = { .global = waylandGlobalAddListener, @@ -146,11 +183,11 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) }; data.ffwl_proxy_add_listener(registry, (void(**)(void)) ®istry_listener, &data); - ffwl_display_dispatch(display); - ffwl_display_roundtrip(display); + ffwl_display_dispatch(data.display); + data.ffwl_display_roundtrip(data.display); data.ffwl_proxy_destroy(registry); - ffwl_display_disconnect(display); + ffwl_display_disconnect(data.display); dlclose(wayland); //We successfully connected to wayland and detected the display. diff --git a/src/fastfetch.c b/src/fastfetch.c index b5ebaf0ca..deebe41d8 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -174,11 +174,12 @@ static inline void printCommandHelp(const char* command) } else if(strcasecmp(command, "display-format") == 0) { - constructAndPrintCommandHelpFormat("display", "{}x{} @ {}Hz", 4, + constructAndPrintCommandHelpFormat("display", "{}x{} @ {}Hz", 5, "Screen width", "Screen height", "Screen refresh rate", - "Screen brightness" + "Screen scaled width", + "Screen scaled height" ); } else if(strcasecmp(command, "de-format") == 0) diff --git a/src/modules/display.c b/src/modules/display.c index 45d93234b..cc6971f1a 100644 --- a/src/modules/display.c +++ b/src/modules/display.c @@ -3,7 +3,7 @@ #include "detection/displayserver/displayserver.h" #define FF_RESOLUTION_MODULE_NAME "Display" -#define FF_RESOLUTION_NUM_FORMAT_ARGS 3 +#define FF_RESOLUTION_NUM_FORMAT_ARGS 5 void ffPrintDisplay(FFinstance* instance) { From fc26acd0ab9ed34ac534c88b17b93cf967a9cea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 3 Feb 2023 10:34:17 +0800 Subject: [PATCH 072/119] DisplayServer: fix scaled resolution detection (Linux) --- src/detection/displayserver/linux/wayland.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index c5c2f13a7..a6ca31edd 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -124,8 +124,8 @@ static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* regist (uint32_t) display.width, (uint32_t) display.height, ffdsParseRefreshRate(display.refreshRate / 1000), - (uint32_t) (display.width * display.scale), - (uint32_t) (display.height * display.scale) + (uint32_t) (display.width / display.scale), + (uint32_t) (display.height / display.scale) ); ffThreadMutexUnlock(&mutex); From 47a32c725d405d6390b0576e27b0cf1cd77c00a2 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 11:22:34 +0100 Subject: [PATCH 073/119] X11: init scaled resolution with normal resolution --- src/detection/displayserver/linux/xcb.c | 20 ++++++++++---------- src/detection/displayserver/linux/xlib.c | 24 ++++++++++++------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 0909d0b76..183ff5251 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -120,8 +120,8 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) (uint32_t) iterator.data->width_in_pixels, (uint32_t) iterator.data->height_in_pixels, 0, - 0, - 0 + (uint32_t) iterator.data->width_in_pixels, + (uint32_t) iterator.data->height_in_pixels ); ffxcb_screen_next(&iterator); } @@ -187,8 +187,8 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, refreshRate == 0 ? data->defaultRefreshRate : refreshRate, - 0, - 0 + (uint32_t) modeInfo->width, + (uint32_t) modeInfo->height ); } @@ -224,8 +224,8 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, data->defaultRefreshRate, - 0, - 0 + (uint32_t) crtcInfoReply->width, + (uint32_t) crtcInfoReply->height ); free(crtcInfoReply); @@ -269,8 +269,8 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* (uint32_t) monitor->width, (uint32_t) monitor->height, data->defaultRefreshRate, - 0, - 0 + (uint32_t) monitor->width, + (uint32_t) monitor->height ); } @@ -329,8 +329,8 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) (uint32_t) screen->width_in_pixels, (uint32_t) screen->height_in_pixels, data->defaultRefreshRate, - 0, - 0 + (uint32_t) screen->width_in_pixels, + (uint32_t) screen->height_in_pixels ); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index a804dd29a..50eba6a2d 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -82,11 +82,11 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) Screen* screen = ScreenOfDisplay(display, i); ffdsAppendDisplay( result, - (uint32_t) screen->width, - (uint32_t) screen->height, + (uint32_t) WidthOfScreen(screen), + (uint32_t) HeightOfScreen(screen), 0, - 0, - 0 + (uint32_t) WidthOfScreen(screen), + (uint32_t) HeightOfScreen(screen) ); } @@ -146,8 +146,8 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, refreshRate == 0 ? data->defaultRefreshRate : refreshRate, - 0, - 0 + (uint32_t) modeInfo->width, + (uint32_t) modeInfo->height ); } @@ -177,8 +177,8 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, data->defaultRefreshRate, - 0, - 0 + (uint32_t) crtcInfo->width, + (uint32_t) crtcInfo->height ); data->ffXRRFreeCrtcInfo(crtcInfo); @@ -213,8 +213,8 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, data->defaultRefreshRate, - 0, - 0 + (uint32_t) monitorInfo->width, + (uint32_t) monitorInfo->height ); } @@ -267,8 +267,8 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) (uint32_t) WidthOfScreen(screen), (uint32_t) HeightOfScreen(screen), data->defaultRefreshRate, - 0, - 0 + (uint32_t) WidthOfScreen(screen), + (uint32_t) HeightOfScreen(screen) ); } From 2a80b5ed36a1f50780a2f8e2099633e30a33a5d4 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 13:37:15 +0100 Subject: [PATCH 074/119] Pipeline(Linux): Build on Ubuntu 20.04 --- .github/workflows/push.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index ef6d86833..919cdbdf3 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-22.04 ubuntu-20.04] compiler: [gcc, clang] enableFeatures: [ON, OFF] runs-on: ${{ matrix.os }} @@ -42,7 +42,7 @@ jobs: linux: name: Linux - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package permissions: security-events: write contents: read From 2005b396faae3f000ac092af265a77f3af7bc967 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 13:38:37 +0100 Subject: [PATCH 075/119] Add missing comma --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 919cdbdf3..cc50f09b5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04 ubuntu-20.04] + os: [ubuntu-22.04, ubuntu-20.04] compiler: [gcc, clang] enableFeatures: [ON, OFF] runs-on: ${{ matrix.os }} From 7a8b94b6d40125de780660656f4ef3ba8e692443 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 14:20:15 +0100 Subject: [PATCH 076/119] Fix build with older libnm versions --- src/detection/wifi/wifi_linux.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 5bc789cdb..178520c8e 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -13,6 +13,12 @@ #define NM_NO_INCLUDE_EXTRA_HEADERS 1 #include +//https://developer-old.gnome.org/libnm/stable/libnm-nm-dbus-interface.html +#ifndef NM_VERSION_1_26 + #define NM_802_11_AP_SEC_KEY_MGMT_OWE 0x00000800 + #define NM_802_11_AP_SEC_KEY_MGMT_OWE_TM 0x00001000 +#endif + static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* result) { FF_LIBRARY_LOAD(nm, &instance->config.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0); From 550e1076833d9e79539ed78c39425de44f98ab5c Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 18:41:08 +0100 Subject: [PATCH 077/119] Pipeline: debug --- .github/workflows/push.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index cc50f09b5..e4cba19c7 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -34,6 +34,9 @@ jobs: - name: run tests run: ctest + - name: debug + run: llvm-symbolizer --obj=fastfetch 0x4966d2 + - name: run fastfetch run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all From 93f1a44d0ff58ed2f33dd634d420c348e96d2114 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 18:43:15 +0100 Subject: [PATCH 078/119] Revert "Pipeline: debug" This reverts commit 550e1076833d9e79539ed78c39425de44f98ab5c. --- .github/workflows/push.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index e4cba19c7..cc50f09b5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -34,9 +34,6 @@ jobs: - name: run tests run: ctest - - name: debug - run: llvm-symbolizer --obj=fastfetch 0x4966d2 - - name: run fastfetch run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all From 291f88b1e4f9e18d758f02fc33c75bd1fdfda26c Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 18:48:40 +0100 Subject: [PATCH 079/119] Pipeline: debug --- .github/workflows/push.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index cc50f09b5..e4ecb0b0c 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -31,6 +31,12 @@ jobs: - name: build project run: cmake --build . + - name: upload artifacts + uses: actions/upload-artifact@v3 + with: + name: fastfetch-linux-buildtest-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.enableFeatures }} + path: ./fastfetch + - name: run tests run: ctest From eead4cf70e36d2612f3cab32dfe45b0db40e01e7 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 3 Feb 2023 18:53:52 +0100 Subject: [PATCH 080/119] Revert "Pipeline: debug" This reverts commit 291f88b1e4f9e18d758f02fc33c75bd1fdfda26c. --- .github/workflows/push.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index e4ecb0b0c..cc50f09b5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -31,12 +31,6 @@ jobs: - name: build project run: cmake --build . - - name: upload artifacts - uses: actions/upload-artifact@v3 - with: - name: fastfetch-linux-buildtest-${{ matrix.os }}-${{ matrix.compiler }}-${{ matrix.enableFeatures }} - path: ./fastfetch - - name: run tests run: ctest From d2460d8e85145529908fa672b0df8f6077701301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 4 Feb 2023 01:53:08 +0800 Subject: [PATCH 081/119] GPU (Windows): try improving performance --- CHANGELOG.md | 1 + CMakeLists.txt | 3 - presets/verbose | 2 +- src/detection/gpu/gpu_windows.cpp | 115 +++++++++++-------- src/util/windows/registry.c | 181 ++++++++++++++++-------------- src/util/windows/registry.h | 1 + 6 files changed, 169 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61326e9f4..2eb3331e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bugfixes: Other: * Simplified wmtheme output format (Windows) +* Improved GPU detection performance on Windows 11 # 1.9.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d1c0eae1..e60e6b26f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -726,9 +726,6 @@ elseif(WIN32) if(USE_WIN_NTAPI) target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI) endif() - if(USE_WIN_GPU_DXGI) - target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_GPU_DXGI) - endif() endif() target_include_directories(libfastfetch diff --git a/presets/verbose b/presets/verbose index 1d4823259..5d8a675bb 100644 --- a/presets/verbose +++ b/presets/verbose @@ -17,7 +17,7 @@ --terminal-font-format Pretty: {}; Name: {}; Size: {}; Styles: {} --cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {} --cpu-usage-format Percentage: {} ---gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {} +--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {} --memory-format Used: {}; Total: {}; Percentage: {} --disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; Removable: {}; Hidden: {}; Filesystem: {}; Name: {} --battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {} diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 07b711205..ccfd187a7 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -1,13 +1,75 @@ extern "C" { #include "gpu.h" #include "util/windows/unicode.h" +#include "util/windows/registry.h" } -#ifdef FF_USE_WIN_GPU_DXGI - #include #include +static const char* detectWithRegistry(FFlist* gpus) +{ + // Ref: https://github.com/lptstr/winfetch/pull/155 + + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\DirectX", &hKey, nullptr)) + return "Open \"SOFTWARE\\Microsoft\\DirectX\" failed"; + + uint64_t lastSeen; + if(!ffRegReadUint64(hKey, L"LastSeen", &lastSeen, nullptr)) + return "Read \"SOFTWARE\\Microsoft\\DirectX\\LastSeen\" failed"; + + DWORD index = 0; + wchar_t subKeyName[64]; + while(true) + { + DWORD subKeySize = sizeof(subKeyName) / sizeof(*subKeyName); + if(RegEnumKeyExW(hKey, index++, subKeyName, &subKeySize, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS) + break; + + FF_HKEY_AUTO_DESTROY hSubKey = NULL; + if(!ffRegOpenKeyForRead(hKey, subKeyName, &hSubKey, nullptr)) + continue; + + uint64_t adapterLastSeen; + if(!ffRegReadUint64(hSubKey, L"LastSeen", &adapterLastSeen, nullptr) || lastSeen != adapterLastSeen) + continue; + + uint32_t softwareAdapter; + if(!ffRegReadUint(hSubKey, L"SoftwareAdapter", &softwareAdapter, nullptr) || softwareAdapter) + continue; + + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->name); + ffStrbufInit(&gpu->driver); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->type = FF_GPU_TYPE_UNKNOWN; + + ffRegReadStrbuf(hSubKey, L"Description", &gpu->name, nullptr); + + uint32_t vendorId; + if(ffRegReadUint(hSubKey, L"VendorId", &vendorId, nullptr)) + { + if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2)) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3)) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3)) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + } + + uint64_t dedicatedVideoMemory; + if(ffRegReadUint64(hSubKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, nullptr)) + { + gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + } + } + + return nullptr; +} + static const char* detectWithDxgi(FFlist* gpus) { IDXGIFactory1* pFactory; @@ -50,56 +112,13 @@ static const char* detectWithDxgi(FFlist* gpus) pFactory->Release(); - return NULL; -} - -#else - -#include "util/windows/wmi.hpp" - -static const char* detectWithWmi(FFlist* gpus) -{ - FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr); - if(!query) - return "Query WMI service failed"; - - while(FFWmiRecord record = query.next()) - { - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - - gpu->type = FF_GPU_TYPE_UNKNOWN; - - ffStrbufInit(&gpu->vendor); - record.getString(L"AdapterCompatibility", &gpu->vendor); - if(ffStrbufStartsWithS(&gpu->vendor, "Intel ")) - { - //Intel returns "Intel Corporation", not sure about AMD - ffStrbufSetS(&gpu->vendor, "Intel"); - } - - ffStrbufInit(&gpu->name); - record.getString(L"Name", &gpu->name); - - ffStrbufInit(&gpu->driver); - record.getString(L"DriverVersion", &gpu->driver); - - gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; - } - return nullptr; } -#endif - extern "C" -const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) +const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance) { - FF_UNUSED(instance); - - #ifdef FF_USE_WIN_GPU_DXGI + if (!detectWithRegistry(gpus)) + return nullptr; return detectWithDxgi(gpus); - #else - return detectWithWmi(gpus); - #endif } diff --git a/src/util/windows/registry.c b/src/util/windows/registry.c index 2257e1963..0a80781d3 100644 --- a/src/util/windows/registry.c +++ b/src/util/windows/registry.c @@ -1,82 +1,99 @@ -#include "registry.h" -#include "unicode.h" -#include "util/mallocHelper.h" - -static const char* hKey2Str(HKEY hKey) -{ - #define HKEY_CASE(compareKey) if(hKey == compareKey) return #compareKey; - HKEY_CASE(HKEY_CLASSES_ROOT) - HKEY_CASE(HKEY_CURRENT_USER) - HKEY_CASE(HKEY_LOCAL_MACHINE) - HKEY_CASE(HKEY_USERS) - HKEY_CASE(HKEY_PERFORMANCE_DATA) - HKEY_CASE(HKEY_PERFORMANCE_TEXT) - HKEY_CASE(HKEY_PERFORMANCE_NLSTEXT) - HKEY_CASE(HKEY_CURRENT_CONFIG) - HKEY_CASE(HKEY_DYN_DATA) - HKEY_CASE(HKEY_CURRENT_USER_LOCAL_SETTINGS) - #undef HKEY_CASE - - return "UNKNOWN"; -} - -bool ffRegOpenKeyForRead(HKEY hKey, const wchar_t* subKeyW, HKEY* result, FFstrbuf* error) -{ - if(RegOpenKeyExW(hKey, subKeyW, 0, KEY_READ, result) != ERROR_SUCCESS) - { - if(error) - { - FF_STRBUF_AUTO_DESTROY subKeyA = ffStrbufCreateWS(subKeyW); - ffStrbufAppendF(error, "RegOpenKeyExW(%s\\%s) failed", hKey2Str(hKey), subKeyA.chars); - } - return false; - } - return true; -} - -bool ffRegReadStrbuf(HKEY hKey, const wchar_t* valueNameW, FFstrbuf* result, FFstrbuf* error) -{ - DWORD bufSize; //with tailing '\0' - if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, NULL, &bufSize) != ERROR_SUCCESS) - { - if(error) - { - if(!valueNameW) - valueNameW = L"(default)"; - FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); - ffStrbufAppendF(error, "RegGetValueA(%s, NULL, RRF_RT_REG_SZ) failed", valueNameA.chars); - } - return false; - } - wchar_t* FF_AUTO_FREE resultW = (wchar_t*)malloc(bufSize); - if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, resultW, &bufSize) != ERROR_SUCCESS) - { - if(error) - { - if(!valueNameW) - valueNameW = L"(default)"; - FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); - ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_REG_SZ) failed", valueNameA.chars); - } - return false; - } - ffStrbufSetWS(result, resultW); - return true; -} - -bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error) -{ - DWORD bufSize = sizeof(*result); - if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_DWORD, NULL, result, &bufSize) != ERROR_SUCCESS) - { - if(error) - { - if(!valueNameW) - valueNameW = L"(default)"; - FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); - ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_DWORD) failed", valueNameA.chars); - } - return false; - } - return true; -} +#include "registry.h" +#include "unicode.h" +#include "util/mallocHelper.h" + +static const char* hKey2Str(HKEY hKey) +{ + #define HKEY_CASE(compareKey) if(hKey == compareKey) return #compareKey; + HKEY_CASE(HKEY_CLASSES_ROOT) + HKEY_CASE(HKEY_CURRENT_USER) + HKEY_CASE(HKEY_LOCAL_MACHINE) + HKEY_CASE(HKEY_USERS) + HKEY_CASE(HKEY_PERFORMANCE_DATA) + HKEY_CASE(HKEY_PERFORMANCE_TEXT) + HKEY_CASE(HKEY_PERFORMANCE_NLSTEXT) + HKEY_CASE(HKEY_CURRENT_CONFIG) + HKEY_CASE(HKEY_DYN_DATA) + HKEY_CASE(HKEY_CURRENT_USER_LOCAL_SETTINGS) + #undef HKEY_CASE + + return "UNKNOWN"; +} + +bool ffRegOpenKeyForRead(HKEY hKey, const wchar_t* subKeyW, HKEY* result, FFstrbuf* error) +{ + if(RegOpenKeyExW(hKey, subKeyW, 0, KEY_READ, result) != ERROR_SUCCESS) + { + if(error) + { + FF_STRBUF_AUTO_DESTROY subKeyA = ffStrbufCreateWS(subKeyW); + ffStrbufAppendF(error, "RegOpenKeyExW(%s\\%s) failed", hKey2Str(hKey), subKeyA.chars); + } + return false; + } + return true; +} + +bool ffRegReadStrbuf(HKEY hKey, const wchar_t* valueNameW, FFstrbuf* result, FFstrbuf* error) +{ + DWORD bufSize; //with tailing '\0' + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, NULL, &bufSize) != ERROR_SUCCESS) + { + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); + ffStrbufAppendF(error, "RegGetValueW(%s, NULL, RRF_RT_REG_SZ) failed", valueNameA.chars); + } + return false; + } + wchar_t* FF_AUTO_FREE resultW = (wchar_t*)malloc(bufSize); + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, resultW, &bufSize) != ERROR_SUCCESS) + { + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); + ffStrbufAppendF(error, "RegGetValueW(%s, result, RRF_RT_REG_SZ) failed", valueNameA.chars); + } + return false; + } + ffStrbufSetWS(result, resultW); + return true; +} + +bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error) +{ + DWORD bufSize = sizeof(*result); + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_DWORD, NULL, result, &bufSize) != ERROR_SUCCESS) + { + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); + ffStrbufAppendF(error, "RegGetValueW(%s, result, RRF_RT_DWORD) failed", valueNameA.chars); + } + return false; + } + return true; +} + +bool ffRegReadUint64(HKEY hKey, const wchar_t* valueNameW, uint64_t* result, FFstrbuf* error) +{ + DWORD bufSize = sizeof(*result); + if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_QWORD, NULL, result, &bufSize) != ERROR_SUCCESS) + { + if(error) + { + if(!valueNameW) + valueNameW = L"(default)"; + FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW); + ffStrbufAppendF(error, "RegGetValueW(%s, result, RRF_RT_QWORD) failed", valueNameA.chars); + } + return false; + } + return true; +} diff --git a/src/util/windows/registry.h b/src/util/windows/registry.h index e21dfdb66..d9eb67666 100644 --- a/src/util/windows/registry.h +++ b/src/util/windows/registry.h @@ -18,5 +18,6 @@ static inline void wrapRegCloseKey(HKEY* phKey) bool ffRegOpenKeyForRead(HKEY hKey, const wchar_t* subKeyW, HKEY* result, FFstrbuf* error); bool ffRegReadStrbuf(HKEY hKey, const wchar_t* valueNameW, FFstrbuf* result, FFstrbuf* error); bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error); +bool ffRegReadUint64(HKEY hKey, const wchar_t* valueNameW, uint64_t* result, FFstrbuf* error); #endif From 749bd8db0e6fdcce5311c0c4864165aa4d061813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 5 Feb 2023 21:42:59 +0800 Subject: [PATCH 082/119] Gamepad (Windows): display attached controllers only --- src/detection/gamepad/gamepad_windows.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/detection/gamepad/gamepad_windows.cpp b/src/detection/gamepad/gamepad_windows.cpp index c30ef9fe4..3d9345423 100644 --- a/src/detection/gamepad/gamepad_windows.cpp +++ b/src/detection/gamepad/gamepad_windows.cpp @@ -17,16 +17,16 @@ CALLBACK BOOL DIEnumDevicesCallback(LPCDIDEVICEINSTANCEA lpddi, LPVOID pvRef) lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]); ffStrbufInitS(&device->name, lpddi->tszInstanceName); - return DIENUM_CONTINUE; + return DIENUM_CONTINUE; } extern "C" const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */) { - IDirectInput8A* dinput; - if (!SUCCEEDED(DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8A, (void**)&dinput, NULL))) + IDirectInput8A* dinput; + if (!SUCCEEDED(DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8A, (void**)&dinput, NULL))) return "DirectInput8Create() failed"; - dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, devices, DIEDFL_ALLDEVICES); - dinput->Release(); + dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, devices, DIEDFL_ATTACHEDONLY); + dinput->Release(); return NULL; } From edf4837ed6a75a928f11fdf2aa6de533ddc979e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 6 Feb 2023 11:07:49 +0800 Subject: [PATCH 083/119] GPU: refactor vendor detection code --- src/detection/gpu/gpu.c | 34 +++++++++++++++++++++++++++---- src/detection/gpu/gpu.h | 10 +++++---- src/detection/gpu/gpu_apple.c | 22 ++++---------------- src/detection/gpu/gpu_linux.c | 23 ++++----------------- src/detection/gpu/gpu_windows.cpp | 19 +++-------------- 5 files changed, 47 insertions(+), 61 deletions(-) diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 420b6a124..89d551e1e 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -2,15 +2,41 @@ #include "detection/internal.h" #include "detection/vulkan.h" -void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance); +const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance); + +const char* FF_GPU_VENDOR_NAME_APPLE = "Apple"; +const char* FF_GPU_VENDOR_NAME_AMD = "AMD"; +const char* FF_GPU_VENDOR_NAME_INTEL = "Intel"; +const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA"; + +static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsigned length) +{ + for (unsigned i = 0; i < length; ++i) + { + if (arr[i] == vendorId) + return true; + } + return false; +} + +const char* ffGetGPUVendorString(unsigned vendorId) +{ + if(vendorId == 0x106b) + return FF_GPU_VENDOR_NAME_APPLE; + if(arrayContains((const unsigned[]) {0x1002, 0x1022}, vendorId, 2)) + return FF_GPU_VENDOR_NAME_AMD; + else if(arrayContains((const unsigned[]) {0x03e7, 0x8086, 0x8087}, vendorId, 3)) + return FF_GPU_VENDOR_NAME_INTEL; + else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3)) + return FF_GPU_VENDOR_NAME_NVIDIA; + return NULL; +} const FFlist* ffDetectGPU(const FFinstance* instance) { FF_DETECTION_INTERNAL_GUARD(FFlist, ffListInit(&result, sizeof(FFGPUResult)); - ffDetectGPUImpl(&result, instance); - - if(result.length == 0) + if(ffDetectGPUImpl(&result, instance) != NULL) { const FFVulkanResult* vulkan = ffDetectVulkan(instance); result = vulkan->gpus; diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index e14feb9d8..177ca2e31 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -8,10 +8,10 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 -#define FF_GPU_VENDOR_NAME_APPLE "Apple" -#define FF_GPU_VENDOR_NAME_AMD "AMD" -#define FF_GPU_VENDOR_NAME_INTEL "Intel" -#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA" +extern const char* FF_GPU_VENDOR_NAME_APPLE; +extern const char* FF_GPU_VENDOR_NAME_AMD; +extern const char* FF_GPU_VENDOR_NAME_INTEL; +extern const char* FF_GPU_VENDOR_NAME_NVIDIA; typedef enum FFGpuType { @@ -32,4 +32,6 @@ typedef struct FFGPUResult const FFlist* ffDetectGPU(const FFinstance* instance); +const char* ffGetGPUVendorString(unsigned vendorId); + #endif diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 413e65746..2bea79896 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -66,26 +66,12 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) int vendorId; if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId)) { - if(vendorId == 0x106b) - { - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); + const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId); + ffStrbufAppendS(&gpu->vendor, vendorStr); + if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL) gpu->type = FF_GPU_TYPE_INTEGRATED; - } - else if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2)) - { - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - gpu->type = FF_GPU_TYPE_DISCRETE; // Apple never used AMD CPUs - } - else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3)) - { - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - gpu->type = FF_GPU_TYPE_INTEGRATED; - } - else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3)) - { - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD) gpu->type = FF_GPU_TYPE_DISCRETE; - } } ffStrbufInit(&gpu->driver); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 549d8ed40..ae7239d43 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -24,25 +24,9 @@ typedef struct PCIData #endif } PCIData; -static bool pciIDsContains(u16 searched, const u16* ids) -{ - while(*ids != 0) - { - if(*ids == searched) - return true; - ids++; - } - return false; -} - static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) { - if(pciIDsContains(device->vendor_id, (const u16[]) {0x1002, 0x1022, 0})) - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - else if(pciIDsContains(device->vendor_id, (const u16[]) {0x03e7, 0x8086, 0x8087, 0})) - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if(pciIDsContains(device->vendor_id, (const u16[]) {0x0955, 0x10de, 0x12d2, 0})) - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(device->vendor_id)); if(gpu->vendor.length > 0) return; @@ -270,11 +254,12 @@ static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus) #endif -void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) +const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) { #ifdef FF_HAVE_LIBPCI - pciDetectGPUs(instance, gpus); + return pciDetectGPUs(instance, gpus); #else FF_UNUSED(gpus, instance); + return "fastfetch is built without libpci support"; #endif } diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index ccfd187a7..8788aa1e6 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -51,14 +51,7 @@ static const char* detectWithRegistry(FFlist* gpus) uint32_t vendorId; if(ffRegReadUint(hSubKey, L"VendorId", &vendorId, nullptr)) - { - if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2)) - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3)) - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3)) - ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); - } + ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(vendorId)); uint64_t dedicatedVideoMemory; if(ffRegReadUint64(hSubKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, nullptr)) @@ -88,14 +81,8 @@ static const char* detectWithDxgi(FFlist* gpus) FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)desc.VendorId, 2)) - ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)desc.VendorId, 3)) - ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)desc.VendorId, 3)) - ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); - else - ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->vendor); + ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(desc.VendorId)); ffStrbufInit(&gpu->name); ffStrbufSetWS(&gpu->name, desc.Description); From 7a5da23b0c4382a66f5c0537e6215fef375836e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 6 Feb 2023 14:45:38 +0800 Subject: [PATCH 084/119] Bluetooth: silense compiler warnings --- src/detection/bluetooth/bluetooth_linux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index 82aba4e77..bcfca6e7d 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -197,6 +197,7 @@ void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* blueto #ifdef FF_HAVE_DBUS ffStrbufAppendS(&bluetooth->error, detectBluetooth(instance, bluetooth)); #else + FF_UNUSED(instance); ffStrbufAppendS(&bluetooth->error, "Fastfetch was compiled without DBus support"); #endif } From e98489a74b653646084ae3fce4287abd192d155f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 6 Feb 2023 14:45:45 +0800 Subject: [PATCH 085/119] Locale: tweaks --- src/detection/locale/locale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/locale/locale.c b/src/detection/locale/locale.c index 7b9e085cf..e2f27a214 100644 --- a/src/detection/locale/locale.c +++ b/src/detection/locale/locale.c @@ -5,7 +5,7 @@ #include #include -__attribute__((__unused__)) +FF_MAYBE_UNUSED static void getLocaleFromEnv(FFstrbuf* locale) { ffStrbufAppendS(locale, getenv("LANG")); From 7a691a42864dd92be445dd64643082fbbfb0d57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 15 Jan 2023 16:54:31 +0800 Subject: [PATCH 086/119] Windows: add 32bit support --- .github/workflows/push.yml | 89 +++++++++++++++++++++-- CHANGELOG.md | 5 ++ src/common/library.h | 14 ++++ src/detection/terminalfont/terminalfont.c | 18 ++--- src/detection/vulkan.c | 10 +-- 5 files changed, 115 insertions(+), 21 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index cc50f09b5..1a99f1221 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -165,8 +165,8 @@ jobs: name: fastfetch-freebsd path: ./fastfetch-*.* - windows: - name: Windows + win64: + name: Win64 runs-on: windows-latest permissions: security-events: write @@ -234,13 +234,87 @@ jobs: run: ctest - name: create zip archive - run: zip fastfetch-$(./fastfetch --version-raw)-Windows.zip *.dll fastfetch.exe flashfetch.exe + run: zip fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe - name: upload artifacts uses: actions/upload-artifact@v3 with: - name: fastfetch-windows - path: ./fastfetch-*-Windows.zip + name: fastfetch-win64 + path: ./fastfetch-*-Win64.zip + + win32: + name: Win32 + runs-on: windows-latest + permissions: + security-events: write + contents: read + defaults: + run: + shell: msys2 {0} + steps: + - name: checkout repository + uses: actions/checkout@v3 + + - name: setup-msys2 + uses: msys2/setup-msys2@v2 + with: + msystem: CLANG32 + update: true + install: git zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-cjson mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd + + - name: print msys version + run: uname -a + + # https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785 + - name: create OpenCL.pc + run: | + cat > /clang32/lib/pkgconfig/OpenCL.pc << EOF + prefix=/clang32 + exec_prefix=${prefix} + libdir=${exec_prefix}/lib + includedir=${prefix}/include + + Name: OpenCL + Description: Open Computing Language generic Installable Client Driver Loader + Version: 2022.09.30-1 + Libs: -L${libdir} -lOpenCL.dll + Cflags: -I${includedir} + EOF + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: c, cpp + + - name: configure project + run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + + - name: build project + run: cmake --build . + + - name: perform CodeQL analysis + uses: github/codeql-action/analyze@v2 + + - name: copy necessary dlls + run: cp /clang32/bin/{libcjson,libOpenCL,vulkan-1}.dll . + + - name: run fastfetch + run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all + + - name: run flashfetch + run: time ./flashfetch + + - name: run tests + run: ctest + + - name: create zip archive + run: zip fastfetch-$(./fastfetch --version-raw)-win32.zip *.dll fastfetch.exe flashfetch.exe + + - name: upload artifacts + uses: actions/upload-artifact@v3 + with: + name: fastfetch-win32 + path: ./fastfetch-*-win32.zip release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch' @@ -250,7 +324,8 @@ jobs: - linux - macos - freebsd - - windows + - win64 + - win32 permissions: contents: write steps: @@ -270,4 +345,4 @@ jobs: tag: ${{ needs.linux.outputs.ffversion }} commit: ${{ github.sha }} artifactErrorsFailBuild: true - artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/* + artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-win64/*,fastfetch-win32/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eb3331e7..dffee431f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # dev +Notable Changes: + +* With the support of Win32 platform, original Windows 64bit artifact file is renamed to Win64 to avoid possible confusion + Features: * Bluetooth module * Sound module @@ -7,6 +11,7 @@ Features: * Support colored percentage numbers output (#409) * Support `--localip-compact-type` option (#408) * Terminator terminal font detection (@Zerogiven, #415) +* Windows 32bit compatibility Bugfixes: diff --git a/src/common/library.h b/src/common/library.h index c23aa7b53..c433d1e81 100644 --- a/src/common/library.h +++ b/src/common/library.h @@ -40,6 +40,14 @@ return returnValue; \ } +#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, symbolMapping, symbolName, alternateName, returnValue) \ + symbolMapping = dlsym(library, #symbolName); \ + if(symbolMapping == NULL && !(symbolMapping = dlsym(library, #alternateName))) \ + { \ + dlclose(library); \ + return returnValue; \ + } + #define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \ __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue); @@ -49,12 +57,18 @@ #define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \ __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed"); +#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(library, symbolName, alternateName) \ + __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed"); + #define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \ FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, returnValue); #define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \ FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, "dlsym " #symbolName " failed"); +#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(library, varName, symbolName, alternateName) \ + FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, varName.ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed"); + #define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \ FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName->ff ## symbolName, symbolName, returnValue); diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index e8a6fb58b..40275314c 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -115,15 +115,15 @@ static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* conten CJSONData cjsonData; FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_Parse, cJSON_Parse@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsObject, cJSON_IsObject@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive, cJSON_GetObjectItemCaseSensitive@8) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsString, cJSON_IsString@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_GetStringValue, cJSON_GetStringValue@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsNumber, cJSON_IsNumber@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_GetNumberValue, cJSON_GetNumberValue@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_IsArray, cJSON_IsArray@4) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(libcjson, cjsonData, cJSON_Delete, cJSON_Delete@4) const char* error = NULL; diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index b6ccd0698..93d5ea2da 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -46,11 +46,11 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu "libvulkan"FF_LIBRARY_EXTENSION, 2, "vulkan-1"FF_LIBRARY_EXTENSION, -1 #endif ) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkCreateInstance) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkDestroyInstance) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkEnumeratePhysicalDevices) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetPhysicalDeviceProperties) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetInstanceProcAddr, vkGetInstanceProcAddr@8) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkCreateInstance, vkCreateInstance@12) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkDestroyInstance, vkDestroyInstance@8) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkEnumeratePhysicalDevices, vkEnumeratePhysicalDevices@12) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceProperties@8) //Some drivers (nvdc) print messages to stdout //and thats the best way i found to disable that From 92c744d971ee513fdc4a78fcffe18d6f0db8e733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 6 Feb 2023 22:45:55 +0800 Subject: [PATCH 087/119] Windows: support for global config path in MSYS2 environment --- src/util/platform/FFPlatform_windows.c | 29 ++++++++++---------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index d264926b1..60e4249b4 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -69,40 +69,33 @@ static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* static void getConfigDirs(FFPlatform* platform) { - ffListInit(&platform->configDirs, sizeof(FFstrbuf)); - - ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME"); - ffPlatformPathAddHome(&platform->configDirs, platform, "/.config/"); - platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_RoamingAppData); - platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_LocalAppData); - ffPlatformPathAddHome(&platform->configDirs, platform, ""); - - if(getenv("MSYSTEM") && getenv("HOME")) + if(getenv("MSYSTEM")) { // We are in MSYS2 / Git Bash platformPathAddEnvSuffix(&platform->configDirs, "HOME", ".config/"); platformPathAddEnvSuffix(&platform->configDirs, "HOME", ""); + platformPathAddEnvSuffix(&platform->configDirs, "MINGW_PREFIX", "etc"); } - ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS"); + ffPlatformPathAddHome(&platform->configDirs, platform, ".config/"); + platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_RoamingAppData); + platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_LocalAppData); + ffPlatformPathAddHome(&platform->configDirs, platform, ""); } static void getDataDirs(FFPlatform* platform) { - ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME"); - ffPlatformPathAddHome(&platform->dataDirs, platform, "/.local/share/"); - platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData); - platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData); - ffPlatformPathAddHome(&platform->dataDirs, platform, ""); - if(getenv("MSYSTEM") && getenv("HOME")) { // We are in MSYS2 / Git Bash platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ".local/share/"); platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ""); + platformPathAddEnvSuffix(&platform->dataDirs, "MINGW_PREFIX", "share"); } - - ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); + ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/"); + platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData); + platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData); + ffPlatformPathAddHome(&platform->dataDirs, platform, ""); } static void getUserName(FFPlatform* platform) From 82b10a527b991e358c937f3e33e88bca3cc076b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 7 Feb 2023 11:03:09 +0800 Subject: [PATCH 088/119] GPU: support driver version detection --- CHANGELOG.md | 2 ++ src/detection/gpu/gpu.h | 1 + src/detection/gpu/gpu_windows.cpp | 11 +++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dffee431f..47a9f1a7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ Features: * Support `--localip-compact-type` option (#408) * Terminator terminal font detection (@Zerogiven, #415) * Windows 32bit compatibility +* Support global configuration in MSYS2 environment (Windows) +* Support GPU driver version detection on Windows 11 Bugfixes: diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 177ca2e31..5d38ca1ac 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -27,6 +27,7 @@ typedef struct FFGPUResult FFstrbuf name; FFstrbuf driver; double temperature; + uint64_t memory; int coreCount; } FFGPUResult; diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 8788aa1e6..d52984a0d 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -6,6 +6,7 @@ extern "C" { #include #include +#include static const char* detectWithRegistry(FFlist* gpus) { @@ -13,11 +14,11 @@ static const char* detectWithRegistry(FFlist* gpus) FF_HKEY_AUTO_DESTROY hKey = NULL; if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\DirectX", &hKey, nullptr)) - return "Open \"SOFTWARE\\Microsoft\\DirectX\" failed"; + return "Open \"HKLM\\SOFTWARE\\Microsoft\\DirectX\" failed"; uint64_t lastSeen; if(!ffRegReadUint64(hKey, L"LastSeen", &lastSeen, nullptr)) - return "Read \"SOFTWARE\\Microsoft\\DirectX\\LastSeen\" failed"; + return "Read \"HKLM\\SOFTWARE\\Microsoft\\DirectX\\LastSeen\" failed"; DWORD index = 0; wchar_t subKeyName[64]; @@ -55,9 +56,11 @@ static const char* detectWithRegistry(FFlist* gpus) uint64_t dedicatedVideoMemory; if(ffRegReadUint64(hSubKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, nullptr)) - { gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - } + + uint64_t driverVersion; + if(ffRegReadUint64(hSubKey, L"DriverVersion", &driverVersion, nullptr)) + ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64, (driverVersion >> 16) & 0xFFFF, driverVersion & 0xFFFF); } return nullptr; From 6c22fd690290ae5701e69123b0454376db58a28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 7 Feb 2023 14:16:53 +0800 Subject: [PATCH 089/119] Host: update newest product name data (macOS) --- CHANGELOG.md | 1 + src/detection/host/host_apple.c | 26 +++++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a9f1a7a..d41113244 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Other: * Simplified wmtheme output format (Windows) * Improved GPU detection performance on Windows 11 +* Lastest Mac model identifier support (macOS) # 1.9.1 diff --git a/src/detection/host/host_apple.c b/src/detection/host/host_apple.c index d768d83e4..4f739276b 100644 --- a/src/detection/host/host_apple.c +++ b/src/detection/host/host_apple.c @@ -8,7 +8,13 @@ static inline bool strEqual(const char* a, const char* b) static const char* getProductName(const FFstrbuf* hwModel) { - //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L1386 + // Macbook Pro: https://support.apple.com/en-us/HT201300 + // Macbook Air: https://support.apple.com/en-us/HT201862 + // Mac mini: https://support.apple.com/en-us/HT201894 + // iMac: https://support.apple.com/en-us/HT201634 + // Mac Pro: https://support.apple.com/en-us/HT202888 + // Mac Studio: https://support.apple.com/en-us/HT213073 + if(ffStrbufStartsWithS(hwModel, "MacBookPro")) { const char* version = hwModel->chars + strlen("MacBookPro"); @@ -106,20 +112,26 @@ static const char* getProductName(const FFstrbuf* hwModel) else if(ffStrbufStartsWithS(hwModel, "Mac")) { const char* version = hwModel->chars + strlen("Mac"); + if(strEqual(version, "14,6") || + strEqual(version, "14,10")) return "MacBook Pro (16-inch, 2023)"; + if(strEqual(version, "14,5") || + strEqual(version, "14,9")) return "MacBook Pro (14-inch, 2023)"; + if(strEqual(version, "14,3")) return "Mac mini (M2, 2023, Two Thunderbolt 4 ports)"; + if(strEqual(version, "14,12")) return "Mac mini (M2, 2023, Four Thunderbolt 4 ports)"; if(strEqual(version, "14,7")) return "MacBook Pro (13-inch, M2, 2022)"; if(strEqual(version, "14,2")) return "MacBook Air (M2, 2022)"; - if(strEqual(version, "13,1")) return "Mac Studio (2022, Two USB-C front ports)"; - if(strEqual(version, "13,2")) return "Mac Studio (2022, Two Thunderbolt 4 front ports)"; + if(strEqual(version, "13,1")) return "Mac Studio (M1 Max, 2022, Two USB-C front ports)"; + if(strEqual(version, "13,2")) return "Mac Studio (M1 Ultra, 2022, Two Thunderbolt 4 front ports)"; } else if(ffStrbufStartsWithS(hwModel, "iMac")) { const char* version = hwModel->chars + strlen("iMac"); - if(strEqual(version, "21,1") || - strEqual(version, "21,2")) return "iMac (24-inch, M1, 2021)"; + if(strEqual(version, "21,1")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports, Two USB 3 ports)"; + if(strEqual(version, "21,2")) return "iMac (24-inch, M1, 2021, Two Thunderbolt / USB 4 ports)"; if(strEqual(version, "20,1") || strEqual(version, "20,2")) return "iMac (Retina 5K, 27-inch, 2020)"; - if(strEqual(version, "19,1") || - strEqual(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)"; + if(strEqual(version, "19,1")) return "iMac (Retina 5K, 27-inch, 2019)"; + if(strEqual(version, "19,2")) return "iMac (Retina 4K, 21.5-inch, 2019)"; if(strEqual(version, "Pro1,1")) return "iMac Pro (2017)"; if(strEqual(version, "18,3")) return "iMac (Retina 5K, 27-inch, 2017)"; if(strEqual(version, "18,2")) return "iMac (Retina 4K, 21.5-inch, 2017)"; From ec3f9acd76e5a629a785b93d681ad320f4758f00 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Tue, 7 Feb 2023 12:18:27 +0100 Subject: [PATCH 090/119] Cmake debug: change to exe linker only --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e60e6b26f..94d82611c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,7 +118,7 @@ if(NOT WIN32) set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined") endif() set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}") -set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic") if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") include(CheckIPOSupported) From e563417166813f5379c73be1d8bfa836e4f8a4be Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Tue, 7 Feb 2023 12:21:47 +0100 Subject: [PATCH 091/119] Build test: Build as release with debug info --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 1a99f1221..f5e2feeb5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -26,7 +26,7 @@ jobs: - name: configure project env: CC: ${{ matrix.compiler }} - run: cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBCJSON=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} . + run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBCJSON=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} . - name: build project run: cmake --build . From 8ffe6fda9ba5fc5997f674d87313160318757298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 8 Feb 2023 15:04:35 +0800 Subject: [PATCH 092/119] Battery: drop powrprof.dll dependency --- src/detection/battery/battery_windows.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index ca8c60991..ce1838613 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -8,6 +8,19 @@ #include #include +#ifdef FF_USE_WIN_NTAPI + NTSYSCALLAPI + NTSTATUS + NTAPI + NtPowerInformation( + IN POWER_INFORMATION_LEVEL InformationLevel, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength); + #define CallNtPowerInformation NtPowerInformation +#endif + static inline void wrapCloseHandle(HANDLE* handle) { if(*handle) From 9a7c73255516f612fa1b511af07378fab6e416b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 8 Feb 2023 21:07:36 +0800 Subject: [PATCH 093/119] OpenCL: fix Windows support They changed the dll file name in the latest release --- .github/workflows/push.yml | 36 ++---------------------------------- src/modules/opencl.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index f5e2feeb5..f1bbf2b83 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -188,22 +188,6 @@ jobs: - name: print msys version run: uname -a - # https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785 - - name: create OpenCL.pc - run: | - cat > /clang64/lib/pkgconfig/OpenCL.pc << EOF - prefix=/clang64 - exec_prefix=${prefix} - libdir=${exec_prefix}/lib - includedir=${prefix}/include - - Name: OpenCL - Description: Open Computing Language generic Installable Client Driver Loader - Version: 2022.09.30-1 - Libs: -L${libdir} -lOpenCL.dll - Cflags: -I${includedir} - EOF - - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: @@ -219,7 +203,7 @@ jobs: uses: github/codeql-action/analyze@v2 - name: copy necessary dlls - run: cp /clang64/bin/{libcjson,libOpenCL,vulkan-1}.dll . + run: cp /clang64/bin/{libcjson,OpenCL,vulkan-1}.dll . - name: list features run: ./fastfetch --list-features @@ -265,22 +249,6 @@ jobs: - name: print msys version run: uname -a - # https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785 - - name: create OpenCL.pc - run: | - cat > /clang32/lib/pkgconfig/OpenCL.pc << EOF - prefix=/clang32 - exec_prefix=${prefix} - libdir=${exec_prefix}/lib - includedir=${prefix}/include - - Name: OpenCL - Description: Open Computing Language generic Installable Client Driver Loader - Version: 2022.09.30-1 - Libs: -L${libdir} -lOpenCL.dll - Cflags: -I${includedir} - EOF - - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: @@ -296,7 +264,7 @@ jobs: uses: github/codeql-action/analyze@v2 - name: copy necessary dlls - run: cp /clang32/bin/{libcjson,libOpenCL,vulkan-1}.dll . + run: cp /clang32/bin/{libcjson,OpenCL,vulkan-1}.dll . - name: run fastfetch run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all diff --git a/src/modules/opencl.c b/src/modules/opencl.c index 18e826317..60bcd2058 100644 --- a/src/modules/opencl.c +++ b/src/modules/opencl.c @@ -24,7 +24,7 @@ typedef struct OpenCLData FF_LIBRARY_SYMBOL(clGetDeviceInfo) } OpenCLData; -static const char* openCLHandelData(FFinstance* instance, OpenCLData* data) +static const char* openCLHandleData(FFinstance* instance, OpenCLData* data) { cl_platform_id platformID; cl_uint numPlatforms; @@ -84,12 +84,17 @@ static const char* printOpenCL(FFinstance* instance) { OpenCLData data; - FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", "libOpenCL"FF_LIBRARY_EXTENSION, 1); + FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", + #ifdef _WIN32 + "OpenCL"FF_LIBRARY_EXTENSION, -1, + #endif + "libOpenCL"FF_LIBRARY_EXTENSION, 1 + ); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); - const char* error = openCLHandelData(instance, &data); + const char* error = openCLHandleData(instance, &data); dlclose(opencl); return error; } @@ -103,7 +108,7 @@ static const char* printOpenCL(FFinstance* instance) data.ffclGetDeviceIDs = clGetDeviceIDs; data.ffclGetDeviceInfo = clGetDeviceInfo; - return openCLHandelData(instance, &data); + return openCLHandleData(instance, &data); } #endif // __APPLE__ From 5c4627189814a90df85f064159265051972527b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 8 Feb 2023 21:23:45 +0800 Subject: [PATCH 094/119] GPU (Windows): fix driver version detection --- src/detection/gpu/gpu_windows.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index d52984a0d..49d0b3e7e 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -60,7 +60,13 @@ static const char* detectWithRegistry(FFlist* gpus) uint64_t driverVersion; if(ffRegReadUint64(hSubKey, L"DriverVersion", &driverVersion, nullptr)) - ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64, (driverVersion >> 16) & 0xFFFF, driverVersion & 0xFFFF); + { + ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64 ".%" PRIu64 ".%" PRIu64, + (driverVersion >> 48) & 0xFFFF, + (driverVersion >> 32) & 0xFFFF, + (driverVersion >> 16) & 0xFFFF, + (driverVersion >> 0) & 0xFFFF); + } } return nullptr; From 03d1c627876bd04cff7bdeab9b15a854864059c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 8 Feb 2023 22:49:30 +0800 Subject: [PATCH 095/119] Packages (Windows): honor $SCOOP when detecting scoop packages Fix #417 --- src/detection/packages/packages_windows.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index afd016c6d..f62bc9d97 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -1,4 +1,5 @@ #include "packages.h" +#include "util/stringUtils.h" #include #include @@ -27,10 +28,21 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix * static void detectScoop(const FFinstance* instance, FFPackagesResult* result) { - char scoopPath[MAX_PATH + 3]; - strcpy(scoopPath, instance->state.platform.homeDir.chars); - strncat(scoopPath, "/scoop/apps/*", sizeof(scoopPath) - 1 - strlen(scoopPath)); - result->scoop = getNumElements(scoopPath, FILE_ATTRIBUTE_DIRECTORY); + FF_STRBUF_AUTO_DESTROY scoopPath; + ffStrbufInitA(&scoopPath, MAX_PATH + 3); + + const char* scoopEnv = getenv("SCOOP"); + if(ffStrSet(scoopEnv)) + { + ffStrbufAppendS(&scoopPath, scoopEnv); + ffStrbufAppendS(&scoopPath, "/apps/*"); + } + else + { + ffStrbufAppendS(&scoopPath, instance->state.platform.homeDir.chars); + ffStrbufAppendS(&scoopPath, "/scoop/apps/*"); + } + result->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY); if(result->scoop > 0) result->scoop--; // scoop } From 878d4608b1d8043cc7431bf4142550eb607fecf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 9 Feb 2023 00:15:35 +0800 Subject: [PATCH 096/119] Packages (Windows): fix scoop packages count in non-default install path --- src/detection/packages/packages_windows.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index f62bc9d97..46a36dc46 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -4,7 +4,7 @@ #include #include -static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type) +static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type, const char* ignore) { uint32_t counter = 0; WIN32_FIND_DATAA wfd; @@ -14,8 +14,9 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix * { do // Managed to locate and create an handle to that folder. { - if(wfd.dwFileAttributes & type) - counter++; + if(!(wfd.dwFileAttributes & type)) continue; + if(ignore != NULL && strcasecmp(ignore, wfd.cFileName) == 0) continue; + counter++; } while (FindNextFileA(hFind, &wfd)); FindClose(hFind); @@ -42,9 +43,7 @@ static void detectScoop(const FFinstance* instance, FFPackagesResult* result) ffStrbufAppendS(&scoopPath, instance->state.platform.homeDir.chars); ffStrbufAppendS(&scoopPath, "/scoop/apps/*"); } - result->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY); - if(result->scoop > 0) - result->scoop--; // scoop + result->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop"); } static void detectChoco(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result) @@ -56,9 +55,7 @@ static void detectChoco(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesRe char chocoPath[MAX_PATH + 3]; strcpy(chocoPath, chocoInstall); strncat(chocoPath, "/lib/*", sizeof(chocoPath) - 1 - strlen(chocoPath)); - result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY); - if(result->choco > 0) - result->choco--; // choco + result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco"); } static void detectPacman(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result) @@ -71,7 +68,7 @@ static void detectPacman(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesR char pacmanPath[MAX_PATH + 3]; strcpy(pacmanPath, msystemPrefix); strncat(pacmanPath, "/../var/lib/pacman/local/*", sizeof(pacmanPath) - 1 - strlen(pacmanPath)); - result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY); + result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL); } void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result) From 51cc87e0db559a5889760e6bae6a3a7a5b0f8979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 9 Feb 2023 00:17:13 +0800 Subject: [PATCH 097/119] GPU (Windows): keep WMI query as a slow operation for accurate results --- src/detection/gpu/gpu_windows.cpp | 38 ++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 49d0b3e7e..4146fc53e 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -3,6 +3,7 @@ extern "C" { #include "util/windows/unicode.h" #include "util/windows/registry.h" } +#include "util/windows/wmi.hpp" #include #include @@ -111,10 +112,45 @@ static const char* detectWithDxgi(FFlist* gpus) return nullptr; } +static const char* detectWithWmi(FFlist* gpus) +{ + FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr); + if(!query) + return "Query WMI service failed"; + + while(FFWmiRecord record = query.next()) + { + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + + gpu->type = FF_GPU_TYPE_UNKNOWN; + + ffStrbufInit(&gpu->vendor); + record.getString(L"AdapterCompatibility", &gpu->vendor); + if(ffStrbufStartsWithS(&gpu->vendor, "Intel ")) + { + //Intel returns "Intel Corporation", not sure about AMD + ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + } + + ffStrbufInit(&gpu->name); + record.getString(L"Name", &gpu->name); + + ffStrbufInit(&gpu->driver); + record.getString(L"DriverVersion", &gpu->driver); + + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + } + + return nullptr; +} + extern "C" const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance) { - if (!detectWithRegistry(gpus)) + if (instance->config.allowSlowOperations) + detectWithWmi(gpus); + else if (!detectWithRegistry(gpus)) return nullptr; return detectWithDxgi(gpus); } From 532b493c42f036b5d6f7a06bf9ad80228aec1f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 9 Feb 2023 00:19:19 +0800 Subject: [PATCH 098/119] Doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d41113244..49e06ed50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Bugfixes: * Fix a rare case that fails to detect terminal * Fix Muffin detection (@Zerogiven, #411) * Fix IPv6 detection (Windows) +* Fix scoop package count detection when scoop is installed in non-default path (Windows, #417) Other: From ff170caff69c4a39a035a256673b49f55fa5137b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 9 Feb 2023 09:46:53 +0800 Subject: [PATCH 099/119] GPU (Windows): fix duplicated entries. --- src/detection/gpu/gpu_windows.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 4146fc53e..8e6d74ef2 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -149,8 +149,9 @@ extern "C" const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance) { if (instance->config.allowSlowOperations) - detectWithWmi(gpus); - else if (!detectWithRegistry(gpus)) + return detectWithWmi(gpus); + + if (!detectWithRegistry(gpus)) return nullptr; return detectWithDxgi(gpus); } From 3a9403a2f153f70419297bf21334a849a6ed54ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 9 Feb 2023 09:51:51 +0800 Subject: [PATCH 100/119] Packages (Windows): optimise --- src/detection/packages/packages_windows.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index 46a36dc46..086a10ea1 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -7,6 +7,7 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type, const char* ignore) { uint32_t counter = 0; + bool flag = ignore == NULL; WIN32_FIND_DATAA wfd; HANDLE hFind = FindFirstFileA(searchPath, &wfd); @@ -15,7 +16,11 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix * do // Managed to locate and create an handle to that folder. { if(!(wfd.dwFileAttributes & type)) continue; - if(ignore != NULL && strcasecmp(ignore, wfd.cFileName) == 0) continue; + if(!flag && strcasecmp(ignore, wfd.cFileName) == 0) + { + flag = true; + continue; + } counter++; } while (FindNextFileA(hFind, &wfd)); FindClose(hFind); From fcc5170a108fe7ce7c1cd5e31e06fa4dc9c6d76c Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 9 Feb 2023 11:20:37 +0100 Subject: [PATCH 101/119] Disk(Linux): Better detection of physical drives --- src/detection/disk/disk_linux.c | 45 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index c15eea812..7e6a1bc0b 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -15,28 +15,35 @@ #define readdir readdir64 #endif -static bool isPhysicalDevice(const char* device) +static bool isPhysicalDevice(FFstrbuf* device) { + struct stat deviceStat; + if(stat(device->chars, &deviceStat) != 0) + return false; + + //Ignore all devices that are not block devices + if(!S_ISBLK(deviceStat.st_mode)) + return false; + + //Ignore all devices that are not physical devices + + //DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem. - if(strcmp(device, "drvfs") == 0) + if(ffStrbufEqualS(device, "drvfs")) return true; //ZFS root pool. The format is rpool/// - if(strncmp(device, "rpool/", 6) == 0) + if(ffStrbufStartsWithS(device, "rpool/")) return true; //Pseudo filesystems don't have a device in /dev - const char* devPrefix = "/dev/"; - if(strncmp(device, devPrefix, strlen(devPrefix)) != 0) + if(!ffStrbufStartsWithS(device, "/dev/")) return false; - //Skip /dev/ prefix - device += strlen(devPrefix); - if( - strncmp(device, "loop", 4) == 0 || //Ignore loop devices - strncmp(device, "ram", 3) == 0 || //Ignore ram devices - strncmp(device, "fd", 2) == 0 //Ignore fd devices + ffStrbufStartsWithS(device, "/dev/loop") || //Ignore loop devices + ffStrbufStartsWithS(device, "/dev/ram") || //Ignore ram devices + ffStrbufStartsWithS(device, "/dev/fd") //Ignore fd devices ) return false; return true; @@ -208,12 +215,6 @@ void ffDetectDisksImpl(FFDiskResult* disks) while(getline(&line, &len, mountsFile) != EOF) { - if(!isPhysicalDevice(line)) - continue; - - //We have a valid device, add it to the list - FFDisk* disk = ffListAdd(&disks->disks); - //Format of the file: " ..." (Same as fstab) char* currentPos = line; @@ -222,6 +223,16 @@ void ffDetectDisksImpl(FFDiskResult* disks) ffStrbufInit(device); appendNextEntry(device, ¤tPos); + if(!isPhysicalDevice(device)) + { + ffStrbufDestroy(device); + devices.length--; + continue; + } + + //We have a valid device, add it to the list + FFDisk* disk = ffListAdd(&disks->disks); + //detect mountpoint ffStrbufInit(&disk->mountpoint); appendNextEntry(&disk->mountpoint, ¤tPos); From 74a68aa62683d97ec285631d253753c0877148cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 10 Feb 2023 11:08:05 +0800 Subject: [PATCH 102/119] CMake: remove unused options --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94d82611c..95b3a447d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,6 @@ cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF) cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF) -cmake_dependent_option(USE_WIN_GPU_DXGI "Use DXGI to detect GPUs instead of WMI. Faster, but may ignore GPUs that only support DX9" ON "WIN32" OFF) option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds From f05d134aa702e656fe83f796e4966092a93f25cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 10 Feb 2023 11:20:27 +0800 Subject: [PATCH 103/119] OpenCL: tidy --- src/modules/opencl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/opencl.c b/src/modules/opencl.c index 60bcd2058..8f1f69cd1 100644 --- a/src/modules/opencl.c +++ b/src/modules/opencl.c @@ -11,10 +11,10 @@ #include #define CL_TARGET_OPENCL_VERSION 100 -#ifdef __APPLE__ - #include -#else +#ifdef FF_HAVE_OPENCL #include +#else + #include #endif typedef struct OpenCLData @@ -99,7 +99,7 @@ static const char* printOpenCL(FFinstance* instance) return error; } -#elif __APPLE__ // FF_HAVE_OPENCL +#elif defined(__APPLE__) // FF_HAVE_OPENCL static const char* printOpenCL(FFinstance* instance) { @@ -111,7 +111,7 @@ static const char* printOpenCL(FFinstance* instance) return openCLHandleData(instance, &data); } -#endif // __APPLE__ +#endif // FF_HAVE_OPENCL void ffPrintOpenCL(FFinstance* instance) { From b90d543afcf4615e12f5baf7fa2e516bad007327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 11 Feb 2023 02:29:26 +0800 Subject: [PATCH 104/119] GPU (Windows): support vmem total / usage detection #416 vmem usage detection is guarded behind `--allow-slow-operations` because it's really slow sometimes --- src/detection/gpu/gpu.h | 9 ++++- src/detection/gpu/gpu_apple.c | 2 + src/detection/gpu/gpu_linux.c | 3 ++ src/detection/gpu/gpu_windows.cpp | 67 +++++++++++++++++++------------ src/detection/vulkan.c | 6 ++- src/modules/gpu.c | 24 +++++++++-- 6 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 5d38ca1ac..15b2de74b 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -7,6 +7,7 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 +#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -15,20 +16,24 @@ extern const char* FF_GPU_VENDOR_NAME_NVIDIA; typedef enum FFGpuType { + FF_GPU_TYPE_UNKNOWN, FF_GPU_TYPE_INTEGRATED, FF_GPU_TYPE_DISCRETE, - FF_GPU_TYPE_UNKNOWN } FFGpuType; typedef struct FFGPUResult { + uint64_t id; FFGpuType type; FFstrbuf vendor; FFstrbuf name; FFstrbuf driver; double temperature; - uint64_t memory; int coreCount; + uint64_t dedicatedTotal; + uint64_t dedicatedUsed; + uint64_t sharedTotal; + uint64_t sharedUsed; } FFGPUResult; const FFlist* ffDetectGPU(const FFinstance* instance); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 2bea79896..bc571d7e2 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -60,6 +60,8 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) FFGPUResult* gpu = ffListAdd(gpus); + gpu->id = 0; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; ffStrbufInit(&gpu->vendor); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index ae7239d43..19f4b455a 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -199,6 +199,9 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData FFGPUResult* gpu = ffListAdd(results); + gpu->id = 0; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + ffStrbufInit(&gpu->vendor); pciDetectVendorName(gpu, pci, device); diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 8e6d74ef2..587ca96e0 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -48,6 +48,10 @@ static const char* detectWithRegistry(FFlist* gpus) gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->id = 0; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + + ffRegReadUint64(hSubKey, L"AdapterLuid", &gpu->id, nullptr); ffRegReadStrbuf(hSubKey, L"Description", &gpu->name, nullptr); @@ -55,10 +59,18 @@ static const char* detectWithRegistry(FFlist* gpus) if(ffRegReadUint(hSubKey, L"VendorId", &vendorId, nullptr)) ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(vendorId)); - uint64_t dedicatedVideoMemory; + uint64_t dedicatedVideoMemory = 0; if(ffRegReadUint64(hSubKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, nullptr)) gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + uint64_t dedicatedSystemMemory, sharedSystemMemory; + if(ffRegReadUint64(hSubKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, nullptr) && + ffRegReadUint64(hSubKey, L"SharedSystemMemory", &sharedSystemMemory, nullptr)) + { + gpu->dedicatedTotal = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->sharedTotal = sharedSystemMemory; + } + uint64_t driverVersion; if(ffRegReadUint64(hSubKey, L"DriverVersion", &driverVersion, nullptr)) { @@ -90,16 +102,21 @@ static const char* detectWithDxgi(FFlist* gpus) continue; FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; ffStrbufInit(&gpu->vendor); ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(desc.VendorId)); + gpu->id = (uint64_t&)desc.AdapterLuid; + ffStrbufInit(&gpu->name); ffStrbufSetWS(&gpu->name, desc.Description); ffStrbufInit(&gpu->driver); gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + gpu->dedicatedTotal = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory; + gpu->sharedTotal = desc.SharedSystemMemory; adapter->Release(); @@ -112,46 +129,44 @@ static const char* detectWithDxgi(FFlist* gpus) return nullptr; } -static const char* detectWithWmi(FFlist* gpus) +static const char* detectMemoryUsage(FFlist* gpus) { - FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr); + FFWmiQuery query(L"SELECT Name, DedicatedUsage, SharedUsage FROM Win32_PerfRawData_GPUPerformanceCounters_GPUAdapterMemory", nullptr); if(!query) return "Query WMI service failed"; + FF_STRBUF_AUTO_DESTROY name; + ffStrbufInit(&name); + while(FFWmiRecord record = query.next()) { - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + record.getString(L"Name", &name); // luid_0x00000000_0x000146E8_phys_0 + assert(name.length == strlen("luid_0x00000000_0x000146E8_phys_0")); + ffStrbufSubstrBefore(&name, strlen("luid_0x00000000_0x000146E8")); // luid_0x00000000_0x000146E8 + ffStrbufSubstrAfter(&name, strlen("luid_0x00000000_0x") - 1); // 000146E8 + uint64_t luid = strtoull(name.chars, nullptr, 16); - gpu->type = FF_GPU_TYPE_UNKNOWN; - - ffStrbufInit(&gpu->vendor); - record.getString(L"AdapterCompatibility", &gpu->vendor); - if(ffStrbufStartsWithS(&gpu->vendor, "Intel ")) + FF_LIST_FOR_EACH(FFGPUResult, gpu, *gpus) { - //Intel returns "Intel Corporation", not sure about AMD - ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + if (gpu->id != luid) continue; + record.getUnsigned(L"DedicatedUsage", &gpu->dedicatedUsed); + record.getUnsigned(L"SharedUsage", &gpu->sharedUsed); + break; } - - ffStrbufInit(&gpu->name); - record.getString(L"Name", &gpu->name); - - ffStrbufInit(&gpu->driver); - record.getString(L"DriverVersion", &gpu->driver); - - gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; } - return nullptr; + return NULL; } extern "C" const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance) { - if (instance->config.allowSlowOperations) - return detectWithWmi(gpus); + const char* error = detectWithRegistry(gpus); + if (error) + error = detectWithDxgi(gpus); - if (!detectWithRegistry(gpus)) - return nullptr; - return detectWithDxgi(gpus); + if (!error && gpus->length > 0 && instance->config.allowSlowOperations) + detectMemoryUsage(gpus); + + return error; } diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index 93d5ea2da..5d8b3f4f9 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -195,12 +195,14 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu gpu->type = FF_GPU_TYPE_INTEGRATED; else gpu->type = FF_GPU_TYPE_DISCRETE; + gpu->id = physicalDeviceProperties.properties.deviceID; + ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID)); + ffStrbufInitF(&gpu->driver, "%X", (unsigned) physicalDeviceProperties.properties.driverVersion); //No way to detect those using vulkan - ffStrbufInit(&gpu->vendor); - ffStrbufInit(&gpu->driver); gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = 0; //VkPhysicalDeviceMemoryProperties? } //If the highest device version is lower than the instance version, use it as our vulkan version diff --git a/src/modules/gpu.c b/src/modules/gpu.c index 6c673df36..3ff02c5ff 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -1,4 +1,6 @@ #include "fastfetch.h" +#include "common/bar.h" +#include "common/parsing.h" #include "common/printing.h" #include "detection/host/host.h" #include "detection/gpu/gpu.h" @@ -14,7 +16,7 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul { ffPrintLogoAndKey(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu.key); - FFstrbuf output; + FF_STRBUF_AUTO_DESTROY output; ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length); if(gpu->vendor.length > 0 && !ffStrbufStartsWith(&gpu->name, &gpu->vendor)) @@ -31,9 +33,25 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET ffStrbufAppendF(&output, " - %.1f°C", gpu->temperature); - ffStrbufPutTo(&output, stdout); + if(gpu->dedicatedTotal != FF_GPU_VMEM_SIZE_UNSET) + { + ffStrbufAppendS(&output, " ("); - ffStrbufDestroy(&output); + if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + { + ffParseSize(gpu->dedicatedUsed, instance->config.binaryPrefixType, &output); + ffStrbufAppendS(&output, " / "); + } + ffParseSize(gpu->dedicatedTotal, instance->config.binaryPrefixType, &output); + if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + { + ffStrbufAppendS(&output, ", "); + ffAppendPercentNum(instance, &output, (uint8_t) (gpu->dedicatedUsed * 100 / gpu->dedicatedTotal), 50, 80, false); + } + ffStrbufAppendC(&output, ')'); + } + + ffStrbufPutTo(&output, stdout); } else { From 662ddac0509e91c50d69dd2cbb4b3efe9bee6feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 11 Feb 2023 12:34:57 +0800 Subject: [PATCH 105/119] Vulkan: detect vmem (#416) --- src/common/io/io.h | 11 ++- src/common/io/io_unix.c | 7 +- src/common/io/io_windows.c | 3 +- src/detection/gpu/gpu.h | 12 ++- src/detection/gpu/gpu_apple.c | 2 +- src/detection/gpu/gpu_linux.c | 2 +- src/detection/gpu/gpu_windows.cpp | 18 ++-- src/detection/vulkan.c | 140 +++++++++++++++++------------- src/modules/gpu.c | 12 +-- 9 files changed, 119 insertions(+), 88 deletions(-) diff --git a/src/common/io/io.h b/src/common/io/io.h index c510c4e14..ca800dbe6 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -88,7 +88,16 @@ bool ffPathExists(const char* path, FFPathType pathType); #endif // Not thread safe! -void ffSuppressIO(bool suppress); +bool ffSuppressIO(bool suppress); + +static inline void ffUnsuppressIO(bool* suppressed) +{ + if (!*suppressed) return; + ffSuppressIO(false); + *suppressed = false; +} + +#define FF_SUPPRESS_IO() bool __attribute__((__cleanup__(ffUnsuppressIO), __unused__)) io_suppressed__ = ffSuppressIO(true) void ffListFilesRecursively(const char* path); diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index f343eb120..12afb7bc2 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -163,7 +163,7 @@ void ffGetTerminalResponse(const char* request, const char* format, ...) va_end(args); } -void ffSuppressIO(bool suppress) +bool ffSuppressIO(bool suppress) { static bool init = false; static int origOut = -1; @@ -173,7 +173,7 @@ void ffSuppressIO(bool suppress) if(!init) { if(!suppress) - return; + return true; origOut = dup(STDOUT_FILENO); origErr = dup(STDERR_FILENO); @@ -182,13 +182,14 @@ void ffSuppressIO(bool suppress) } if(nullFile == -1) - return; + return false; fflush(stdout); fflush(stderr); dup2(suppress ? nullFile : origOut, STDOUT_FILENO); dup2(suppress ? nullFile : origErr, STDERR_FILENO); + return true; } void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 3a28f19be..152c7c9a4 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -111,9 +111,10 @@ bool ffPathExists(const char* path, FFPathType type) return false; } -void ffSuppressIO(bool suppress) +bool ffSuppressIO(bool suppress) { (void) suppress; //Not implemented. + return false; } void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 15b2de74b..13983a8a4 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -21,6 +21,12 @@ typedef enum FFGpuType FF_GPU_TYPE_DISCRETE, } FFGpuType; +typedef struct FFGPUMemory +{ + uint64_t total; + uint64_t used; +} FFGPUMemory; + typedef struct FFGPUResult { uint64_t id; @@ -30,10 +36,8 @@ typedef struct FFGPUResult FFstrbuf driver; double temperature; int coreCount; - uint64_t dedicatedTotal; - uint64_t dedicatedUsed; - uint64_t sharedTotal; - uint64_t sharedUsed; + FFGPUMemory dedicated; + FFGPUMemory shared; } FFGPUResult; const FFlist* ffDetectGPU(const FFinstance* instance); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index bc571d7e2..fa514732e 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -61,7 +61,7 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) FFGPUResult* gpu = ffListAdd(gpus); gpu->id = 0; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; ffStrbufInit(&gpu->vendor); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 19f4b455a..d62d0e6cc 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -200,7 +200,7 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData FFGPUResult* gpu = ffListAdd(results); gpu->id = 0; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; ffStrbufInit(&gpu->vendor); pciDetectVendorName(gpu, pci, device); diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 587ca96e0..0ff1ad43c 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -49,7 +49,7 @@ static const char* detectWithRegistry(FFlist* gpus) gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->id = 0; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; ffRegReadUint64(hSubKey, L"AdapterLuid", &gpu->id, nullptr); @@ -67,8 +67,8 @@ static const char* detectWithRegistry(FFlist* gpus) if(ffRegReadUint64(hSubKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, nullptr) && ffRegReadUint64(hSubKey, L"SharedSystemMemory", &sharedSystemMemory, nullptr)) { - gpu->dedicatedTotal = dedicatedVideoMemory + dedicatedSystemMemory; - gpu->sharedTotal = sharedSystemMemory; + gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->shared.total = sharedSystemMemory; } uint64_t driverVersion; @@ -102,7 +102,7 @@ static const char* detectWithDxgi(FFlist* gpus) continue; FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = FF_GPU_VMEM_SIZE_UNSET; + gpu->dedicated.total = gpu->dedicated.total = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; ffStrbufInit(&gpu->vendor); ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(desc.VendorId)); @@ -115,8 +115,8 @@ static const char* detectWithDxgi(FFlist* gpus) ffStrbufInit(&gpu->driver); gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - gpu->dedicatedTotal = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory; - gpu->sharedTotal = desc.SharedSystemMemory; + gpu->dedicated.total = desc.DedicatedVideoMemory + desc.DedicatedSystemMemory; + gpu->shared.total = desc.SharedSystemMemory; adapter->Release(); @@ -149,13 +149,13 @@ static const char* detectMemoryUsage(FFlist* gpus) FF_LIST_FOR_EACH(FFGPUResult, gpu, *gpus) { if (gpu->id != luid) continue; - record.getUnsigned(L"DedicatedUsage", &gpu->dedicatedUsed); - record.getUnsigned(L"SharedUsage", &gpu->sharedUsed); + record.getUnsigned(L"DedicatedUsage", &gpu->dedicated.used); + record.getUnsigned(L"SharedUsage", &gpu->shared.used); break; } } - return NULL; + return nullptr; } extern "C" diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index 5d8b3f4f9..9a04e1dbb 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -8,6 +8,7 @@ #include "common/io/io.h" #include "common/parsing.h" #include "util/stringUtils.h" +#include "util/mallocHelper.h" #include #include @@ -42,19 +43,20 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed", #ifdef __APPLE__ "libMoltenVK"FF_LIBRARY_EXTENSION, -1 + #elif defined(_WIN32) + "vulkan-1"FF_LIBRARY_EXTENSION, -1 #else - "libvulkan"FF_LIBRARY_EXTENSION, 2, "vulkan-1"FF_LIBRARY_EXTENSION, -1 + "libvulkan"FF_LIBRARY_EXTENSION, 2 #endif ) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetInstanceProcAddr, vkGetInstanceProcAddr@8) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkCreateInstance, vkCreateInstance@12) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkDestroyInstance, vkDestroyInstance@8) FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkEnumeratePhysicalDevices, vkEnumeratePhysicalDevices@12) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(vulkan, vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceProperties@8) //Some drivers (nvdc) print messages to stdout //and thats the best way i found to disable that - ffSuppressIO(true); + FF_SUPPRESS_IO(); FFVersion instanceVersion = FF_VERSION_INIT; @@ -74,37 +76,29 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu FASTFETCH_PROJECT_VERSION_PATCH ); - //We need to request 1.2 to get physicalDeviceDriverProperties - uint32_t requestedVkVersion = VK_API_VERSION_1_0; - if(instanceVersion.minor >= 2) - requestedVkVersion = VK_API_VERSION_1_2; - - const VkApplicationInfo applicationInfo = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pNext = NULL, - .pApplicationName = FASTFETCH_PROJECT_NAME, - .applicationVersion = projectVersion, - .pEngineName = "vulkanPrintGPUs", - .engineVersion = projectVersion, - .apiVersion = requestedVkVersion - }; - - const VkInstanceCreateInfo instanceCreateInfo = { + VkInstance vkInstance; + if(ffvkCreateInstance(&(VkInstanceCreateInfo) { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = NULL, - .pApplicationInfo = &applicationInfo, + .pApplicationInfo = &(VkApplicationInfo) { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pNext = NULL, + .pApplicationName = FASTFETCH_PROJECT_NAME, + .applicationVersion = projectVersion, + .pEngineName = "vulkanPrintGPUs", + .engineVersion = projectVersion, + + // We need to request 1.1 to get physicalDeviceDriverProperties + .apiVersion = instanceVersion.minor >= 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0 + }, .enabledLayerCount = 0, .ppEnabledLayerNames = NULL, .enabledExtensionCount = 0, .ppEnabledExtensionNames = NULL, .flags = 0 - }; - - VkInstance vkInstance; - if(ffvkCreateInstance(&instanceCreateInfo, NULL, &vkInstance) != VK_SUCCESS) + }, NULL, &vkInstance) != VK_SUCCESS) { dlclose(vulkan); - ffSuppressIO(false); return "ffvkCreateInstance() failed"; } @@ -114,26 +108,25 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0) instanceVersion.major = 1; - uint32_t physicalDeviceCount; - if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL) != VK_SUCCESS) - { - ffvkDestroyInstance(vkInstance, NULL); - dlclose(vulkan); - ffSuppressIO(false); - return "ffvkEnumeratePhysicalDevices() failed"; - } - - VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); + VkPhysicalDevice physicalDevices[128]; + uint32_t physicalDeviceCount = (uint32_t) (sizeof(physicalDevices) / sizeof(*physicalDevices)); if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS) { - free(physicalDevices); ffvkDestroyInstance(vkInstance, NULL); dlclose(vulkan); - ffSuppressIO(false); return "ffvkEnumeratePhysicalDevices() failed"; } - PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2"); + PFN_vkGetPhysicalDeviceProperties ffvkGetPhysicalDeviceProperties = NULL; + PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2"); // 1.1 + if(!ffvkGetPhysicalDeviceProperties2) + ffvkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties"); + + PFN_vkGetPhysicalDeviceMemoryProperties ffvkGetPhysicalDeviceMemoryProperties = NULL; + PFN_vkGetPhysicalDeviceMemoryProperties2 ffvkGetPhysicalDeviceMemoryProperties2 = + instance->config.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1 + if(!ffvkGetPhysicalDeviceMemoryProperties2) + ffvkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties"); FFVersion maxDeviceApiVersion = FF_VERSION_INIT; FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT; @@ -141,18 +134,16 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu for(uint32_t i = 0; i < physicalDeviceCount; i++) { //Get device properties. - //On VK 1.2 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain. + //On VK 1.1 and up, we use vkGetPhysicalDeviceProperties2, so we can put VkPhysicalDeviceDriverProperties in the pNext chain. //This is required to get the driver name and conformance version. - VkPhysicalDeviceDriverProperties driverProperties; - driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; - driverProperties.pNext = NULL; - driverProperties.driverName[0] = '\0'; - driverProperties.conformanceVersion = (VkConformanceVersion) {0, 0, 0, 0}; - - VkPhysicalDeviceProperties2 physicalDeviceProperties; - physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - physicalDeviceProperties.pNext = &driverProperties; + VkPhysicalDeviceDriverProperties driverProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, + }; + VkPhysicalDeviceProperties2 physicalDeviceProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &driverProperties, + }; if(ffvkGetPhysicalDeviceProperties2 != NULL) ffvkGetPhysicalDeviceProperties2(physicalDevices[i], &physicalDeviceProperties); @@ -162,6 +153,7 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu //If the device api version is higher than the current highest device api version, overwrite it //In this case, also use the current device driver name as the shown driver name + FFVersion deviceAPIVersion = FF_VERSION_INIT; applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion); if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0) @@ -171,14 +163,17 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu } //If the device conformance version is higher than the current highest device conformance version, overwrite it + if(ffvkGetPhysicalDeviceProperties2) + { + FFVersion deviceConformanceVersion = { + .major = driverProperties.conformanceVersion.major, + .minor = driverProperties.conformanceVersion.minor, + .patch = driverProperties.conformanceVersion.patch, + }; - FFVersion deviceConformanceVersion = FF_VERSION_INIT; - deviceConformanceVersion.major = driverProperties.conformanceVersion.major; - deviceConformanceVersion.minor = driverProperties.conformanceVersion.minor; - deviceConformanceVersion.patch = driverProperties.conformanceVersion.patch; - - if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0) - maxDeviceConformanceVersion = deviceConformanceVersion; + if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0) + maxDeviceConformanceVersion = deviceConformanceVersion; + } //Add the device to the list of devices shown by the GPU module @@ -191,18 +186,41 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu ffStrbufInit(&gpu->name); ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName); - if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) - gpu->type = FF_GPU_TYPE_INTEGRATED; - else + if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) gpu->type = FF_GPU_TYPE_DISCRETE; + else + gpu->type = FF_GPU_TYPE_INTEGRATED; gpu->id = physicalDeviceProperties.properties.deviceID; ffStrbufInitS(&gpu->vendor, ffGetGPUVendorString(physicalDeviceProperties.properties.vendorID)); - ffStrbufInitF(&gpu->driver, "%X", (unsigned) physicalDeviceProperties.properties.driverVersion); + ffStrbufInitS(&gpu->driver, driverProperties.driverInfo); + + VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProperties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT, + }; + VkPhysicalDeviceMemoryProperties2 memoryProperties2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + .pNext = &budgetProperties, + }; + + if(ffvkGetPhysicalDeviceMemoryProperties2) + ffvkGetPhysicalDeviceMemoryProperties2(physicalDevices[i], &memoryProperties2); + else + ffvkGetPhysicalDeviceMemoryProperties(physicalDevices[i], &memoryProperties2.memoryProperties); + + gpu->dedicated.total = gpu->shared.total = 0; + gpu->dedicated.used = gpu->shared.used = ffvkGetPhysicalDeviceMemoryProperties2 ? 0 : FF_GPU_VMEM_SIZE_UNSET; + for(uint32_t index = 0; index < memoryProperties2.memoryProperties.memoryHeapCount; ++index) + { + const VkMemoryHeap* heap = &memoryProperties2.memoryProperties.memoryHeaps[index]; + FFGPUMemory* vmem = gpu->type == FF_GPU_TYPE_DISCRETE && (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? &gpu->dedicated : &gpu->shared; + vmem->total += heap->size; + if(ffvkGetPhysicalDeviceMemoryProperties2) + vmem->used += heap->size - budgetProperties.heapBudget[index]; + } //No way to detect those using vulkan gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->dedicatedTotal = gpu->dedicatedUsed = gpu->sharedTotal = gpu->sharedUsed = 0; //VkPhysicalDeviceMemoryProperties? } //If the highest device version is lower than the instance version, use it as our vulkan version @@ -215,10 +233,8 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu //Use the highest device conformace version as our conformance version ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion); - free(physicalDevices); ffvkDestroyInstance(vkInstance, NULL); dlclose(vulkan); - ffSuppressIO(false); return NULL; } diff --git a/src/modules/gpu.c b/src/modules/gpu.c index 3ff02c5ff..0033d33be 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -33,20 +33,20 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET ffStrbufAppendF(&output, " - %.1f°C", gpu->temperature); - if(gpu->dedicatedTotal != FF_GPU_VMEM_SIZE_UNSET) + if(gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET && gpu->dedicated.total != 0) { ffStrbufAppendS(&output, " ("); - if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { - ffParseSize(gpu->dedicatedUsed, instance->config.binaryPrefixType, &output); + ffParseSize(gpu->dedicated.used, instance->config.binaryPrefixType, &output); ffStrbufAppendS(&output, " / "); } - ffParseSize(gpu->dedicatedTotal, instance->config.binaryPrefixType, &output); - if(gpu->dedicatedUsed != FF_GPU_VMEM_SIZE_UNSET) + ffParseSize(gpu->dedicated.total, instance->config.binaryPrefixType, &output); + if(gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) { ffStrbufAppendS(&output, ", "); - ffAppendPercentNum(instance, &output, (uint8_t) (gpu->dedicatedUsed * 100 / gpu->dedicatedTotal), 50, 80, false); + ffAppendPercentNum(instance, &output, (uint8_t) (gpu->dedicated.used * 100 / gpu->dedicated.total), 50, 80, false); } ffStrbufAppendC(&output, ')'); } From e29169711c4fc37a408bf6a2f7448c09e78abc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 16:33:58 +0800 Subject: [PATCH 106/119] TerminalShell (Linux): tidy --- src/detection/terminalshell/terminalshell_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 460b98a09..8db9f2901 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -53,7 +53,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex size_t size = exe->allocated; if(!sysctl( (int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}, 4, - exe->chars, &size, + exe->chars, &size, NULL, 0 )) exe->length = (uint32_t)size; From b634c70f809dcf213dd5c876e7810e6c80b4193b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 17:29:21 +0800 Subject: [PATCH 107/119] Temp (Apple): support memory temperature detection for future use --- src/detection/temps/temps_apple.c | 4 ++++ src/detection/temps/temps_apple.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index 9daee1c91..041e1418e 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -397,6 +397,10 @@ const char *ffDetectCoreTemps(enum FFTempType type, FFlist *result) case FF_TEMP_BATTERY: detectTemp(conn, "TB1T", "Battery", result); break; + + case FF_TEMP_MEMORY: + detectTemp(conn, "Tm02", "Memory", result); + break; } return NULL; diff --git a/src/detection/temps/temps_apple.h b/src/detection/temps/temps_apple.h index 8ac83e22d..147c32d07 100644 --- a/src/detection/temps/temps_apple.h +++ b/src/detection/temps/temps_apple.h @@ -26,6 +26,8 @@ enum FFTempType FF_TEMP_GPU_M2X, FF_TEMP_BATTERY, + + FF_TEMP_MEMORY, }; const char *ffDetectCoreTemps(enum FFTempType type, FFlist *result); From e2d145cf3132f6b8986d2e34557d944317513eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 17:31:07 +0800 Subject: [PATCH 108/119] Memory (Apple): use sysctl instead of sysctlbyname --- src/detection/memory/memory_apple.c | 19 ++++++++++--------- src/detection/swap/swap_apple.c | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/detection/memory/memory_apple.c b/src/detection/memory/memory_apple.c index f86f52cd4..37b7addb7 100644 --- a/src/detection/memory/memory_apple.c +++ b/src/detection/memory/memory_apple.c @@ -1,30 +1,31 @@ #include "memory.h" -#include "common/sysctl.h" #include #include +#include void ffDetectMemory(FFMemoryStorage* ram) { - ram->bytesTotal = (uint64_t) ffSysctlGetInt64("hw.memsize", 0); - if(ram->bytesTotal == 0) + size_t length = sizeof(ram->bytesTotal); + if (sysctl((int[]){ CTL_HW, HW_MEMSIZE }, 2, &ram->bytesTotal, &length, NULL, 0)) { ffStrbufAppendS(&ram->error, "Failed to read hw.memsize"); return; } - uint32_t pagesize = (uint32_t) ffSysctlGetInt("hw.pagesize", 0); - if(pagesize == 0) + uint32_t pagesize; + length = sizeof(pagesize); + if (sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &pagesize, &length, NULL, 0)) { ffStrbufAppendS(&ram->error, "Failed to read hw.pagesize"); return; } - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - vm_statistics_data_t vmstat; - if(host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) (&vmstat), &count) != KERN_SUCCESS) + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; + vm_statistics64_data_t vmstat; + if(host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) (&vmstat), &count) != KERN_SUCCESS) { - ffStrbufAppendS(&ram->error, "Failed to read vm statistics"); + ffStrbufAppendS(&ram->error, "Failed to read host_statistics64"); return; } diff --git a/src/detection/swap/swap_apple.c b/src/detection/swap/swap_apple.c index 34e72802a..15200da15 100644 --- a/src/detection/swap/swap_apple.c +++ b/src/detection/swap/swap_apple.c @@ -1,13 +1,13 @@ #include "swap.h" -#include "common/sysctl.h" #include +#include void ffDetectSwap(FFMemoryStorage* swap) { struct xsw_usage xsw; size_t size = sizeof(xsw); - if(sysctlbyname("vm.swapusage", &xsw, &size, 0, 0) != 0) + if(sysctl((int[]){ CTL_VM, VM_SWAPUSAGE }, 2, &xsw, &size, NULL, 0) != 0) { ffStrbufAppendS(&swap->error, "Failed to read vm.swapusage"); return; From 6407bf6a1f1a4f8e1b303b83bc70ed02491e870a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 17:46:21 +0800 Subject: [PATCH 109/119] GTK / QT: refactor directory structures --- CMakeLists.txt | 8 ++++---- src/common/init.c | 4 ++-- src/detection/cursor/cursor_linux.c | 2 +- src/detection/font/font_linux.c | 3 +-- src/detection/{ => gtk_qt}/gtk.c | 2 +- src/detection/{gtk.h => gtk_qt/gtk_qt.h} | 13 +++++++++++-- src/detection/{ => gtk_qt}/qt.c | 2 +- src/detection/qt.h | 18 ------------------ src/detection/wmtheme/wmtheme_linux.c | 2 +- src/modules/icons.c | 3 +-- src/modules/theme.c | 3 +-- 11 files changed, 24 insertions(+), 36 deletions(-) rename src/detection/{ => gtk_qt}/gtk.c (99%) rename src/detection/{gtk.h => gtk_qt/gtk_qt.h} (57%) rename src/detection/{ => gtk_qt}/qt.c (99%) delete mode 100644 src/detection/qt.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 95b3a447d..a9e155b3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,7 +333,7 @@ if(LINUX) src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c src/detection/gpu/gpu_linux.c - src/detection/gtk.c + src/detection/gtk_qt/gtk.c src/detection/host/host_linux.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_linux.c @@ -344,7 +344,7 @@ if(LINUX) src/detection/packages/packages_linux.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_linux.c - src/detection/qt.c + src/detection/gtk_qt/qt.c src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c src/detection/temps/temps_linux.c @@ -419,7 +419,7 @@ elseif(BSD) src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c src/detection/gpu/gpu_linux.c - src/detection/gtk.c + src/detection/gtk_qt/gtk.c src/detection/host/host_bsd.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_nosupport.c @@ -430,7 +430,7 @@ elseif(BSD) src/detection/packages/packages_linux.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_bsd.c - src/detection/qt.c + src/detection/gtk_qt/qt.c src/detection/sound/sound_linux.c src/detection/swap/swap_bsd.c src/detection/temps/temps_linux.c diff --git a/src/common/init.c b/src/common/init.c index cf4a46735..90970089a 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -1,8 +1,6 @@ #include "fastfetch.h" #include "common/parsing.h" #include "common/thread.h" -#include "detection/qt.h" -#include "detection/gtk.h" #include "detection/displayserver/displayserver.h" #include "util/textModifier.h" @@ -220,6 +218,8 @@ FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*) #if !(defined(__APPLE__) || defined(_WIN32)) +#include "detection/gtk_qt/gtk_qt.h" + #define FF_DETECT_QT_GTK 1 FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*) diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c index 88366c935..3ca696091 100644 --- a/src/detection/cursor/cursor_linux.c +++ b/src/detection/cursor/cursor_linux.c @@ -3,7 +3,7 @@ #include "common/properties.h" #include "common/parsing.h" #include "common/settings.h" -#include "detection/gtk.h" +#include "detection/gtk_qt/gtk_qt.h" #include "detection/displayserver/displayserver.h" #include "util/stringUtils.h" diff --git a/src/detection/font/font_linux.c b/src/detection/font/font_linux.c index 62c66445b..ae2f03331 100644 --- a/src/detection/font/font_linux.c +++ b/src/detection/font/font_linux.c @@ -1,6 +1,5 @@ -#include "detection/qt.h" -#include "detection/gtk.h" #include "common/font.h" +#include "detection/gtk_qt/gtk_qt.h" #include "font.h" void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) diff --git a/src/detection/gtk.c b/src/detection/gtk_qt/gtk.c similarity index 99% rename from src/detection/gtk.c rename to src/detection/gtk_qt/gtk.c index 3fb9b8e7c..e06a63542 100644 --- a/src/detection/gtk.c +++ b/src/detection/gtk_qt/gtk.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "detection/gtk.h" +#include "detection/gtk_qt/gtk_qt.h" #include "common/properties.h" #include "common/thread.h" #include "common/settings.h" diff --git a/src/detection/gtk.h b/src/detection/gtk_qt/gtk_qt.h similarity index 57% rename from src/detection/gtk.h rename to src/detection/gtk_qt/gtk_qt.h index 683984351..fb3c44c4b 100644 --- a/src/detection/gtk.h +++ b/src/detection/gtk_qt/gtk_qt.h @@ -1,7 +1,7 @@ #pragma once -#ifndef FF_INCLUDED_detection_gtk -#define FF_INCLUDED_detection_gtk +#ifndef FF_INCLUDED_detection_gtkqt_gtkqt +#define FF_INCLUDED_detection_gtkqt_gtkqt #include "fastfetch.h" @@ -14,8 +14,17 @@ typedef struct FFGTKResult FFstrbuf cursorSize; } FFGTKResult; +typedef struct FFQtResult +{ + FFstrbuf widgetStyle; + FFstrbuf colorScheme; + FFstrbuf icons; + FFstrbuf font; +} FFQtResult; + const FFGTKResult* ffDetectGTK2(const FFinstance* instance); const FFGTKResult* ffDetectGTK4(const FFinstance* instance); const FFGTKResult* ffDetectGTK3(const FFinstance* instance); +const FFQtResult* ffDetectQt(const FFinstance* instance); #endif diff --git a/src/detection/qt.c b/src/detection/gtk_qt/qt.c similarity index 99% rename from src/detection/qt.c rename to src/detection/gtk_qt/qt.c index 649a2a25b..74b54a1df 100644 --- a/src/detection/qt.c +++ b/src/detection/gtk_qt/qt.c @@ -1,7 +1,7 @@ #include "fastfetch.h" -#include "detection/qt.h" #include "common/properties.h" #include "common/thread.h" +#include "detection/gtk_qt/gtk_qt.h" #include "detection/displayserver/displayserver.h" #include diff --git a/src/detection/qt.h b/src/detection/qt.h deleted file mode 100644 index a23b29db6..000000000 --- a/src/detection/qt.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#ifndef FF_INCLUDED_detection_qt -#define FF_INCLUDED_detection_qt - -#include "fastfetch.h" - -typedef struct FFQtResult -{ - FFstrbuf widgetStyle; - FFstrbuf colorScheme; - FFstrbuf icons; - FFstrbuf font; -} FFQtResult; - -const FFQtResult* ffDetectQt(const FFinstance* instance); - -#endif diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index 8d2a079f6..e325e0bce 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -2,7 +2,7 @@ #include "common/properties.h" #include "common/parsing.h" #include "common/settings.h" -#include "detection/gtk.h" +#include "detection/gtk_qt/gtk_qt.h" #include "detection/displayserver/displayserver.h" #include "util/stringUtils.h" diff --git a/src/modules/icons.c b/src/modules/icons.c index bb12ecc81..81fa3af9d 100644 --- a/src/modules/icons.c +++ b/src/modules/icons.c @@ -1,8 +1,7 @@ #include "fastfetch.h" #include "common/printing.h" #include "common/parsing.h" -#include "detection/qt.h" -#include "detection/gtk.h" +#include "detection/gtk_qt/gtk_qt.h" #include "detection/displayserver/displayserver.h" #define FF_ICONS_MODULE_NAME "Icons" diff --git a/src/modules/theme.c b/src/modules/theme.c index 1dc7c868a..04a2e1d7b 100644 --- a/src/modules/theme.c +++ b/src/modules/theme.c @@ -1,8 +1,7 @@ #include "fastfetch.h" #include "common/printing.h" #include "common/parsing.h" -#include "detection/qt.h" -#include "detection/gtk.h" +#include "detection/gtk_qt/gtk_qt.h" #include "detection/displayserver/displayserver.h" #define FF_THEME_MODULE_NAME "Theme" From 47be29b89c1bcca98c9b5189cdc8a3401f758ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 17:49:23 +0800 Subject: [PATCH 110/119] DateTime: refactor directory structures --- CMakeLists.txt | 2 +- src/detection/{ => datetime}/datetime.c | 2 +- src/detection/{ => datetime}/datetime.h | 4 ++-- src/modules/date.c | 2 +- src/modules/datetime.c | 2 +- src/modules/time.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) rename src/detection/{ => datetime}/datetime.c (98%) rename src/detection/{ => datetime}/datetime.h (89%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9e155b3a..dd5a28fee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,7 @@ set(LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth.c src/detection/cpu/cpu.c src/detection/cpuUsage/cpuUsage.c - src/detection/datetime.c + src/detection/datetime/datetime.c src/detection/disk/disk.c src/detection/displayserver/displayserver.c src/detection/font/font.c diff --git a/src/detection/datetime.c b/src/detection/datetime/datetime.c similarity index 98% rename from src/detection/datetime.c rename to src/detection/datetime/datetime.c index 20b8ec367..317fdcf85 100644 --- a/src/detection/datetime.c +++ b/src/detection/datetime/datetime.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "detection/datetime.h" +#include "detection/datetime/datetime.h" #include "common/thread.h" #include diff --git a/src/detection/datetime.h b/src/detection/datetime/datetime.h similarity index 89% rename from src/detection/datetime.h rename to src/detection/datetime/datetime.h index 7f6956e61..418f14fb2 100644 --- a/src/detection/datetime.h +++ b/src/detection/datetime/datetime.h @@ -1,7 +1,7 @@ #pragma once -#ifndef FF_INCLUDED_detection_datetime -#define FF_INCLUDED_detection_datetime +#ifndef FF_INCLUDED_detection_datetime_datetime +#define FF_INCLUDED_detection_datetime_datetime #include "fastfetch.h" diff --git a/src/modules/date.c b/src/modules/date.c index 96ea03e1e..a92209ed0 100644 --- a/src/modules/date.c +++ b/src/modules/date.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/datetime.h" +#include "detection/datetime/datetime.h" #define FF_DATE_MODULE_NAME "Date" diff --git a/src/modules/datetime.c b/src/modules/datetime.c index 61745c16a..25f08da5a 100644 --- a/src/modules/datetime.c +++ b/src/modules/datetime.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/datetime.h" +#include "detection/datetime/datetime.h" #define FF_DATETIME_MODULE_NAME "Date & Time" #define FF_DATETIME_NUM_FORMAT_ARGS 20 diff --git a/src/modules/time.c b/src/modules/time.c index d06b5b714..523e4fa19 100644 --- a/src/modules/time.c +++ b/src/modules/time.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/datetime.h" +#include "detection/datetime/datetime.h" #define FF_TIME_MODULE_NAME "Time" From 64bacd257242c42de0fa76fa586523158a38457b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 17:50:53 +0800 Subject: [PATCH 111/119] Vulkan: refactor directory structures --- CMakeLists.txt | 2 +- src/detection/gpu/gpu.c | 2 +- src/detection/gpu/gpu_linux.c | 4 ++-- src/detection/{ => vulkan}/vulkan.c | 2 +- src/detection/{ => vulkan}/vulkan.h | 0 src/modules/vulkan.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/detection/{ => vulkan}/vulkan.c (99%) rename src/detection/{ => vulkan}/vulkan.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd5a28fee..0446e4419 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,7 +246,7 @@ set(LIBFASTFETCH_SRC src/detection/packages/packages.c src/detection/terminalfont/terminalfont.c src/detection/terminalshell/terminalshell.c - src/detection/vulkan.c + src/detection/vulkan/vulkan.c src/logo/builtin.c src/logo/image/im6.c src/logo/image/im7.c diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 89d551e1e..61951e32d 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -1,6 +1,6 @@ #include "gpu.h" #include "detection/internal.h" -#include "detection/vulkan.h" +#include "detection/vulkan/vulkan.h" const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index d62d0e6cc..d1776d2e2 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -1,5 +1,5 @@ -#include "gpu.h" -#include "detection/vulkan.h" +#include "detection/gpu/gpu.h" +#include "detection/vulkan/vulkan.h" #ifdef FF_HAVE_LIBPCI #include "common/library.h" diff --git a/src/detection/vulkan.c b/src/detection/vulkan/vulkan.c similarity index 99% rename from src/detection/vulkan.c rename to src/detection/vulkan/vulkan.c index 9a04e1dbb..5e63d812b 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -1,7 +1,7 @@ #include "fastfetch.h" #include "common/thread.h" -#include "detection/vulkan.h" #include "detection/gpu/gpu.h" +#include "detection/vulkan/vulkan.h" #ifdef FF_HAVE_VULKAN #include "common/library.h" diff --git a/src/detection/vulkan.h b/src/detection/vulkan/vulkan.h similarity index 100% rename from src/detection/vulkan.h rename to src/detection/vulkan/vulkan.h diff --git a/src/modules/vulkan.c b/src/modules/vulkan.c index 4b3d19fea..23c6f60df 100644 --- a/src/modules/vulkan.c +++ b/src/modules/vulkan.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/vulkan.h" +#include "detection/vulkan/vulkan.h" #define FF_VULKAN_MODULE_NAME "Vulkan" #define FF_VULKAN_NUM_FORMAT_ARGS 3 From cabd36d07888e6d1bc398d5c9fe636df8a85ab19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Feb 2023 19:24:29 +0800 Subject: [PATCH 112/119] CpuUsage (apple): simplify implementation --- src/detection/cpuUsage/cpuUsage_apple.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/detection/cpuUsage/cpuUsage_apple.c b/src/detection/cpuUsage/cpuUsage_apple.c index 38a6b4865..d3b533f48 100644 --- a/src/detection/cpuUsage/cpuUsage_apple.c +++ b/src/detection/cpuUsage/cpuUsage_apple.c @@ -6,23 +6,18 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) { - natural_t numCPUs = 0U; - processor_info_array_t cpuInfo; - mach_msg_type_number_t numCpuInfo; + host_cpu_load_info_data_t cpustats; + mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; + *inUseAll = *totalAll = 0; - if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS) - return "host_processor_info() failed"; - if (numCPUs * CPU_STATE_MAX != numCpuInfo) - return "Unexpected host_processor_info() result"; + if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)(&cpustats), &count) != KERN_SUCCESS) + return "host_statistics() failed"; + + *inUseAll = cpustats.cpu_ticks[CPU_STATE_USER] + + cpustats.cpu_ticks[CPU_STATE_SYSTEM] + + cpustats.cpu_ticks[CPU_STATE_NICE]; + *totalAll = *inUseAll + cpustats.cpu_ticks[CPU_STATE_IDLE]; - for (natural_t i = 0U; i < numCPUs; ++i) { - integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER] - + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM] - + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE]; - integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE]; - *inUseAll += (uint64_t)inUse; - *totalAll += (uint64_t)total; - } return NULL; } From 6ca4b5391b51a649901834224b7e423c3c4fda66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 15 Feb 2023 14:51:04 +0800 Subject: [PATCH 113/119] Library: refactor FF_LIBRARY_LOAD to use `__cleanup__` --- src/common/dbus.c | 4 ++-- src/common/library.h | 21 ++++++++++--------- src/detection/displayserver/linux/wayland.c | 5 ----- src/detection/displayserver/linux/xcb.c | 8 ------- src/detection/displayserver/linux/xlib.c | 8 ------- src/detection/gpu/gpu_linux.c | 1 - src/detection/opengl/opengl_linux.c | 12 +++-------- src/detection/packages/packages_linux.c | 8 ------- src/detection/sound/sound_linux.c | 1 - src/detection/terminalfont/terminalfont.c | 1 - .../terminalfont/terminalfont_android.c | 1 - src/detection/vulkan/vulkan.c | 6 ------ src/detection/wifi/wifi_linux.c | 4 ---- src/detection/wifi/wifi_windows.c | 1 - src/logo/image/im6.c | 13 ++++-------- src/logo/image/im7.c | 13 ++++-------- src/logo/image/image.c | 11 +--------- src/modules/opencl.c | 4 +--- src/util/mallocHelper.h | 1 + 19 files changed, 27 insertions(+), 96 deletions(-) diff --git a/src/common/dbus.c b/src/common/dbus.c index f974b39d9..b0f5c4ffe 100644 --- a/src/common/dbus.c +++ b/src/common/dbus.c @@ -24,7 +24,7 @@ static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false) - + dbus = NULL; // don't auto dlclose return true; } @@ -178,7 +178,7 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char return NULL; } - DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); + DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); dbus->lib->ffdbus_message_unref(message); diff --git a/src/common/library.h b/src/common/library.h index c433d1e81..a0de3d621 100644 --- a/src/common/library.h +++ b/src/common/library.h @@ -6,7 +6,7 @@ #include "fastfetch.h" #include "util/FFcheckmacros.h" -#if defined(_WIN32) //We don't force MSYS using LoadLibrary because dlopen also searches $LD_LIBRARY_PATH +#if defined(_WIN32) #include #define FF_DLOPEN_FLAGS 0 FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); } @@ -24,29 +24,30 @@ #define FF_LIBRARY_EXTENSION ".so" #endif +static inline void ffLibraryUnload(void** handle) +{ + assert(handle); + if (*handle) + dlclose(*handle); +} + #define FF_LIBRARY_SYMBOL(symbolName) \ __typeof__(&symbolName) ff ## symbolName; #define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \ - void* libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\ + void* __attribute__((__cleanup__(ffLibraryUnload))) libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\ if(libraryObjectName == NULL) \ return returnValue; #define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \ symbolMapping = dlsym(library, #symbolName); \ if(symbolMapping == NULL) \ - { \ - dlclose(library); \ - return returnValue; \ - } + return returnValue; #define FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, symbolMapping, symbolName, alternateName, returnValue) \ symbolMapping = dlsym(library, #symbolName); \ if(symbolMapping == NULL && !(symbolMapping = dlsym(library, #alternateName))) \ - { \ - dlclose(library); \ - return returnValue; \ - } + return returnValue; #define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \ __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue); diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index a6ca31edd..fce97c8f2 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -160,10 +160,7 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) data.display = ffwl_display_connect(NULL); if(data.display == NULL) - { - dlclose(wayland); return false; - } waylandDetectWM(ffwl_display_get_fd(data.display), result); @@ -171,7 +168,6 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) if(registry == NULL) { ffwl_display_disconnect(data.display); - dlclose(wayland); return false; } @@ -188,7 +184,6 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) data.ffwl_proxy_destroy(registry); ffwl_display_disconnect(data.display); - dlclose(wayland); //We successfully connected to wayland and detected the display. //So we can set set the session type to wayland. diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 183ff5251..c31803286 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -103,10 +103,7 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) xcb_connection_t* connection = ffxcb_connect(NULL, NULL); if(connection == NULL) - { - dlclose(xcb); return; - } xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(connection)); @@ -127,7 +124,6 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) } ffxcb_disconnect(connection); - dlclose(xcb); //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) @@ -368,10 +364,7 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu data.connection = ffxcb_connect(NULL, NULL); if(data.connection == NULL) - { - dlclose(xcbRandr); return; - } data.result = result; @@ -387,7 +380,6 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu } ffxcb_disconnect(data.connection); - dlclose(xcbRandr); //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 50eba6a2d..241db5e87 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -69,10 +69,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) Display* display = ffXOpenDisplay(x11); if(display == NULL) - { - dlclose(x11); return; - } if(propertyDataInitialized && ScreenCount(display) > 0) x11DetectWMFromEWMH(&propertyData, display, result); @@ -91,7 +88,6 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) } ffXCloseDisplay(display); - dlclose(x11); //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) @@ -298,10 +294,7 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result data.display = ffXOpenDisplay(NULL); if(data.display == NULL) - { - dlclose(xrandr); return; - } if(propertyDataInitialized && ScreenCount(data.display) > 0) x11DetectWMFromEWMH(&propertyData, data.display, result); @@ -312,7 +305,6 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i)); ffXCloseDisplay(data.display); - dlclose(xrandr); //If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland. if(result->wmProtocolName.length == 0) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index d1776d2e2..999856cdc 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -251,7 +251,6 @@ static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus) } ffpci_cleanup(pci.access); - dlclose(libpci); return NULL; } diff --git a/src/detection/opengl/opengl_linux.c b/src/detection/opengl/opengl_linux.c index d95062ad5..a959578f8 100644 --- a/src/detection/opengl/opengl_linux.c +++ b/src/detection/opengl/opengl_linux.c @@ -133,9 +133,7 @@ static const char* eglPrint(FFinstance* instance, FFOpenGLResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate); - const char* error = eglHandleData(result, &eglData); - dlclose(egl); - return error; + return eglHandleData(result, &eglData); } #endif //FF_HAVE_EGL @@ -252,9 +250,7 @@ static const char* glxPrint(FFinstance* instance, FFOpenGLResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCloseDisplay); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFree); - const char* error = glxHandleData(result, &data); - dlclose(glx); - return error; + return glxHandleData(result, &data); } #endif //FF_HAVE_GLX @@ -310,9 +306,7 @@ static const char* osMesaPrint(FFinstance* instance, FFOpenGLResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaDestroyContext); - const char* error = osMesaHandleData(result, &data); - dlclose(osmesa); - return error; + return osMesaHandleData(result, &data); } #endif //FF_HAVE_OSMESA diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index c3cd1381d..11162b138 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -229,23 +229,16 @@ static uint32_t getRpmFromLibrpm(const FFinstance* instance) ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG)); if(ffrpmReadConfigFiles(NULL, NULL) != 0) - { - dlclose(rpm); return 0; - } rpmts ts = ffrpmtsCreate(); if(ts == NULL) - { - dlclose(rpm); return 0; - } rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0); if(mi == NULL) { ffrpmtsFree(ts); - dlclose(rpm); return 0; } @@ -253,7 +246,6 @@ static uint32_t getRpmFromLibrpm(const FFinstance* instance) ffrpmdbFreeIterator(mi); ffrpmtsFree(ts); - dlclose(rpm); return count > 0 ? (uint32_t) count : 0; } diff --git a/src/detection/sound/sound_linux.c b/src/detection/sound/sound_linux.c index a752a6b5f..bb0b9d409 100644 --- a/src/detection/sound/sound_linux.c +++ b/src/detection/sound/sound_linux.c @@ -114,7 +114,6 @@ static const char* detectSound(const FFinstance* instance, FFlist* devices) ffpa_context_unref(context); ffpa_mainloop_free(mainloop); - dlclose(pulse); return NULL; } diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 40275314c..db967b245 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -177,7 +177,6 @@ static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* conten exit: cjsonData.ffcJSON_Delete(root); - dlclose(libcjson); return error; } diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index f3f6a38d6..251ada6c7 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -42,7 +42,6 @@ const char* detectTermux(const FFinstance* instance, FFTerminalFontResult* termi exit: if(face) ffFT_Done_Face(face); if(library) ffFT_Done_FreeType(library); - dlclose(freetype); return error; diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 5e63d812b..d46f1879c 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -97,11 +97,7 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu .ppEnabledExtensionNames = NULL, .flags = 0 }, NULL, &vkInstance) != VK_SUCCESS) - { - dlclose(vulkan); return "ffvkCreateInstance() failed"; - } - //if instance creation succeeded, but vkEnumerateInstanceVersion didn't, this means we are running against a vulkan 1.0 implementation //explicitly set this version, if no device is found, so we still have at least this info @@ -113,7 +109,6 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu if(ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices) != VK_SUCCESS) { ffvkDestroyInstance(vkInstance, NULL); - dlclose(vulkan); return "ffvkEnumeratePhysicalDevices() failed"; } @@ -234,7 +229,6 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion); ffvkDestroyInstance(vkInstance, NULL); - dlclose(vulkan); return NULL; } diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 178520c8e..edd5affc5 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -45,10 +45,7 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul NMClient* client = ffnm_client_new(NULL, NULL); if(!client) - { - dlclose(nm); return "Could not create NMClient"; - } /* Get all devices managed by NetworkManager */ const GPtrArray* devices = ffnm_client_get_devices(client); @@ -199,7 +196,6 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul } ffg_object_unref(client); - dlclose(nm); return NULL; } diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 70d7ea577..f13cc5484 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -207,7 +207,6 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res exit: if(ifList) ffWlanFreeMemory(ifList); if(hClient) ffWlanCloseHandle(hClient, NULL); - dlclose(wlanapi); return error; } diff --git a/src/logo/image/im6.c b/src/logo/image/im6.c index a235bb867..ba652a370 100644 --- a/src/logo/image/im6.c +++ b/src/logo/image/im6.c @@ -17,15 +17,10 @@ FFLogoImageResult ffLogoPrintImageIM6(FFinstance* instance, FFLogoRequestData* r FF_LIBRARY_LOAD(imageMagick, &instance->config.libImageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI" FF_LIBRARY_EXTENSION, 8, "libMagickCore-6.Q16" FF_LIBRARY_EXTENSION, 8) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR); - FFIMData imData; - imData.resizeFunc = logoResize; - imData.library = imageMagick; - - FFLogoImageResult result = ffLogoPrintImageImpl(instance, requestData, &imData); - - dlclose(imageMagick); - - return result; + return ffLogoPrintImageImpl(instance, requestData, &(FFIMData) { + .resizeFunc = logoResize, + .library = imageMagick, + }); } #endif diff --git a/src/logo/image/im7.c b/src/logo/image/im7.c index d7cf4b6d0..0677b4911 100644 --- a/src/logo/image/im7.c +++ b/src/logo/image/im7.c @@ -21,15 +21,10 @@ FFLogoImageResult ffLogoPrintImageIM7(FFinstance* instance, FFLogoRequestData* r ) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR); - FFIMData imData; - imData.resizeFunc = logoResize; - imData.library = imageMagick; - - FFLogoImageResult result = ffLogoPrintImageImpl(instance, requestData, &imData); - - dlclose(imageMagick); - - return result; + return ffLogoPrintImageImpl(instance, requestData, &(FFIMData) { + .resizeFunc = logoResize, + .library = imageMagick, + }); } #endif diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 96be2d049..7010dd815 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -131,14 +131,9 @@ static bool compressBlob(const FFinstance* instance, void** blob, size_t* length uLong compressedLength = ffcompressBound(*length); void* compressed = malloc(compressedLength); if(compressed == NULL) - { - dlclose(zlib); return false; - } - int compressResult = ffcompress2(compressed, &compressedLength, *blob, *length, Z_BEST_COMPRESSION); - dlclose(zlib); - if(compressResult != Z_OK) + if(ffcompress2(compressed, &compressedLength, *blob, *length, Z_BEST_COMPRESSION) != Z_OK) { free(compressed); return false; @@ -336,10 +331,7 @@ static bool printImageChafa(FFinstance* instance, FFLogoRequestData* requestData size_t length; void* blob = imageData->ffImageToBlob(imageData->imageInfo, imageData->image, &length, imageData->exceptionInfo); if(!checkAllocationResult(blob, length)) - { - dlclose(chafa); return false; - } ChafaSymbolMap* symbolMap = ffchafa_symbol_map_new(); GError* error = NULL; @@ -408,7 +400,6 @@ static bool printImageChafa(FFinstance* instance, FFLogoRequestData* requestData ffchafa_canvas_unref(canvas); ffchafa_canvas_config_unref(canvasConfig); ffchafa_symbol_map_unref(symbolMap); - dlclose(chafa); return true; } diff --git a/src/modules/opencl.c b/src/modules/opencl.c index 8f1f69cd1..621165742 100644 --- a/src/modules/opencl.c +++ b/src/modules/opencl.c @@ -94,9 +94,7 @@ static const char* printOpenCL(FFinstance* instance) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); - const char* error = openCLHandleData(instance, &data); - dlclose(opencl); - return error; + return openCLHandleData(instance, &data); } #elif defined(__APPLE__) // FF_HAVE_OPENCL diff --git a/src/util/mallocHelper.h b/src/util/mallocHelper.h index a4fd8eb6e..18aa801bf 100644 --- a/src/util/mallocHelper.h +++ b/src/util/mallocHelper.h @@ -2,6 +2,7 @@ static inline void ffWrapFree(void* pPtr) { + assert(pPtr); if(*(void**)pPtr) free(*(void**)pPtr); } From 9a3909f8ba303999dc710232825d06d06925966c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 Feb 2023 17:19:43 +0800 Subject: [PATCH 114/119] Memory (Windows): check for error cases --- src/detection/memory/memory_windows.c | 6 +++++- src/detection/swap/swap_windows.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/detection/memory/memory_windows.c b/src/detection/memory/memory_windows.c index ef3153843..d639c2a73 100644 --- a/src/detection/memory/memory_windows.c +++ b/src/detection/memory/memory_windows.c @@ -5,7 +5,11 @@ void ffDetectMemory(FFMemoryStorage* ram) MEMORYSTATUSEX statex = { .dwLength = sizeof(statex), }; - GlobalMemoryStatusEx(&statex); + if (!GlobalMemoryStatusEx(&statex)) + { + ffStrbufAppendS(&ram->error, "GlobalMemoryStatusEx() failed"); + return; + } ram->bytesTotal = statex.ullTotalPhys; ram->bytesUsed = statex.ullTotalPhys - statex.ullAvailPhys; } diff --git a/src/detection/swap/swap_windows.cpp b/src/detection/swap/swap_windows.cpp index 224a3ce35..d7f910f95 100644 --- a/src/detection/swap/swap_windows.cpp +++ b/src/detection/swap/swap_windows.cpp @@ -23,7 +23,7 @@ void ffDetectSwap(FFMemoryStorage* swap) { if(!(pstart = (SYSTEM_PAGEFILE_INFORMATION*)realloc(pstart, size))) { - ffStrbufAppendF(&swap->error, "relloc(pstart, %lu) failed", size); + ffStrbufAppendF(&swap->error, "realloc(pstart, %lu) failed", size); return; } } From 304f171d383ac6db2966c0200c5e06ee56541ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 Feb 2023 17:37:04 +0800 Subject: [PATCH 115/119] Battery / Wifi (Android): add more debug messages --- src/detection/battery/battery_android.c | 12 +++++++++--- src/detection/wifi/wifi_android.c | 10 ++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index 0c4772c3e..d8c56e836 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -4,16 +4,22 @@ #include "common/processing.h" #include "common/properties.h" +#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" +#define FF_TERMUX_API_PARAM "BatteryStatus" + const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results) { FF_STRBUF_AUTO_DESTROY buffer; ffStrbufInit(&buffer); if(ffProcessAppendStdOut(&buffer, (char* const[]){ - FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api", - "BatteryStatus" + FF_TERMUX_API_PATH, + FF_TERMUX_API_PARAM })) - return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " BatteryStatus` failed"; + return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed"; + + if(buffer.length == 0) + return "`" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` prints empty"; BatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index af1012fe7..5a304de4c 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -3,16 +3,22 @@ #include "common/processing.h" #include "common/properties.h" +#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" +#define FF_TERMUX_API_PARAM "WifiConnectionInfo" + const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result) { FF_STRBUF_AUTO_DESTROY buffer; ffStrbufInit(&buffer); if(ffProcessAppendStdOut(&buffer, (char* const[]){ - FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api", + FF_TERMUX_API_PATH, "WifiConnectionInfo" })) - return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " WifiConnectionInfo` failed"; + return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed"; + + if(buffer.length == 0) + return "`" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` prints empty"; FFWifiResult* item = (FFWifiResult*)ffListAdd(result); ffStrbufInit(&item->inf.description); From efdbeb585bb9ac9213279206d5abb4401eceb6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 21 Feb 2023 09:43:22 +0800 Subject: [PATCH 116/119] Battery (Android): add temperature --- src/detection/battery/battery_android.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index d8c56e836..fe081e85b 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -34,6 +34,17 @@ const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* re ffStrbufClear(&battery->status); } + if(instance->config.batteryTemp) + { + if(ffParsePropLines(buffer.chars, "\"temperature\": ", &battery->status)) + { + ffStrbufTrimRight(&battery->status, ','); + ffStrbufTrim(&battery->status, '"'); + battery->temperature = ffStrbufToDouble(&battery->status); + ffStrbufClear(&battery->status); + } + } + if(ffParsePropLines(buffer.chars, "\"status\": ", &battery->status)) { ffStrbufTrimRight(&battery->status, ','); From 92b1788825c56bcde26ff64c783cfd599c84acb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 21 Feb 2023 10:02:04 +0800 Subject: [PATCH 117/119] Platform: refactor; remove extra `/` --- src/util/platform/FFPlatform_unix.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 6d65defcb..a971d75c5 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -8,10 +8,7 @@ static void getHomeDir(FFPlatform* platform, const struct passwd* pwd) { - const char* home = getenv("HOME"); - if(!ffStrSet(home) && pwd) - home = pwd->pw_dir; - + const char* home = pwd ? pwd->pw_dir : getenv("HOME"); ffStrbufAppendS(&platform->homeDir, home); ffStrbufEnsureEndsWithC(&platform->homeDir, '/'); } @@ -44,11 +41,11 @@ static void getConfigDirs(FFPlatform* platform) ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS"); #if !defined(__APPLE__) - ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/"); + ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC "/xdg/"); #endif - ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC"/"); - ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/"); + ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC "/"); + ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF "/"); } static void getDataDirs(FFPlatform* platform) @@ -57,13 +54,13 @@ static void getDataDirs(FFPlatform* platform) ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/"); #if defined(__APPLE__) - ffPlatformPathAddHome(&platform->dataDirs, platform, "/Library/Application Support/"); + ffPlatformPathAddHome(&platform->dataDirs, platform, "Library/Application Support/"); #endif ffPlatformPathAddHome(&platform->dataDirs, platform, ""); ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); - ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/"); - ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/share/"); + ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/"); + ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/"); } static void getUserName(FFPlatform* platform, const struct passwd* pwd) From cc1260ee3cae505f7756003a8dc8ef73d6282c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 21 Feb 2023 10:21:07 +0800 Subject: [PATCH 118/119] FFvaluestore: fix UB reported by clang --- src/util/FFvaluestore.c | 2 +- src/util/FFvaluestore.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/FFvaluestore.c b/src/util/FFvaluestore.c index 6b0407500..68040045b 100644 --- a/src/util/FFvaluestore.c +++ b/src/util/FFvaluestore.c @@ -2,7 +2,7 @@ #include -typedef char KeyType[33]; //32 byte key + \0 +typedef char KeyType[32]; //31 byte key + \0 void ffValuestoreInit(FFvaluestore* vs, uint32_t valueSize) { diff --git a/src/util/FFvaluestore.h b/src/util/FFvaluestore.h index c59b584a6..4d966837c 100644 --- a/src/util/FFvaluestore.h +++ b/src/util/FFvaluestore.h @@ -10,7 +10,7 @@ typedef FFlist FFvaluestore; void ffValuestoreInit(FFvaluestore* vs, uint32_t valueSize); FF_C_NODISCARD void* ffValuestoreGet(FFvaluestore* vs, const char* key); -void* ffValuestoreSet(FFvaluestore* vs, const char* key, bool* created); //created may be NULL +FF_C_NODISCARD void* ffValuestoreSet(FFvaluestore* vs, const char* key, bool* created); //created may be NULL void ffValuestoreDestroy(FFvaluestore* vs); #endif From b1a779c17810d0d9f2b6c6f7585b4cfc9e98456c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 21 Feb 2023 15:52:56 +0800 Subject: [PATCH 119/119] Release: 1.10.0; update changelog --- CHANGELOG.md | 6 +++++- CMakeLists.txt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e06ed50..425678945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# dev +# 1.10.0 Notable Changes: @@ -14,13 +14,17 @@ Features: * Windows 32bit compatibility * Support global configuration in MSYS2 environment (Windows) * Support GPU driver version detection on Windows 11 +* Support scaled resolution detection for wayland (Linux) Bugfixes: +* Fix build with older libnm versions * Fix a rare case that fails to detect terminal * Fix Muffin detection (@Zerogiven, #411) * Fix IPv6 detection (Windows) * Fix scoop package count detection when scoop is installed in non-default path (Windows, #417) +* Fix UB reported by clang +* Honor $SCOOP when detecting scoop packages (#417) Other: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0446e4419..6cd942949 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 1.9.1 + VERSION 1.10.0 LANGUAGES C DESCRIPTION "Fast system information tool" HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"