From 985264d485c53ad554d3cf1a1c301b8584388bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Oct 2023 23:19:44 +0800 Subject: [PATCH 01/74] Fastfetch: add `Directx Headers` to `--list-features` --- src/common/init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/init.c b/src/common/init.c index 35f1467fc4..4510a261ef 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -469,6 +469,9 @@ void ffListFeatures(void) #ifdef FF_HAVE_DDCUTIL "libddcutil\n" #endif + #ifdef FF_HAVE_DIRECTX_HEADERS + "Directx Headers\n" + #endif "" , stdout); } From 19855526360effc4460232e0d6d26a9a2e3fba3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 3 Oct 2023 16:50:57 +0800 Subject: [PATCH 02/74] Disk (Windows): fix crashing on Windows 7 VM --- src/detection/disk/disk_windows.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index dadb7d3aec..35f1722c49 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -38,6 +38,7 @@ const char* ffDetectDisksImpl(FFlist* disks) if (handle != INVALID_HANDLE_VALUE) { DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; + DWORD retSize = 0; if(DeviceIoControl( handle, IOCTL_STORAGE_QUERY_PROPERTY, @@ -48,9 +49,9 @@ const char* ffDetectDisksImpl(FFlist* disks) sizeof(STORAGE_PROPERTY_QUERY), &dspd, sizeof(dspd), - NULL, + &retSize, NULL - )) + ) && retSize == sizeof(dspd)) disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD; } } From be860064c562109b584dc9fd6a86e015d7981073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 3 Oct 2023 17:01:57 +0800 Subject: [PATCH 03/74] Users (Windows): fix crashing caused by uninitialized strings --- src/detection/users/users_windows.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index a891520b11..21e4353a12 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -28,17 +28,17 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitWS(&user->name, session->pUserName); ffStrbufInitWS(&user->hostName, session->pHostName); + ffStrbufInitS(&user->clientIp, "0.0.0.0"); + user->loginTime = 0; DWORD bytes = 0; PWTS_CLIENT_ADDRESS address = NULL; if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSClientAddress, (LPWSTR *) &address, &bytes)) { if (address->AddressFamily == 2 /*AF_INET*/) - ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]); + ffStrbufSetF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]); WTSFreeMemory(address); } - else - ffStrbufInitS(&user->clientIp, "0.0.0.0"); bytes = 0; PWTSINFOW wtsInfo = NULL; @@ -47,8 +47,6 @@ const char* ffDetectUsers(FFlist* users) user->loginTime = to_ms(*(uint64_t*) &wtsInfo->LogonTime); WTSFreeMemory(wtsInfo); } - else - user->loginTime = 0; } WTSFreeMemoryExW(WTSTypeSessionInfoLevel1, sessionInfo, 1); From 3eb9acea2e4a14aab647469f605ebcdcd2796933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 3 Oct 2023 17:04:08 +0800 Subject: [PATCH 04/74] Doc: update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index feeaeb4723..5f0e41a06a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 2.1.1 + +Bugfixes: +* Fix possible crashes on Windows 7 (Disk, Windows) +* Fix possible crashes caused by uninitialized strings (Users, Windows) + # 2.1.0 This release introduces a new output format: JSON result From 1a4eb251943fb069cdaad14ffe996d3e80cf2438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Oct 2023 10:55:52 +0800 Subject: [PATCH 05/74] DisplayServer (Linux): add debug log for #568 --- .../displayserver/linux/displayserver_linux.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 3c93d29c02..bc54d18a24 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -1,5 +1,6 @@ #include "displayserver_linux.h" #include "common/io/io.h" +#include "common/time.h" #include "util/edidHelper.h" #include "util/stringUtils.h" @@ -80,6 +81,8 @@ static void parseDRM(FFDisplayServerResult* result) void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { + uint64_t start = ffTimeGetTick(); + printf("DS start: %lums\n", ffTimeGetTick() - start); ffStrbufInit(&ds->wmProcessName); ffStrbufInit(&ds->wmPrettyName); ffStrbufInit(&ds->wmProtocolName); @@ -90,10 +93,12 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) if (!instance.config.dsForceDrm) { + printf("DS Wayland start: %lums\n", ffTimeGetTick() - start); //We try wayland as our prefered display server, as it supports the most features. //This method can't detect the name of our WM / DE ffdsConnectWayland(ds); + printf("DS XcbRandr start: %lums\n", ffTimeGetTick() - start); //Try the x11 libs, from most feature rich to least. //We use the display list to detect if a connection is needed. //They respect wmProtocolName, and only detect display if it is set. @@ -101,21 +106,27 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) if(ds->displays.length == 0) ffdsConnectXcbRandr(ds); + printf("DS Xrandr start: %lums\n", ffTimeGetTick() - start); if(ds->displays.length == 0) ffdsConnectXrandr(ds); + printf("DS Xcb start: %lums\n", ffTimeGetTick() - start); if(ds->displays.length == 0) ffdsConnectXcb(ds); + printf("DS Xlib start: %lums\n", ffTimeGetTick() - start); if(ds->displays.length == 0) ffdsConnectXlib(ds); } + printf("DS DRM start: %lums\n", ffTimeGetTick() - start); //This display detection method is display server independent. //Use it if all connections failed if(ds->displays.length == 0) parseDRM(ds); + printf("DS WMDE start: %lums\n", ffTimeGetTick() - start); //This fills in missing information about WM / DE by using env vars and iterating processes ffdsDetectWMDE(ds); + printf("DS end: %lums\n", ffTimeGetTick() - start); } From 4a89b921855d3bf6f683c5b75a1a8383df91c958 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 3 Oct 2023 21:40:38 +0800 Subject: [PATCH 06/74] Disk: allow custiomize disk key with `mountFrom` --- src/modules/disk/disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index e6c976f0eb..ca671bca78 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -34,9 +34,10 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) } else { - ffParseFormatString(&key, &options->moduleArgs.key, 2, (FFformatarg[]){ + ffParseFormatString(&key, &options->moduleArgs.key, 3, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &disk->mountpoint}, {FF_FORMAT_ARG_TYPE_STRBUF, &disk->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &disk->mountFrom}, }); } From 27581d92b5f58d71e285411e1bec2700619aacc3 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 3 Oct 2023 22:10:22 +0800 Subject: [PATCH 07/74] Disk (macOS): detect physical type --- src/detection/disk/disk_bsd.c | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 55fc94a2e6..461b31861f 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -21,8 +21,12 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk) disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; } #elif __APPLE__ +#include "util/apple/cf_helpers.h" + #include #include +#include +#include struct VolAttrBuf { uint32_t length; @@ -30,6 +34,52 @@ struct VolAttrBuf { char volNameSpace[MAXPATHLEN]; } __attribute__((aligned(4), packed)); +void detectDiskType(FFDisk* disk) // Not thread safe +{ + if (!ffStrbufStartsWithS(&disk->mountFrom, "/dev/disk")) return; + + static uint8_t cache[100]; // disk_id => physical_type + 1 + const char* numStart = disk->mountFrom.chars + strlen("/dev/disk"); + char* numEnd = NULL; + unsigned long diskId = strtoul(numStart, &numEnd, 10); + if (numEnd == numStart || diskId >= 100) + return; + + if (cache[diskId]) + { + disk->physicalType = cache[diskId] - 1; + return; + } + + io_iterator_t iterator; + char temp = *numEnd; *numEnd = '\0'; // Check for root disk directly + CFMutableDictionaryRef matchDict = IOBSDNameMatching(MACH_PORT_NULL, 0, disk->mountFrom.chars + strlen("/dev/")); + *numEnd = temp; + if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) == kIOReturnSuccess) + { + for (io_registry_entry_t registryEntry = IOIteratorNext(iterator); registryEntry; IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, ®istryEntry)) + { + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = (CFDictionaryRef) IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions); + if (!deviceCharacteristics) + continue; + + CFStringRef diskType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); + if (diskType) + { + if (CFStringCompare(diskType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0) + disk->physicalType = FF_DISK_PHYSICAL_TYPE_SSD; + else if (CFStringCompare(diskType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0) + disk->physicalType = FF_DISK_PHYSICAL_TYPE_HDD; + } + break; + } + + IOObjectRelease(iterator); + } + + cache[diskId] = (uint8_t) (disk->physicalType + 1); +} + void detectFsInfo(struct statfs* fs, FFDisk* disk) { if(fs->f_flags & MNT_DONTBROWSE) @@ -45,6 +95,8 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk) .volattr = ATTR_VOL_INFO | ATTR_VOL_NAME, }, &attrBuf, sizeof(attrBuf), 0) == 0) ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace); + + detectDiskType(disk); } #endif From f8aafb7ce45715d27d764719633282776108b9bc Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 4 Oct 2023 00:28:49 +0800 Subject: [PATCH 08/74] Monitor (macOS): better intel platform support --- src/detection/monitor/monitor_apple.m | 150 ++++++++------------------ 1 file changed, 46 insertions(+), 104 deletions(-) diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 8f931a98d5..9d9ceb4bc6 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -9,131 +9,73 @@ extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); -static const char* detectWithDisplayServices(const FFDisplayServerResult* displayServer, FFlist* results) +static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) { - if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available"; - - FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) + NSScreen* mainScreen = NSScreen.mainScreen; + if (display->primary) + return mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; + else { - if (display->type == FF_DISPLAY_TYPE_BUILTIN) + for (NSScreen* screen in NSScreen.screens) { - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id); - if(displayInfo) + if (screen == mainScreen) continue; + NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"]; + if (screenNumber && screenNumber.longValue == (long) display->id) { - int width, height; - if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) || // Default resolution (limited by connectors, GPUs, etc.) - ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) || - width <= 0 || height <= 0) - continue; - - FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); - monitor->width = (uint32_t) width; - monitor->height = (uint32_t) height; - ffStrbufInitCopy(&monitor->name, &display->name); - - CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id); - monitor->physicalWidth = (uint32_t) (size.width + 0.5); - monitor->physicalHeight = (uint32_t) (size.height + 0.5); - monitor->hdrCompatible = false; - - if (CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance"))) - monitor->hdrCompatible = true; - else - { - NSScreen* mainScreen = NSScreen.mainScreen; - if (display->primary) - monitor->hdrCompatible = mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; - else - { - for (NSScreen* screen in NSScreen.screens) - { - if (screen == mainScreen) continue; - NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"]; - if (screenNumber && screenNumber.longValue == (long) display->id) - { - monitor->hdrCompatible = screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; - break; - } - } - continue; - } - } + return screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; } } } - return NULL; + return false; } -static const char* detectWithDdcci(FFlist* results) +const char* ffDetectMonitor(FFlist* results) { - if (!IOAVServiceCreate || !IOAVServiceReadI2C) - return "IOAVService is not available"; - - CFMutableDictionaryRef matchDict = IOServiceMatching("DCPAVServiceProxy"); - if (matchDict == NULL) - return "IOServiceMatching(\"DCPAVServiceProxy\") failed"; - - io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) - return "IOServiceGetMatchingServices() failed"; + if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available"; - FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate(); + const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); - io_registry_entry_t registryEntry; - while((registryEntry = IOIteratorNext(iterator)) != 0) + FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) { - CFMutableDictionaryRef properties; - if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) - { - IOObjectRelease(registryEntry); - continue; - } + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id); + if(!displayInfo) continue; - ffStrbufClear(&location); - if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded")) + uint8_t edidData[128] = {}; + uint32_t edidLength = 0; + if (false || !ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength)) { - // Builtin display should be handled by DisplayServices - IOObjectRelease(registryEntry); - continue; + uint32_t width, height; + ffEdidGetPhysicalResolution(edidData, &width, &height); + if (width > 0 && height > 0) + { + FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); + ffStrbufInitCopy(&monitor->name, &display->name); + monitor->width = width; + monitor->height = height; + ffEdidGetPhysicalSize(edidData, &monitor->physicalWidth, &monitor->physicalHeight); + monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || + detectHdrSupportWithNSScreen(display); + continue; + } } - FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry); - IOObjectRelease(registryEntry); - - if (!service) continue; - - FF_CFTYPE_AUTO_RELEASE CFDataRef edid = NULL; - if (IOAVServiceCopyEDID(service, &edid) != KERN_SUCCESS) - continue; - - uint32_t edidLength = (uint32_t) CFDataGetLength(edid); - if (edidLength == 0 || edidLength % 128 != 0) + int width, height; + if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) || // Default resolution (limited by connectors, GPUs, etc.) + ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) || + width <= 0 || height <= 0) continue; - uint32_t width, height; - const uint8_t* edidData = CFDataGetBytePtr(edid); + FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); + monitor->width = (uint32_t) width; + monitor->height = (uint32_t) height; + ffStrbufInitCopy(&monitor->name, &display->name); - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width == 0 || height == 0) continue; - - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - display->width = width; - display->height = height; - ffStrbufInit(&display->name); - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, edidLength); + CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id); + monitor->physicalWidth = (uint32_t) (size.width + 0.5); + monitor->physicalHeight = (uint32_t) (size.height + 0.5); + monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || + detectHdrSupportWithNSScreen(display); } - return NULL; -} - -const char* ffDetectMonitor(FFlist* results) -{ - const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); - - detectWithDisplayServices(displayServer, results); - if (displayServer->displays.length > results->length) - detectWithDdcci(results); return NULL; } From 8795d99f795c7141a287c227dbc97afb25ec4f16 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 4 Oct 2023 14:41:06 +0800 Subject: [PATCH 09/74] Brightness: add DDC/CI support for Intel Doesn't work for me. Need more testing --- src/detection/brightness/brightness_apple.c | 92 +++++++++++++++++++-- src/detection/monitor/monitor_apple.m | 2 +- src/util/apple/ddcci.h | 15 ---- 3 files changed, 88 insertions(+), 21 deletions(-) delete mode 100644 src/util/apple/ddcci.h diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index a3b1d3c8f2..947115bfb9 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -1,9 +1,27 @@ #include "brightness.h" #include "detection/displayserver/displayserver.h" #include "util/apple/cf_helpers.h" -#include "util/apple/ddcci.h" #include "util/edidHelper.h" +#include + +// DDC/CI +#ifdef __aarch64__ +typedef CFTypeRef IOAVServiceRef; +extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import)); +extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import)); +extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import)); +extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import)); +extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import)); +#else +// DDC/CI (Intel) +#include +#include +#include +extern void CGSServiceForDisplayNumber(CGDirectDisplayID display, io_service_t* service) __attribute__((weak_import)); +#endif + +// ACPI extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import)); // Works for internal display @@ -31,9 +49,10 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa return NULL; } +#ifdef __aarch64__ // https://github.com/waydabber/m1ddc // Works for Apple Silicon and USB-C adapter connection ( but not HTMI ) -FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result) +static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFlist* result) { if (!IOAVServiceCreate || !IOAVServiceReadI2C) return "IOAVService is not available"; @@ -105,6 +124,71 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result) return NULL; } +#else +static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) +{ + if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available"; + + FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) + { + if (display->type == FF_DISPLAY_TYPE_EXTERNAL) + { + io_service_t framebuffer = 0; + CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer); + if (framebuffer == 0) continue; + + IOItemCount count; + if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue; + + io_service_t interface = 0; + if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; + + uint8_t i2cOut[12] = {}; + IOI2CConnectRef connect; + if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) + { + IOObjectRelease(interface); + continue; + } + + uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; + i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; + + IOI2CRequest request = { + .commFlags = kNilOptions, + .sendAddress = 0x6e, + .sendTransactionType = kIOI2CSimpleTransactionType, + .sendBuffer = (vm_address_t) i2cIn, + .sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]), + .minReplyDelay = 10, + .replyAddress = 0x6F, + .replySubAddress = 0x51, + .replyTransactionType = kIOI2CDDCciReplyTransactionType, + .replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]), + .replyBuffer = (vm_address_t) i2cOut, + }; + IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); + IOI2CInterfaceClose(connect, kNilOptions); + IOObjectRelease(interface); + + if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue; + + if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; + + uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9]; + uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; + + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + brightness->max = max; + brightness->min = 0; + brightness->current = current; + ffStrbufInitCopy(&brightness->name, &display->name); + } + } + + return NULL; +} +#endif const char* ffDetectBrightness(FFlist* result) { @@ -112,10 +196,8 @@ const char* ffDetectBrightness(FFlist* result) detectWithDisplayServices(displayServer, result); - #ifdef __aarch64__ if (displayServer->displays.length > result->length) - detectWithDdcci(result); - #endif + detectWithDdcci(displayServer, result); return NULL; } diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 9d9ceb4bc6..be3b51a465 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -1,11 +1,11 @@ #include "monitor.h" #include "detection/displayserver/displayserver.h" #include "util/apple/cf_helpers.h" -#include "util/apple/ddcci.h" #include "util/edidHelper.h" #import #import +#import extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); diff --git a/src/util/apple/ddcci.h b/src/util/apple/ddcci.h deleted file mode 100644 index a0de174828..0000000000 --- a/src/util/apple/ddcci.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#ifndef FASTFETCH_INCLUDED_util_apple_ddcci_h - -#include - -// DDC/CI -typedef CFTypeRef IOAVServiceRef; -extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import)); -extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import)); -extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import)); -extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import)); -extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import)); - -#endif From 9972c61bbe535a8b78fd58dc3ea77b45265a3093 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 4 Oct 2023 14:59:13 +0800 Subject: [PATCH 10/74] Sound (macOS): support non-controllable devices --- src/detection/sound/sound_apple.c | 39 ++++++++++++++++++------------- src/modules/sound/sound.c | 7 +++++- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index 8f23f2a3aa..092d4479d1 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -32,21 +32,40 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */) { AudioDeviceID deviceId = deviceIds[index]; - uint32_t muted; - dataSize = sizeof(muted); + FF_CFTYPE_AUTO_RELEASE CFStringRef name = NULL; + dataSize = sizeof(name); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ - kAudioDevicePropertyMute, + kAudioObjectPropertyName, kAudioObjectPropertyScopeOutput, kAudioObjectPropertyElementMain - }, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError) + }, 0, NULL, &dataSize, &name) != kAudioHardwareNoError) continue; + uint32_t connected; + dataSize = sizeof(connected); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyJackIsConnected, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &connected) == kAudioHardwareNoError) + if (!connected) continue; + FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = deviceId == mainDeviceId; device->active = false; device->volume = FF_SOUND_VOLUME_UNKNOWN; ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId); ffStrbufInit(&device->name); + ffCfStrGetString(name, &device->name); + + uint32_t muted; + dataSize = sizeof(muted); + if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyMute, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, &muted) != kAudioHardwareNoError) + muted = false; // Device may not support volume control uint32_t active; dataSize = sizeof(active); @@ -96,18 +115,6 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */) } } } - - CFStringRef name; - dataSize = sizeof(name); - if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ - kAudioObjectPropertyName, - kAudioObjectPropertyScopeOutput, - kAudioObjectPropertyElementMain - }, 0, NULL, &dataSize, &name) == kAudioHardwareNoError) - { - ffCfStrGetString(name, &device->name); - CFRelease(name); - } } return NULL; diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 3796a7365a..6157c32d3c 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -173,7 +173,12 @@ void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_bool(doc, obj, "active", item->active); yyjson_mut_obj_add_bool(doc, obj, "main", item->main); - yyjson_mut_obj_add_uint(doc, obj, "volume", item->volume); + + if (item->volume != FF_SOUND_VOLUME_UNKNOWN) + yyjson_mut_obj_add_uint(doc, obj, "volume", item->volume); + else + yyjson_mut_obj_add_null(doc, obj, "volumne"); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier); } From f78f97a726bd8706109249906d522eac963bf4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 4 Oct 2023 16:28:54 +0800 Subject: [PATCH 11/74] Revert "DisplayServer (Linux): add debug log for #568" This reverts commit 1a4eb251943fb069cdaad14ffe996d3e80cf2438. --- .../displayserver/linux/displayserver_linux.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index bc54d18a24..3c93d29c02 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -1,6 +1,5 @@ #include "displayserver_linux.h" #include "common/io/io.h" -#include "common/time.h" #include "util/edidHelper.h" #include "util/stringUtils.h" @@ -81,8 +80,6 @@ static void parseDRM(FFDisplayServerResult* result) void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { - uint64_t start = ffTimeGetTick(); - printf("DS start: %lums\n", ffTimeGetTick() - start); ffStrbufInit(&ds->wmProcessName); ffStrbufInit(&ds->wmPrettyName); ffStrbufInit(&ds->wmProtocolName); @@ -93,12 +90,10 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) if (!instance.config.dsForceDrm) { - printf("DS Wayland start: %lums\n", ffTimeGetTick() - start); //We try wayland as our prefered display server, as it supports the most features. //This method can't detect the name of our WM / DE ffdsConnectWayland(ds); - printf("DS XcbRandr start: %lums\n", ffTimeGetTick() - start); //Try the x11 libs, from most feature rich to least. //We use the display list to detect if a connection is needed. //They respect wmProtocolName, and only detect display if it is set. @@ -106,27 +101,21 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) if(ds->displays.length == 0) ffdsConnectXcbRandr(ds); - printf("DS Xrandr start: %lums\n", ffTimeGetTick() - start); if(ds->displays.length == 0) ffdsConnectXrandr(ds); - printf("DS Xcb start: %lums\n", ffTimeGetTick() - start); if(ds->displays.length == 0) ffdsConnectXcb(ds); - printf("DS Xlib start: %lums\n", ffTimeGetTick() - start); if(ds->displays.length == 0) ffdsConnectXlib(ds); } - printf("DS DRM start: %lums\n", ffTimeGetTick() - start); //This display detection method is display server independent. //Use it if all connections failed if(ds->displays.length == 0) parseDRM(ds); - printf("DS WMDE start: %lums\n", ffTimeGetTick() - start); //This fills in missing information about WM / DE by using env vars and iterating processes ffdsDetectWMDE(ds); - printf("DS end: %lums\n", ffTimeGetTick() - start); } From 1dfa0315dbbb9b9158e14879b5a6ffea1d6129b1 Mon Sep 17 00:00:00 2001 From: Md Rasel Hossain <77199897+iamrasel@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:59:24 +0600 Subject: [PATCH 12/74] Fix several `--help` command related issues (#572) * Help: fix wrong output for irrelevant commands * Help: fix `module-format` related issues * Help: remove unnecessary code --- src/fastfetch.c | 72 +++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index c956357ebe..bff53eff7d 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -94,7 +94,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "bios-format")) { - constructAndPrintCommandHelpFormat("bios", "{2} {3}", 4, + constructAndPrintCommandHelpFormat("bios", "{4} ({2})", 4, "bios date", "bios release", "bios vendor", @@ -103,7 +103,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "board-format")) { - constructAndPrintCommandHelpFormat("board", "{2} {3}", 3, + constructAndPrintCommandHelpFormat("board", "{1} ({3})", 3, "board name", "board vendor", "board version" @@ -111,7 +111,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "chassis-format")) { - constructAndPrintCommandHelpFormat("chassis", "{2} {3}", 4, + constructAndPrintCommandHelpFormat("chassis", "{1}", 3, "chassis type", "chassis vendor", "chassis version" @@ -127,7 +127,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "uptime-format")) { - constructAndPrintCommandHelpFormat("uptime", "{} days {} hours {} mins", 4, + constructAndPrintCommandHelpFormat("uptime", "{1} days {2} hours {3} mins", 4, "Days", "Hours", "Minutes", @@ -136,7 +136,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "processes-format")) { - constructAndPrintCommandHelpFormat("processes", "{}", 1, + constructAndPrintCommandHelpFormat("processes", "{1}", 1, "Count" ); } @@ -182,7 +182,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "display-format")) { - constructAndPrintCommandHelpFormat("display", "{}x{} @ {}Hz", 7, + constructAndPrintCommandHelpFormat("display", "{1}x{2} @ {3}Hz", 8, "Screen width", "Screen height", "Screen refresh rate", @@ -202,7 +202,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "monitor-format")) { - constructAndPrintCommandHelpFormat("monitor", "{}", 6, + constructAndPrintCommandHelpFormat("monitor", "{2}x{3} px - {4}x{5} mm ({6} inches, {7} ppi)", 7, "Display name", "Display native resolution width in pixels", "Display native resolution height in pixels", @@ -230,31 +230,31 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "wmtheme-format")) { - constructAndPrintCommandHelpFormat("wmtheme", "{}", 1, + constructAndPrintCommandHelpFormat("wmtheme", "{1}", 1, "WM theme name" ); } else if(ffStrEqualsIgnCase(command, "theme-format")) { - constructAndPrintCommandHelpFormat("theme", "{}", 1, + constructAndPrintCommandHelpFormat("theme", "{1}", 1, "Combined themes" ); } else if(ffStrEqualsIgnCase(command, "icons-format")) { - constructAndPrintCommandHelpFormat("icons", "{}", 1, + constructAndPrintCommandHelpFormat("icons", "{1}", 1, "Combined icons" ); } else if(ffStrEqualsIgnCase(command, "wallpaper-format")) { - constructAndPrintCommandHelpFormat("wallpaper", "{}", 1, + constructAndPrintCommandHelpFormat("wallpaper", "{1}", 1, "Wallpaper image file" ); } else if(ffStrEqualsIgnCase(command, "font-format")) { - constructAndPrintCommandHelpFormat("font", "{} [QT], {} [GTK2], {} [GTK3], {} [GTK4]", 4, + constructAndPrintCommandHelpFormat("font", "{1} [QT], {2} [GTK2], {3} [GTK3], {4} [GTK4]", 4, "Font 1", "Font 2", "Font 3", @@ -263,14 +263,14 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "cursor-format")) { - constructAndPrintCommandHelpFormat("cursor", "{} ({}pt)", 2, + constructAndPrintCommandHelpFormat("cursor", "{1}", 2, "Cursor theme", "Cursor size" ); } else if(ffStrEqualsIgnCase(command, "terminal-format")) { - constructAndPrintCommandHelpFormat("terminal", "{3}", 10, + constructAndPrintCommandHelpFormat("terminal", "{5} {6}", 6, "Terminal process name", "Terminal path with exe name", "Terminal exe name", @@ -281,7 +281,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "terminalfont-format")) { - constructAndPrintCommandHelpFormat("terminalfont", "{}", 4, + constructAndPrintCommandHelpFormat("terminalfont", "{1}", 4, "Terminal font", "Terminal font name", "Termianl font size", @@ -290,7 +290,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "cpu-format")) { - constructAndPrintCommandHelpFormat("cpu", "{1} ({5}) @ {7}GHz", 8, + constructAndPrintCommandHelpFormat("cpu", "{1} ({5}) @ {7} GHz", 8, "Name", "Vendor", "Physical core count", @@ -303,13 +303,13 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "cpuusage-format")) { - constructAndPrintCommandHelpFormat("cpuusage", "{0}%", 1, + constructAndPrintCommandHelpFormat("cpuusage", "{1}", 1, "CPU usage without percent mark" ); } else if(ffStrEqualsIgnCase(command, "gpu-format")) { - constructAndPrintCommandHelpFormat("gpu", "{} {}", 6, + constructAndPrintCommandHelpFormat("gpu", "{1} {2}", 6, "GPU vendor", "GPU name", "GPU driver", @@ -320,7 +320,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "memory-format")) { - constructAndPrintCommandHelpFormat("memory", "{} / {} ({}%)", 3, + constructAndPrintCommandHelpFormat("memory", "{1} / {2} ({3})", 3, "Used size", "Total size", "Percentage used" @@ -328,7 +328,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "swap-format")) { - constructAndPrintCommandHelpFormat("swap", "{} / {} ({}%)", 3, + constructAndPrintCommandHelpFormat("swap", "{1} / {2} ({3})", 3, "Used size", "Total size", "Percentage used" @@ -336,7 +336,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "disk-format")) { - constructAndPrintCommandHelpFormat("disk", "{1} / {2} ({3}%)", 9, + constructAndPrintCommandHelpFormat("disk", "{1} / {2} ({3}) - {9}", 9, "Size used", "Size total", "Size percentage", @@ -370,20 +370,21 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "lm-format")) { - constructAndPrintCommandHelpFormat("lm", "{} ({})", 2, + constructAndPrintCommandHelpFormat("lm", "{1} {3} ({2})", 3, "LM service", - "LM type" + "LM type", + "LM version" ); } else if(ffStrEqualsIgnCase(command, "locale-format")) { - constructAndPrintCommandHelpFormat("locale", "{}", 1, + constructAndPrintCommandHelpFormat("locale", "{1}", 1, "Locale code" ); } else if(ffStrEqualsIgnCase(command, "localip-format")) { - constructAndPrintCommandHelpFormat("localip", "{}", 5, + constructAndPrintCommandHelpFormat("localip", "{1}{5}", 5, "Local IPv4 address", "Local IPv6 address", "Physical (MAC) address", @@ -393,13 +394,14 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "publicip-format")) { - constructAndPrintCommandHelpFormat("publicip", "{}", 1, - "Public IP address" + constructAndPrintCommandHelpFormat("publicip", "{1} ({2})", 2, + "Public IP address", + "Location" ); } else if(ffStrEqualsIgnCase(command, "netio-format")) { - constructAndPrintCommandHelpFormat("netio", "{}", 3, + constructAndPrintCommandHelpFormat("netio", "{1} (IN) - {2} (OUT){4}", 4, "Size of data received per second (formatted)", "Size of data sent per second (formatted)", "Interface name", @@ -408,7 +410,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "wifi-format")) { - constructAndPrintCommandHelpFormat("wifi", "{4} - {6}", 3, + constructAndPrintCommandHelpFormat("wifi", "{4} - {10}", 10, "Interface description", "Interface status", "Connection status", @@ -439,7 +441,7 @@ static inline void printCommandHelp(const char* command) "Album name" ); } - else if(ffStrEqualsIgnCase(command, "datetime-format") == 0 || ffStrEqualsIgnCase(command, "date-format") || ffStrEqualsIgnCase(command, "time-format")) + else if(ffStrEqualsIgnCase(command, "datetime-format")) { constructAndPrintCommandHelpFormat("[date][time]", "{1}-{4}-{11} {14}:{18}:{20}", 20, "year", @@ -466,7 +468,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "version-format")) { - constructAndPrintCommandHelpFormat("version", "{1} {2}{3} (5)", 6, + constructAndPrintCommandHelpFormat("version", "{1} {2}{3} ({5})", 8, "Project name", "Version", "Version tweak", @@ -487,7 +489,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "opengl-format")) { - constructAndPrintCommandHelpFormat("opengl", "{}", 3, + constructAndPrintCommandHelpFormat("opengl", "{1}", 4, "version", "renderer", "vendor", @@ -513,7 +515,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "sound-format")) { - constructAndPrintCommandHelpFormat("sound", "{2} (3%)", 4, + constructAndPrintCommandHelpFormat("sound", "{2} ({3}%)", 4, "Main", "Name", "Volume", @@ -522,13 +524,13 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "gamepad-format")) { - constructAndPrintCommandHelpFormat("gamepad", "{1}", 1, + constructAndPrintCommandHelpFormat("gamepad", "{1}", 2, "Name", "Identifier" ); } else - fprintf(stderr, "No specific help for command %s provided\n", command); + fprintf(stderr, "No specific help for command '%s' provided\n", command); } static void listAvailablePresets(void) From 23d2cc3fdc1d1531174a67b0dd708b05a5cba43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 5 Oct 2023 19:06:15 +0800 Subject: [PATCH 13/74] Version: print libc version used when compiling --- CMakeLists.txt | 5 +++ src/detection/libc/libc.h | 16 +++++++ src/detection/libc/libc_android.c | 25 +++++++++++ src/detection/libc/libc_linux.c | 19 +++++++++ src/detection/libc/libc_nosupport.c | 9 ++++ src/detection/libc/libc_windows.cpp | 65 +++++++++++++++++++++++++++++ src/fastfetch.c | 2 +- src/modules/version/version.c | 32 +++++++++++++- 8 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 src/detection/libc/libc.h create mode 100644 src/detection/libc/libc_android.c create mode 100644 src/detection/libc/libc_linux.c create mode 100644 src/detection/libc/libc_nosupport.c create mode 100644 src/detection/libc/libc_windows.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 04eebf6797..47af8e6afb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -385,6 +385,7 @@ if(LINUX) src/detection/gtk_qt/gtk.c src/detection/host/host_linux.c src/detection/icons/icons_linux.c + src/detection/libc/libc_linux.c src/detection/lm/lm_linux.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_linux.c @@ -433,6 +434,7 @@ elseif(ANDROID) src/detection/gpu/gpu_nosupport.c src/detection/host/host_android.c src/detection/icons/icons_nosupport.c + src/detection/libc/libc_android.c src/detection/lm/lm_nosupport.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_nosupport.c @@ -488,6 +490,7 @@ elseif(BSD) src/detection/host/host_bsd.c src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c + src/detection/libc/libc_nosupport.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c @@ -537,6 +540,7 @@ elseif(APPLE) src/detection/host/host_apple.c src/detection/lm/lm_nosupport.c src/detection/icons/icons_nosupport.c + src/detection/libc/libc_nosupport.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m @@ -585,6 +589,7 @@ elseif(WIN32) src/detection/gpu/gpu_windows.c src/detection/host/host_windows.c src/detection/icons/icons_windows.c + src/detection/libc/libc_windows.cpp src/detection/lm/lm_nosupport.c src/detection/localip/localip_windows.c src/detection/gamepad/gamepad_windows.c diff --git a/src/detection/libc/libc.h b/src/detection/libc/libc.h new file mode 100644 index 0000000000..dc89cc2be9 --- /dev/null +++ b/src/detection/libc/libc.h @@ -0,0 +1,16 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_libc_libc +#define FF_INCLUDED_detection_libc_libc + +#include "fastfetch.h" + +typedef struct FFLibcResult +{ + const char* name; + const char* version; +} FFLibcResult; + +const char* ffDetectLibc(FFLibcResult* result); + +#endif diff --git a/src/detection/libc/libc_android.c b/src/detection/libc/libc_android.c new file mode 100644 index 0000000000..845a66fa4b --- /dev/null +++ b/src/detection/libc/libc_android.c @@ -0,0 +1,25 @@ +#include "libc.h" + +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +#include + +const char* ffDetectLibc(FFLibcResult* result) +{ +#if __ANDROID_NDK__ + result->name = "ndk-bionic"; + result->version = FF_STR(__NDK_MAJOR__) "." FF_STR(__NDK_MINOR__) "." FF_STR(__NDK_BUILD__) + + #if __NDK_BETA__ + "-beta" FF_STR(__NDK_BETA__) + #elif __NDK_CANARY__ + "-canary" + #endif + + ; + return NULL; +#else + return "Unknown Android libc"; +#endif +} diff --git a/src/detection/libc/libc_linux.c b/src/detection/libc/libc_linux.c new file mode 100644 index 0000000000..399a678705 --- /dev/null +++ b/src/detection/libc/libc_linux.c @@ -0,0 +1,19 @@ +#include "libc.h" + +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +#include + +const char* ffDetectLibc(FFLibcResult* result) +{ +#ifdef __GNU_LIBRARY__ + result->name = "glibc"; + result->version = FF_STR(__GLIBC__) "." FF_STR(__GLIBC_MINOR__); +#else + result->name = "musl"; + result->version = NULL; +#endif + + return NULL; +} diff --git a/src/detection/libc/libc_nosupport.c b/src/detection/libc/libc_nosupport.c new file mode 100644 index 0000000000..0c6a968a3d --- /dev/null +++ b/src/detection/libc/libc_nosupport.c @@ -0,0 +1,9 @@ +#include "libc.h" + +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +const char* ffDetectLibc(FF_MAYBE_UNUSED FFLibcResult* result) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/libc/libc_windows.cpp b/src/detection/libc/libc_windows.cpp new file mode 100644 index 0000000000..8a699d7655 --- /dev/null +++ b/src/detection/libc/libc_windows.cpp @@ -0,0 +1,65 @@ +extern "C" +{ +#include "libc.h" +} + +#ifdef __MINGW32__ +#include <_mingw.h> +#endif + +template +class version_t { + constexpr static auto buflen() noexcept { + unsigned int len = 2; // "." + if (Major == 0) + len++; + else + for (auto n = Major; n; len++, n /= 10); + + if (Minor == 0) + len++; + else + for (auto n = Minor; n; len++, n /= 10); + return len; + } + + char buf[buflen()] = {}; + +public: + constexpr version_t() noexcept { + auto ptr = buf + buflen(); + *--ptr = '\0'; + + if (Minor == 0) { + *--ptr = '0'; + } else { + for (auto n = Minor; n; n /= 10) + *--ptr = "0123456789"[n % 10]; + } + *--ptr = '.'; + if (Major == 0) { + *--ptr = '0'; + } else { + for (auto n = Major; n; n /= 10) + *--ptr = "0123456789"[n % 10]; + } + } + + constexpr operator const char *() const { return buf; } +}; + +template +constexpr version_t version; + +extern "C" +const char* ffDetectLibc(FFLibcResult* result) +{ +#ifdef _UCRT + result->name = "ucrt"; +#else + result->name = "msvcrt"; +#endif + + result->version = version<(__MSVCRT_VERSION__ >> 8), (__MSVCRT_VERSION__ & 8)>; + return NULL; +} diff --git a/src/fastfetch.c b/src/fastfetch.c index bff53eff7d..d00d051207 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -468,7 +468,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "version-format")) { - constructAndPrintCommandHelpFormat("version", "{1} {2}{3} ({5})", 8, + constructAndPrintCommandHelpFormat("version", "{1} {2}{3} ({5})", 9, "Project name", "Version", "Version tweak", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 54781eb622..a5a6ca7d8b 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -1,10 +1,11 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "detection/libc/libc.h" #include "detection/version/version.h" #include "modules/version/version.h" #include "util/stringUtils.h" -#define FF_VERSION_NUM_FORMAT_ARGS 8 +#define FF_VERSION_NUM_FORMAT_ARGS 9 void ffPrintVersion(FFVersionOptions* options) { @@ -18,6 +19,18 @@ void ffPrintVersion(FFVersionOptions* options) } else { + FFLibcResult libcResult; + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + if (!ffDetectLibc(&libcResult)) + { + ffStrbufSetS(&buf, libcResult.name); + if (libcResult.version) + { + ffStrbufAppendC(&buf, ' '); + ffStrbufAppendS(&buf, libcResult.version); + } + } + ffPrintFormat(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_VERSION_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRING, result.projectName}, {FF_FORMAT_ARG_TYPE_STRING, result.version}, @@ -27,6 +40,7 @@ void ffPrintVersion(FFVersionOptions* options) {FF_FORMAT_ARG_TYPE_STRING, result.cmakeBuiltType}, {FF_FORMAT_ARG_TYPE_STRING, result.compileTime}, {FF_FORMAT_ARG_TYPE_STRING, result.compiler}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buf}, }); } } @@ -83,4 +97,20 @@ void ffGenerateVersionJson(FF_MAYBE_UNUSED FFVersionOptions* options, yyjson_mut yyjson_mut_obj_add_str(doc, obj, "compileTime", result.compileTime); yyjson_mut_obj_add_str(doc, obj, "compiler", result.compiler); yyjson_mut_obj_add_bool(doc, obj, "debugMode", result.debugMode); + + FFLibcResult libcResult; + if (ffDetectLibc(&libcResult)) + { + yyjson_mut_obj_add_null(doc, obj, "libc"); + } + else + { + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreateS(libcResult.name); + if (libcResult.version) + { + ffStrbufAppendC(&buf, ' '); + ffStrbufAppendS(&buf, libcResult.version); + } + yyjson_mut_obj_add_strbuf(doc, obj, "libc", &buf); + } } From 12208b2c7cdffd0d531294e3e271d04e7cf4e35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 13:40:40 +0800 Subject: [PATCH 14/74] Global: improve support of `--help *-format` Also fix some bugs found when refactoring --- src/common/option.h | 5 +- src/common/printing.c | 15 + src/common/printing.h | 2 + src/fastfetch.c | 513 +----------------------- src/modules/battery/battery.c | 13 +- src/modules/battery/battery.h | 1 + src/modules/bios/bios.c | 12 +- src/modules/bios/bios.h | 1 + src/modules/bluetooth/bluetooth.c | 12 +- src/modules/bluetooth/bluetooth.h | 1 + src/modules/board/board.c | 11 +- src/modules/board/board.h | 1 + src/modules/break/break.c | 2 +- src/modules/brightness/brightness.c | 13 +- src/modules/brightness/brightness.h | 1 + src/modules/chassis/chassis.c | 11 +- src/modules/chassis/chassis.h | 1 + src/modules/colors/colors.c | 2 +- src/modules/command/command.c | 24 +- src/modules/command/command.h | 1 + src/modules/cpu/cpu.c | 16 +- src/modules/cpu/cpu.h | 1 + src/modules/cpuusage/cpuusage.c | 9 +- src/modules/cpuusage/cpuusage.h | 1 + src/modules/cursor/cursor.c | 10 +- src/modules/cursor/cursor.h | 1 + src/modules/custom/custom.c | 2 +- src/modules/datetime/datetime.c | 28 +- src/modules/datetime/datetime.h | 1 + src/modules/de/de.c | 11 +- src/modules/de/de.h | 1 + src/modules/disk/disk.c | 17 +- src/modules/disk/disk.h | 1 + src/modules/display/display.c | 16 +- src/modules/display/display.h | 1 + src/modules/font/font.c | 13 +- src/modules/font/font.h | 1 + src/modules/gamepad/gamepad.c | 10 +- src/modules/gamepad/gamepad.h | 1 + src/modules/gpu/gpu.c | 24 +- src/modules/gpu/gpu.h | 1 + src/modules/host/host.c | 13 +- src/modules/host/host.h | 1 + src/modules/icons/icons.c | 9 +- src/modules/icons/icons.h | 1 + src/modules/kernel/kernel.c | 11 +- src/modules/kernel/kernel.h | 1 + src/modules/lm/lm.c | 11 +- src/modules/lm/lm.h | 1 + src/modules/locale/locale.c | 9 +- src/modules/locale/locale.h | 1 + src/modules/localip/localip.c | 13 +- src/modules/localip/localip.h | 1 + src/modules/media/media.c | 13 +- src/modules/media/media.h | 1 + src/modules/memory/memory.c | 11 +- src/modules/memory/memory.h | 1 + src/modules/monitor/monitor.c | 15 +- src/modules/monitor/monitor.h | 1 + src/modules/netio/netio.c | 12 +- src/modules/netio/netio.h | 1 + src/modules/opencl/opencl.c | 11 +- src/modules/opencl/opencl.h | 1 + src/modules/opengl/opengl.c | 12 +- src/modules/opengl/opengl.h | 1 + src/modules/os/os.c | 20 +- src/modules/os/os.h | 1 + src/modules/packages/packages.c | 32 +- src/modules/packages/packages.h | 1 + src/modules/player/player.c | 12 +- src/modules/player/player.h | 1 + src/modules/poweradapter/poweradapter.c | 17 +- src/modules/poweradapter/poweradapter.h | 1 + src/modules/processes/processes.c | 9 +- src/modules/processes/processes.h | 1 + src/modules/publicip/publicip.c | 10 +- src/modules/publicip/publicip.h | 1 + src/modules/separator/separator.c | 2 +- src/modules/shell/shell.c | 14 +- src/modules/shell/shell.h | 1 + src/modules/sound/sound.c | 12 +- src/modules/sound/sound.h | 1 + src/modules/swap/swap.c | 11 +- src/modules/swap/swap.h | 1 + src/modules/terminal/terminal.c | 14 +- src/modules/terminal/terminal.h | 1 + src/modules/terminalfont/terminalfont.c | 12 +- src/modules/terminalfont/terminalfont.h | 1 + src/modules/terminalsize/terminalsize.c | 12 +- src/modules/terminalsize/terminalsize.h | 1 + src/modules/theme/theme.c | 9 +- src/modules/theme/theme.h | 1 + src/modules/title/title.c | 16 +- src/modules/title/title.h | 1 + src/modules/uptime/uptime.c | 12 +- src/modules/uptime/uptime.h | 1 + src/modules/users/users.c | 13 +- src/modules/users/users.h | 1 + src/modules/version/version.c | 17 +- src/modules/version/version.h | 1 + src/modules/vulkan/vulkan.c | 11 +- src/modules/vulkan/vulkan.h | 1 + src/modules/wallpaper/wallpaper.c | 9 +- src/modules/wallpaper/wallpaper.h | 1 + src/modules/weather/weather.c | 9 +- src/modules/weather/weather.h | 1 + src/modules/wifi/wifi.c | 18 +- src/modules/wifi/wifi.h | 1 + src/modules/wm/wm.c | 11 +- src/modules/wm/wm.h | 1 + src/modules/wmtheme/wmtheme.c | 9 +- src/modules/wmtheme/wmtheme.h | 1 + src/util/stringUtils.h | 9 + 113 files changed, 746 insertions(+), 557 deletions(-) diff --git a/src/common/option.h b/src/common/option.h index 3fef4995a0..47e96585cc 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -18,6 +18,7 @@ typedef struct FFModuleBaseInfo void (*parseJsonObject)(void* options, struct yyjson_val *module); void (*printModule)(void* options); void (*generateJson)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module); + void (*printHelpFormat)(void); } FFModuleBaseInfo; static inline void ffOptionInitModuleBaseInfo( @@ -26,7 +27,8 @@ static inline void ffOptionInitModuleBaseInfo( void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value) void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module) void* printModule, // void (*const printModule)(void* options) - void* generateJson // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj) + void* generateJson, // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj) + void (*printHelpFormat)(void) ) { baseInfo->name = name; @@ -34,6 +36,7 @@ static inline void ffOptionInitModuleBaseInfo( baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject; baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule; baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson; + baseInfo->printHelpFormat = printHelpFormat; } typedef struct FFModuleArgs diff --git a/src/common/printing.c b/src/common/printing.c index 0d8635f2f0..d03d7b40eb 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -132,3 +132,18 @@ void ffPrintCharTimes(char c, uint32_t times) if(remaining > 0) fwrite(str, 1, remaining, stdout); } + +void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]) +{ + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateS(name); + ffStrbufLowerCase(&buffer); + printf("--%s-format:\n", buffer.chars); + printf("Sets the format string for %s output.\n", name); + puts("To see how a format string is constructed, take a look at \"fastfetch --help format\"."); + puts("The following values are passed:"); + + for(unsigned i = 0; i < numArgs; i++) + printf(" {%u}: %s\n", i, args[i]); + + printf("The default is something similar to \"%s\".\n", def); +} diff --git a/src/common/printing.h b/src/common/printing.h index a03c555555..d9925757cd 100644 --- a/src/common/printing.h +++ b/src/common/printing.h @@ -25,4 +25,6 @@ FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex, void ffPrintColor(const FFstrbuf* colorValue); void ffPrintCharTimes(char c, uint32_t times); +void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]); + #endif diff --git a/src/fastfetch.c b/src/fastfetch.c index d00d051207..2268822b05 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -21,22 +21,23 @@ #include "modules/modules.h" -static void constructAndPrintCommandHelpFormat(const char* name, const char* def, uint32_t numArgs, ...) +static void printCommandFormatHelp(const char* command) { - va_list argp; - va_start(argp, numArgs); - - printf("--%s-format:\n", name); - printf("Sets the format string for %s output.\n", name); - puts("To see how a format string is constructed, take a look at \"fastfetch --help format\"."); - puts("The following values are passed:"); - - for(uint32_t i = 1; i <= numArgs; i++) - printf(" {%u}: %s\n", i, va_arg(argp, const char*)); - - printf("The default is something similar to \"%s\".\n", def); + FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateNS((uint32_t) (strlen(command) - strlen("-format")), command); + for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(command[0]) - 'A']; *modules; ++modules) + { + FFModuleBaseInfo* baseInfo = *modules; + if (ffStrbufIgnCaseEqualS(&type, baseInfo->name)) + { + if (baseInfo->printHelpFormat) + baseInfo->printHelpFormat(); + else + fprintf(stderr, "Error: Module '%s' doesn't support output formatting\n", baseInfo->name); + return; + } + } - va_end(argp); + fprintf(stderr, "Error: Module '%s' is not supported\n", type.chars); } static inline void printCommandHelp(const char* command) @@ -49,488 +50,10 @@ static inline void printCommandHelp(const char* command) puts(FASTFETCH_DATATEXT_HELP_FORMAT); else if(ffStrEqualsIgnCase(command, "load-config") || ffStrEqualsIgnCase(command, "config")) puts(FASTFETCH_DATATEXT_HELP_CONFIG); - else if(ffStrEqualsIgnCase(command, "title-format")) - { - constructAndPrintCommandHelpFormat("title", "{6}{7}{8}", 8, - "User name", - "Host name", - "Home directory", - "Executable path of current process", - "User's default shell", - "User name (colored)", - "@ symbol (colored)", - "Host name (colored)" - ); - } - else if(ffStrEqualsIgnCase(command, "os-format")) - { - constructAndPrintCommandHelpFormat("os", "{3} {12}", 12, - "System name (typically just Linux)", - "Name of the OS", - "Pretty name of the OS", - "ID of the OS", - "ID like of the OS", - "Variant of the OS", - "Variant ID of the OS", - "Version of the OS", - "Version ID of the OS", - "Version codename of the OS", - "Build ID of the OS", - "Architecture of the OS" - ); - } - else if(ffStrEqualsIgnCase(command, "host-format")) - { - constructAndPrintCommandHelpFormat("host", "{2} {3}", 8, - "product family", - "product name", - "product version", - "product sku", - "chassis type", - "chassis vendor", - "chassis version", - "sys vendor" - ); - } - else if(ffStrEqualsIgnCase(command, "bios-format")) - { - constructAndPrintCommandHelpFormat("bios", "{4} ({2})", 4, - "bios date", - "bios release", - "bios vendor", - "bios version" - ); - } - else if(ffStrEqualsIgnCase(command, "board-format")) - { - constructAndPrintCommandHelpFormat("board", "{1} ({3})", 3, - "board name", - "board vendor", - "board version" - ); - } - else if(ffStrEqualsIgnCase(command, "chassis-format")) - { - constructAndPrintCommandHelpFormat("chassis", "{1}", 3, - "chassis type", - "chassis vendor", - "chassis version" - ); - } - else if(ffStrEqualsIgnCase(command, "kernel-format")) - { - constructAndPrintCommandHelpFormat("kernel", "{2}", 3, - "Kernel sysname", - "Kernel release", - "Kernel version" - ); - } - else if(ffStrEqualsIgnCase(command, "uptime-format")) - { - constructAndPrintCommandHelpFormat("uptime", "{1} days {2} hours {3} mins", 4, - "Days", - "Hours", - "Minutes", - "Seconds" - ); - } - else if(ffStrEqualsIgnCase(command, "processes-format")) - { - constructAndPrintCommandHelpFormat("processes", "{1}", 1, - "Count" - ); - } - else if(ffStrEqualsIgnCase(command, "packages-format")) - { - constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget)", 24, - "Number of all packages", - "Number of pacman packages", - "Pacman branch on manjaro", - "Number of dpkg packages", - "Number of rpm packages", - "Number of emerge packages", - "Number of eopkg packages", - "Number of xbps packages", - "Number of nix-system packages", - "Number of nix-user packages", - "Number of nix-default packages", - "Number of apk packages", - "Number of pkg packages", - "Number of flatpak-system packages", - "Number of flatpak-user packages", - "Number of snap packages", - "Number of brew packages", - "Number of brew-cask packages", - "Number of macports packages", - "Number of scoop packages", - "Number of choco packages", - "Number of pkgtool packages", - "Number of paludis packages" - "Number of winget packages" - ); - } - else if(ffStrEqualsIgnCase(command, "shell-format")) - { - constructAndPrintCommandHelpFormat("shell", "{3} {4}", 6, - "Shell process name", - "Shell path with exe name", - "Shell exe name", - "Shell version", - "Shell pid", - "Shell pretty name" - ); - } - else if(ffStrEqualsIgnCase(command, "display-format")) - { - constructAndPrintCommandHelpFormat("display", "{1}x{2} @ {3}Hz", 8, - "Screen width", - "Screen height", - "Screen refresh rate", - "Screen scaled width", - "Screen scaled height", - "Screen name", - "Screen type", - "Screen rotation" - ); - } - else if(ffStrEqualsIgnCase(command, "brightness-format")) - { - constructAndPrintCommandHelpFormat("brightness", "{}", 2, - "Screen brightness", - "Screen name" - ); - } - else if(ffStrEqualsIgnCase(command, "monitor-format")) - { - constructAndPrintCommandHelpFormat("monitor", "{2}x{3} px - {4}x{5} mm ({6} inches, {7} ppi)", 7, - "Display name", - "Display native resolution width in pixels", - "Display native resolution height in pixels", - "Display physical width in millimeters", - "Display physical height in millimeters", - "Display physical diagonal length in inches", - "Display physical pixels per inch (PPI)" - ); - } - else if(ffStrEqualsIgnCase(command, "de-format")) - { - constructAndPrintCommandHelpFormat("de", "{2} {3}", 3, - "DE process name", - "DE pretty name", - "DE version" - ); - } - else if(ffStrEqualsIgnCase(command, "wm-format")) - { - constructAndPrintCommandHelpFormat("wm", "{2} ({3})", 3, - "WM process name", - "WM pretty name", - "WM protocol name" - ); - } - else if(ffStrEqualsIgnCase(command, "wmtheme-format")) - { - constructAndPrintCommandHelpFormat("wmtheme", "{1}", 1, - "WM theme name" - ); - } - else if(ffStrEqualsIgnCase(command, "theme-format")) - { - constructAndPrintCommandHelpFormat("theme", "{1}", 1, - "Combined themes" - ); - } - else if(ffStrEqualsIgnCase(command, "icons-format")) - { - constructAndPrintCommandHelpFormat("icons", "{1}", 1, - "Combined icons" - ); - } - else if(ffStrEqualsIgnCase(command, "wallpaper-format")) - { - constructAndPrintCommandHelpFormat("wallpaper", "{1}", 1, - "Wallpaper image file" - ); - } - else if(ffStrEqualsIgnCase(command, "font-format")) - { - constructAndPrintCommandHelpFormat("font", "{1} [QT], {2} [GTK2], {3} [GTK3], {4} [GTK4]", 4, - "Font 1", - "Font 2", - "Font 3", - "Font 4" - ); - } - else if(ffStrEqualsIgnCase(command, "cursor-format")) - { - constructAndPrintCommandHelpFormat("cursor", "{1}", 2, - "Cursor theme", - "Cursor size" - ); - } - else if(ffStrEqualsIgnCase(command, "terminal-format")) - { - constructAndPrintCommandHelpFormat("terminal", "{5} {6}", 6, - "Terminal process name", - "Terminal path with exe name", - "Terminal exe name", - "Terminal pid", - "Terminal pretty name", - "Terminal version" - ); - } - else if(ffStrEqualsIgnCase(command, "terminalfont-format")) - { - constructAndPrintCommandHelpFormat("terminalfont", "{1}", 4, - "Terminal font", - "Terminal font name", - "Termianl font size", - "Terminal font styles" - ); - } - else if(ffStrEqualsIgnCase(command, "cpu-format")) - { - constructAndPrintCommandHelpFormat("cpu", "{1} ({5}) @ {7} GHz", 8, - "Name", - "Vendor", - "Physical core count", - "Logical core count", - "Online core count", - "Min frequency", - "Max frequency", - "Temperature" - ); - } - else if(ffStrEqualsIgnCase(command, "cpuusage-format")) - { - constructAndPrintCommandHelpFormat("cpuusage", "{1}", 1, - "CPU usage without percent mark" - ); - } - else if(ffStrEqualsIgnCase(command, "gpu-format")) - { - constructAndPrintCommandHelpFormat("gpu", "{1} {2}", 6, - "GPU vendor", - "GPU name", - "GPU driver", - "GPU temperature", - "GPU core count", - "GPU type" - ); - } - else if(ffStrEqualsIgnCase(command, "memory-format")) - { - constructAndPrintCommandHelpFormat("memory", "{1} / {2} ({3})", 3, - "Used size", - "Total size", - "Percentage used" - ); - } - else if(ffStrEqualsIgnCase(command, "swap-format")) - { - constructAndPrintCommandHelpFormat("swap", "{1} / {2} ({3})", 3, - "Used size", - "Total size", - "Percentage used" - ); - } - else if(ffStrEqualsIgnCase(command, "disk-format")) - { - constructAndPrintCommandHelpFormat("disk", "{1} / {2} ({3}) - {9}", 9, - "Size used", - "Size total", - "Size percentage", - "Files used", - "Files total", - "Files percentage", - "True if external volume", - "True if hidden volume", - "Filesystem" - ); - } - else if(ffStrEqualsIgnCase(command, "battery-format")) - { - constructAndPrintCommandHelpFormat("battery", "{}%, {}", 5, - "Battery manufactor", - "Battery model", - "Battery technology", - "Battery capacity", - "Battery status" - ); - } - else if(ffStrEqualsIgnCase(command, "poweradapter-format")) - { - constructAndPrintCommandHelpFormat("poweradapter", "{}%, {}", 5, - "PowerAdapter watts", - "PowerAdapter name", - "PowerAdapter manufacturer", - "PowerAdapter model", - "PowerAdapter description" - ); - } - else if(ffStrEqualsIgnCase(command, "lm-format")) - { - constructAndPrintCommandHelpFormat("lm", "{1} {3} ({2})", 3, - "LM service", - "LM type", - "LM version" - ); - } - else if(ffStrEqualsIgnCase(command, "locale-format")) - { - constructAndPrintCommandHelpFormat("locale", "{1}", 1, - "Locale code" - ); - } - else if(ffStrEqualsIgnCase(command, "localip-format")) - { - constructAndPrintCommandHelpFormat("localip", "{1}{5}", 5, - "Local IPv4 address", - "Local IPv6 address", - "Physical (MAC) address", - "Interface name", - "Is default route" - ); - } - else if(ffStrEqualsIgnCase(command, "publicip-format")) - { - constructAndPrintCommandHelpFormat("publicip", "{1} ({2})", 2, - "Public IP address", - "Location" - ); - } - else if(ffStrEqualsIgnCase(command, "netio-format")) - { - constructAndPrintCommandHelpFormat("netio", "{1} (IN) - {2} (OUT){4}", 4, - "Size of data received per second (formatted)", - "Size of data sent per second (formatted)", - "Interface name", - "Is default route" - ); - } - else if(ffStrEqualsIgnCase(command, "wifi-format")) - { - constructAndPrintCommandHelpFormat("wifi", "{4} - {10}", 10, - "Interface description", - "Interface status", - "Connection status", - "Connection SSID", - "Connection mac address", - "Connection protocol", - "Connection signal quality (percentage)", - "Connection RX rate", - "Connection TX rate", - "Connection Security algorithm" - ); - } - else if(ffStrEqualsIgnCase(command, "player-format")) - { - constructAndPrintCommandHelpFormat("player", "{}", 4, - "Pretty player name", - "Player name", - "Player Identifier", - "URL name" - ); - } - else if(ffStrEqualsIgnCase(command, "media-format")) - { - constructAndPrintCommandHelpFormat("media", "{3} - {1}", 4, - "Pretty media name", - "Media name", - "Artist name", - "Album name" - ); - } - else if(ffStrEqualsIgnCase(command, "datetime-format")) - { - constructAndPrintCommandHelpFormat("[date][time]", "{1}-{4}-{11} {14}:{18}:{20}", 20, - "year", - "last two digits of year", - "month", - "month with leading zero", - "month name", - "month name short", - "week number on year", - "weekday", - "weekday short", - "day in year", - "day in month", - "day in Week", - "hour", - "hour with leading zero", - "hour 12h format", - "hour 12h format with leading zero", - "minute", - "minute with leading zero", - "second", - "second with leading zero" - ); - } - else if(ffStrEqualsIgnCase(command, "version-format")) - { - constructAndPrintCommandHelpFormat("version", "{1} {2}{3} ({5})", 9, - "Project name", - "Version", - "Version tweak", - "Build type (debug or release)", - "Architecture", - "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)", - "Date time when compiling", - "Compiler used" - ); - } - else if(ffStrEqualsIgnCase(command, "vulkan-format")) - { - constructAndPrintCommandHelpFormat("vulkan", "{} (driver), {} (api version)", 3, - "Driver name", - "API version", - "Conformance version" - ); - } - else if(ffStrEqualsIgnCase(command, "opengl-format")) - { - constructAndPrintCommandHelpFormat("opengl", "{1}", 4, - "version", - "renderer", - "vendor", - "shading language version" - ); - } - else if(ffStrEqualsIgnCase(command, "opencl-format")) - { - constructAndPrintCommandHelpFormat("opencl", "{}", 3, - "version", - "device", - "vendor" - ); - } - else if(ffStrEqualsIgnCase(command, "bluetooth-format")) - { - constructAndPrintCommandHelpFormat("bluetooth", "{1} (4%)", 4, - "Name", - "Address", - "Type", - "Battery percentage" - ); - } - else if(ffStrEqualsIgnCase(command, "sound-format")) - { - constructAndPrintCommandHelpFormat("sound", "{2} ({3}%)", 4, - "Main", - "Name", - "Volume", - "Identifier" - ); - } - else if(ffStrEqualsIgnCase(command, "gamepad-format")) - { - constructAndPrintCommandHelpFormat("gamepad", "{1}", 2, - "Name", - "Identifier" - ); - } + else if(isalpha(command[0]) && ffStrEndsWithIgnCase(command, "-format")) // x-format + printCommandFormatHelp(command); else - fprintf(stderr, "No specific help for command '%s' provided\n", command); + fprintf(stderr, "Error: No specific help for command '%s' provided\n", command); } static void listAvailablePresets(void) diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 85103b5c8b..67ca2eed08 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -103,7 +103,7 @@ void ffPrintBattery(FFBatteryOptions* options) void ffInitBatteryOptions(FFBatteryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BATTERY_MODULE_NAME, ffParseBatteryCommandOptions, ffParseBatteryJsonObject, ffPrintBattery, ffGenerateBatteryJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BATTERY_MODULE_NAME, ffParseBatteryCommandOptions, ffParseBatteryJsonObject, ffPrintBattery, ffGenerateBatteryJson, ffPrintBatteryHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; @@ -208,3 +208,14 @@ void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjso ffStrbufDestroy(&battery->status); } } + +void ffPrintBatteryHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BATTERY_MODULE_NAME, "{4}, {5}", FF_BATTERY_NUM_FORMAT_ARGS, (const char* []) { + "Battery manufactor", + "Battery model", + "Battery technology", + "Battery capacity (percentage)", + "Battery status" + }); +} diff --git a/src/modules/battery/battery.h b/src/modules/battery/battery.h index adefbdeddf..d50ad8bae2 100644 --- a/src/modules/battery/battery.h +++ b/src/modules/battery/battery.h @@ -11,3 +11,4 @@ bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, co void ffDestroyBatteryOptions(FFBatteryOptions* options); void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module); void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBatteryHelpFormat(void); diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index b3f3e598ce..6658cfac6f 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -55,7 +55,7 @@ void ffPrintBios(FFBiosOptions* options) void ffInitBiosOptions(FFBiosOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BIOS_MODULE_NAME, ffParseBiosCommandOptions, ffParseBiosJsonObject, ffPrintBios, ffGenerateBiosJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BIOS_MODULE_NAME, ffParseBiosCommandOptions, ffParseBiosJsonObject, ffPrintBios, ffGenerateBiosJson, ffPrintBiosHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -125,3 +125,13 @@ void ffGenerateBiosJson(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut_doc* ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); } + +void ffPrintBiosHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BIOS_MODULE_NAME, "{4} ({2})", FF_BIOS_NUM_FORMAT_ARGS, (const char* []) { + "bios date", + "bios release", + "bios vendor", + "bios version" + }); +} diff --git a/src/modules/bios/bios.h b/src/modules/bios/bios.h index a3bb81d8d1..db7ab37040 100644 --- a/src/modules/bios/bios.h +++ b/src/modules/bios/bios.h @@ -10,3 +10,4 @@ bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const ch void ffDestroyBiosOptions(FFBiosOptions* options); void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module); void ffGenerateBiosJson(FFBiosOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBiosHelpFormat(void); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index ade503bc1c..6ddfb173c6 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -75,7 +75,7 @@ void ffPrintBluetooth(FFBluetoothOptions* options) void ffInitBluetoothOptions(FFBluetoothOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, ffGenerateBluetoothJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, ffGenerateBluetoothJson, ffPrintBluetoothHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->showDisconnected = false; } @@ -156,3 +156,13 @@ void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson ffStrbufDestroy(&device->address); } } + +void ffPrintBluetoothHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BLUETOOTH_MODULE_NAME, "{1} ({4})", FF_BLUETOOTH_NUM_FORMAT_ARGS, (const char* []) { + "Name", + "Address", + "Type", + "Battery percentage" + }); +} diff --git a/src/modules/bluetooth/bluetooth.h b/src/modules/bluetooth/bluetooth.h index b4d1f0a89f..dbccd1410f 100644 --- a/src/modules/bluetooth/bluetooth.h +++ b/src/modules/bluetooth/bluetooth.h @@ -10,3 +10,4 @@ bool ffParseBluetoothCommandOptions(FFBluetoothOptions* options, const char* key void ffDestroyBluetoothOptions(FFBluetoothOptions* options); void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module); void ffGenerateBluetoothJson(FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBluetoothHelpFormat(void); diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 17e187adee..7dde50d89f 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -51,7 +51,7 @@ void ffPrintBoard(FFBoardOptions* options) void ffInitBoardOptions(FFBoardOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BOARD_MODULE_NAME, ffParseBoardCommandOptions, ffParseBoardJsonObject, ffPrintBoard, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BOARD_MODULE_NAME, ffParseBoardCommandOptions, ffParseBoardJsonObject, ffPrintBoard, ffGenerateBoardJson, ffPrintBoardHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -118,3 +118,12 @@ void ffGenerateBoardJson(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_mut_doc ffStrbufDestroy(&board.vendor); ffStrbufDestroy(&board.version); } + +void ffPrintBoardHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BOARD_MODULE_NAME, "{1} ({3})", FF_BOARD_NUM_FORMAT_ARGS, (const char* []) { + "board name", + "board vendor", + "board version" + }); +} diff --git a/src/modules/board/board.h b/src/modules/board/board.h index 0e1dabbaba..f1a8e46e8c 100644 --- a/src/modules/board/board.h +++ b/src/modules/board/board.h @@ -10,3 +10,4 @@ bool ffParseBoardCommandOptions(FFBoardOptions* options, const char* key, const void ffDestroyBoardOptions(FFBoardOptions* options); void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module); void ffGenerateBoardJson(FFBoardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBoardHelpFormat(void); diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 59c39c1d72..e52e357e67 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -9,7 +9,7 @@ void ffPrintBreak(FF_MAYBE_UNUSED FFBreakOptions* options) void ffInitBreakOptions(FF_MAYBE_UNUSED FFBreakOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BREAK_MODULE_NAME, ffParseBreakCommandOptions, ffParseBreakJsonObject, ffPrintBreak, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BREAK_MODULE_NAME, ffParseBreakCommandOptions, ffParseBreakJsonObject, ffPrintBreak, NULL, NULL); } bool ffParseBreakCommandOptions(FF_MAYBE_UNUSED FFBreakOptions* options, FF_MAYBE_UNUSED const char* key, FF_MAYBE_UNUSED const char* value) diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 261122bb06..f65c30d215 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -86,7 +86,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) void ffInitBrightnessOptions(FFBrightnessOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson, ffPrintBrightnessHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -157,3 +157,14 @@ void ffGenerateBrightnessJson(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjs ffStrbufDestroy(&item->name); } } + +void ffPrintBrightnessHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_BRIGHTNESS_MODULE_NAME, "{1}", FF_BRIGHTNESS_NUM_FORMAT_ARGS, (const char* []) { + "Screen brightness (percentage)", + "Screen name", + "Maximum brightness value", + "Minimum brightness value", + "Current brightness value", + }); +} diff --git a/src/modules/brightness/brightness.h b/src/modules/brightness/brightness.h index 6933c65009..453a4532c3 100644 --- a/src/modules/brightness/brightness.h +++ b/src/modules/brightness/brightness.h @@ -10,3 +10,4 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k void ffDestroyBrightnessOptions(FFBrightnessOptions* options); void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module); void ffGenerateBrightnessJson(FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintBrightnessHelpFormat(void); diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 28a0f557dc..fc915a200a 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -52,7 +52,7 @@ void ffPrintChassis(FFChassisOptions* options) void ffInitChassisOptions(FFChassisOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, ffGenerateChassisJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, ffGenerateChassisJson, ffPrintChassisHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -119,3 +119,12 @@ void ffGenerateChassisJson(FF_MAYBE_UNUSED FFChassisOptions* options, yyjson_mut ffStrbufDestroy(&result.vendor); ffStrbufDestroy(&result.version); } + +void ffPrintChassisHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CHASSIS_MODULE_NAME, "{1}", FF_CHASSIS_NUM_FORMAT_ARGS, (const char* []) { + "chassis type", + "chassis vendor", + "chassis version" + }); +} diff --git a/src/modules/chassis/chassis.h b/src/modules/chassis/chassis.h index c5553f7722..f0d810d166 100644 --- a/src/modules/chassis/chassis.h +++ b/src/modules/chassis/chassis.h @@ -10,3 +10,4 @@ bool ffParseChassisCommandOptions(FFChassisOptions* options, const char* key, co void ffDestroyChassisOptions(FFChassisOptions* options); void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module); void ffGenerateChassisJson(FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintChassisHelpFormat(void); diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 4bcf9bafd2..4ac68d12e5 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -57,7 +57,7 @@ void ffPrintColors(FFColorsOptions* options) void ffInitColorsOptions(FFColorsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors, NULL, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); options->symbol = FF_COLORS_SYMBOL_BLOCK; diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 393aab97b7..5273e74ca0 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -4,6 +4,8 @@ #include "modules/command/command.h" #include "util/stringUtils.h" +#define FF_COMMAND_NUM_FORMAT_ARGS 1 + void ffPrintCommand(FFCommandOptions* options) { FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); @@ -30,13 +32,22 @@ void ffPrintCommand(FFCommandOptions* options) return; } - ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufPutTo(&result, stdout); + if (options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&result, stdout); + } + else + { + ffPrintFormat(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_COMMAND_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &result} + }); + } } void ffInitCommandOptions(FFCommandOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, ffGenerateCommandJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, ffGenerateCommandJson, ffPrintCommandHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInitStatic(&options->shell, @@ -136,3 +147,10 @@ void ffGenerateCommandJson(FF_MAYBE_UNUSED FFCommandOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, module, "result", &result); } + +void ffPrintCommandHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_COMMAND_MODULE_NAME, "{1}", FF_COMMAND_NUM_FORMAT_ARGS, (const char* []) { + "Command result" + }); +} diff --git a/src/modules/command/command.h b/src/modules/command/command.h index ec8e2bab37..932b1b8c3c 100644 --- a/src/modules/command/command.h +++ b/src/modules/command/command.h @@ -10,3 +10,4 @@ bool ffParseCommandCommandOptions(FFCommandOptions* options, const char* key, co void ffDestroyCommandOptions(FFCommandOptions* options); void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module); void ffGenerateCommandJson(FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCommandHelpFormat(void); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 3cd5a6cf7a..8626466141 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -79,7 +79,7 @@ void ffPrintCPU(FFCPUOptions* options) void ffInitCPUOptions(FFCPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, ffGenerateCPUJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, ffGenerateCPUJson, ffPrintCPUHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; } @@ -168,3 +168,17 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va ffStrbufDestroy(&cpu.name); ffStrbufDestroy(&cpu.vendor); } + +void ffPrintCPUHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CPU_MODULE_NAME, "{1} ({5}) @ {7} GHz", FF_CPU_NUM_FORMAT_ARGS, (const char* []) { + "Name", + "Vendor", + "Physical core count", + "Logical core count", + "Online core count", + "Min frequency", + "Max frequency", + "Temperature" + }); +} diff --git a/src/modules/cpu/cpu.h b/src/modules/cpu/cpu.h index 0a3e7c4c62..dac7362765 100644 --- a/src/modules/cpu/cpu.h +++ b/src/modules/cpu/cpu.h @@ -10,3 +10,4 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char void ffDestroyCPUOptions(FFCPUOptions* options); void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module); void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCPUHelpFormat(void); diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index ca0909377a..f658d832f4 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -46,7 +46,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) void ffInitCPUUsageOptions(FFCPUUsageOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, ffGenerateCPUUsageJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, ffGenerateCPUUsageJson, ffPrintCPUUsageHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -94,3 +94,10 @@ void ffGenerateCPUUsageJson(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_m } yyjson_mut_obj_add_real(doc, module, "result", percentage); } + +void ffPrintCPUUsageHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CPUUSAGE_MODULE_NAME, "{1}", FF_CPUUSAGE_NUM_FORMAT_ARGS, (const char* []) { + "CPU usage (percentage)" + }); +} diff --git a/src/modules/cpuusage/cpuusage.h b/src/modules/cpuusage/cpuusage.h index e31bc14c78..51af8bb222 100644 --- a/src/modules/cpuusage/cpuusage.h +++ b/src/modules/cpuusage/cpuusage.h @@ -12,3 +12,4 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options); void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module); void ffGenerateCPUUsageJson(FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCPUUsageHelpFormat(void); diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 555ec0374c..2de69177db 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -52,7 +52,7 @@ void ffPrintCursor(FFCursorOptions* options) void ffInitCursorOptions(FFCursorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, ffGenerateCursorJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, ffGenerateCursorJson, ffPrintCursorHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -111,3 +111,11 @@ void ffGenerateCursorJson(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson_mut_d ffStrbufDestroy(&result.theme); ffStrbufDestroy(&result.size); } + +void ffPrintCursorHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_CURSOR_MODULE_NAME, "{1} ({2}px)", FF_CURSOR_NUM_FORMAT_ARGS, (const char* []) { + "Cursor theme", + "Cursor size" + }); +} diff --git a/src/modules/cursor/cursor.h b/src/modules/cursor/cursor.h index 02ed47e8fd..44dff4909a 100644 --- a/src/modules/cursor/cursor.h +++ b/src/modules/cursor/cursor.h @@ -10,3 +10,4 @@ bool ffParseCursorCommandOptions(FFCursorOptions* options, const char* key, cons void ffDestroyCursorOptions(FFCursorOptions* options); void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module); void ffGenerateCursorJson(FFCursorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintCursorHelpFormat(void); diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 6576cd3c5e..11104d6c1f 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -19,7 +19,7 @@ void ffPrintCustom(FFCustomOptions* options) void ffInitCustomOptions(FFCustomOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom, NULL, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); } diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index adc7c50cf9..50cad80f95 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -143,7 +143,7 @@ void ffPrintDateTime(FFDateTimeOptions* options) void ffInitDateTimeOptions(FFDateTimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, ffGenerateDateTimeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, ffGenerateDateTimeJson, ffPrintDateTimeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -183,3 +183,29 @@ void ffGenerateDateTimeJson(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_m { yyjson_mut_obj_add_uint(doc, module, "result", ffTimeGetNow()); } + +void ffPrintDateTimeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DATETIME_MODULE_NAME, "{1}-{4}-{11} {14}:{18}:{20}", FF_DATETIME_NUM_FORMAT_ARGS, (const char* []) { + "year", + "last two digits of year", + "month", + "month with leading zero", + "month name", + "month name short", + "week number on year", + "weekday", + "weekday short", + "day in year", + "day in month", + "day in Week", + "hour", + "hour with leading zero", + "hour 12h format", + "hour 12h format with leading zero", + "minute", + "minute with leading zero", + "second", + "second with leading zero" + }); +} diff --git a/src/modules/datetime/datetime.h b/src/modules/datetime/datetime.h index 8f4ceb6908..ef1f91dcbc 100644 --- a/src/modules/datetime/datetime.h +++ b/src/modules/datetime/datetime.h @@ -10,3 +10,4 @@ bool ffParseDateTimeCommandOptions(FFDateTimeOptions* options, const char* key, void ffDestroyDateTimeOptions(FFDateTimeOptions* options); void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module); void ffGenerateDateTimeJson(FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDateTimeHelpFormat(void); diff --git a/src/modules/de/de.c b/src/modules/de/de.c index a6d896d7ce..0ea30ca013 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -42,7 +42,7 @@ void ffPrintDE(FFDEOptions* options) void ffInitDEOptions(FFDEOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, ffGenerateDEJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, ffGenerateDEJson, ffPrintDEHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -93,3 +93,12 @@ void ffGenerateDEJson(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->dePrettyName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->deVersion); } + +void ffPrintDEHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DE_MODULE_NAME, "{2} {3}", FF_DE_NUM_FORMAT_ARGS, (const char* []) { + "DE process name", + "DE pretty name", + "DE version" + }); +} diff --git a/src/modules/de/de.h b/src/modules/de/de.h index b8d122184f..6b1ea47780 100644 --- a/src/modules/de/de.h +++ b/src/modules/de/de.h @@ -10,3 +10,4 @@ bool ffParseDECommandOptions(FFDEOptions* options, const char* key, const char* void ffDestroyDEOptions(FFDEOptions* options); void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module); void ffGenerateDEJson(FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDEHelpFormat(void); diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index ca671bca78..f075ac123e 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -218,7 +218,7 @@ void ffPrintDisk(FFDiskOptions* options) void ffInitDiskOptions(FFDiskOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, ffGenerateDiskJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, ffGenerateDiskJson, ffPrintDiskHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->folders); @@ -452,3 +452,18 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ ffStrbufDestroy(&item->name); } } + +void ffPrintDiskHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DISK_MODULE_NAME, "{1} / {2} ({3}) - {9}", FF_DISK_NUM_FORMAT_ARGS, (const char* []) { + "Size used", + "Size total", + "Size percentage", + "Files used", + "Files total", + "Files percentage", + "True if external volume", + "True if hidden volume", + "Filesystem" + }); +} diff --git a/src/modules/disk/disk.h b/src/modules/disk/disk.h index eb4520b351..a3ee43e184 100644 --- a/src/modules/disk/disk.h +++ b/src/modules/disk/disk.h @@ -10,3 +10,4 @@ bool ffParseDiskCommandOptions(FFDiskOptions* options, const char* key, const ch void ffDestroyDiskOptions(FFDiskOptions* options); void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module); void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDiskHelpFormat(void); diff --git a/src/modules/display/display.c b/src/modules/display/display.c index f623bc5f4f..c52bf42a66 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -112,7 +112,7 @@ void ffPrintDisplay(FFDisplayOptions* options) void ffInitDisplayOptions(FFDisplayOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, ffGenerateDisplayJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, ffGenerateDisplayJson, ffPrintDisplayHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; options->preciseRefreshRate = false; @@ -225,3 +225,17 @@ void ffGenerateDisplayJson(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut } } } + +void ffPrintDisplayHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DISPLAY_MODULE_NAME, "{1}x{2} @ {3}Hz (as {4}x{5}) [{7}]", FF_DISPLAY_NUM_FORMAT_ARGS, (const char* []) { + "Screen width (in pixels)", + "Screen height (in pixels)", + "Screen refresh rate (in Hz)", + "Screen scaled width (in pixels)", + "Screen scaled height (in pixels)", + "Screen name", + "Screen type (builtin, external or unknown)", + "Screen rotation (in degrees)", + }); +} diff --git a/src/modules/display/display.h b/src/modules/display/display.h index 6c46dfb18c..b01a97ef14 100644 --- a/src/modules/display/display.h +++ b/src/modules/display/display.h @@ -10,3 +10,4 @@ bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, co void ffDestroyDisplayOptions(FFDisplayOptions* options); void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module); void ffGenerateDisplayJson(FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDisplayHelpFormat(void); diff --git a/src/modules/font/font.c b/src/modules/font/font.c index a737c615e9..c4ea4e62e3 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -45,7 +45,7 @@ void ffPrintFont(FFFontOptions* options) void ffInitFontOptions(FFFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, ffGenerateFontJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, ffGenerateFontJson, ffPrintFontHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -106,3 +106,14 @@ void ffGenerateFontJson(FF_MAYBE_UNUSED FFFontOptions* options, yyjson_mut_doc* for (uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i) ffStrbufDestroy(&font.fonts[i]); } + +void ffPrintFontHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_FONT_MODULE_NAME, "{5}", FF_FONT_NUM_FORMAT_ARGS, (const char* []) { + "Font 1", + "Font 2", + "Font 3", + "Font 4", + "Combined fonts" + }); +} diff --git a/src/modules/font/font.h b/src/modules/font/font.h index dedb1dfb95..5d8631a9e7 100644 --- a/src/modules/font/font.h +++ b/src/modules/font/font.h @@ -10,3 +10,4 @@ bool ffParseFontCommandOptions(FFFontOptions* options, const char* key, const ch void ffDestroyFontOptions(FFFontOptions* options); void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module); void ffGenerateFontJson(FFFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintFontHelpFormat(void); diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 43818aa2fa..b0a5b50430 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -51,7 +51,7 @@ void ffPrintGamepad(FFGamepadOptions* options) void ffInitGamepadOptions(FFGamepadOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, ffGenerateGamepadJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, ffGenerateGamepadJson, ffPrintGamepadHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -119,3 +119,11 @@ void ffGenerateGamepadJson(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjson_mut ffStrbufDestroy(&device->name); } } + +void ffPrintGamepadHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_GAMEPAD_MODULE_NAME, "{1}", FF_GAMEPAD_NUM_FORMAT_ARGS, (const char* []) { + "Name", + "Identifier" + }); +} diff --git a/src/modules/gamepad/gamepad.h b/src/modules/gamepad/gamepad.h index eff98e9925..ff05a4dbc5 100644 --- a/src/modules/gamepad/gamepad.h +++ b/src/modules/gamepad/gamepad.h @@ -10,3 +10,4 @@ bool ffParseGamepadCommandOptions(FFGamepadOptions* options, const char* key, co void ffDestroyGamepadOptions(FFGamepadOptions* options); void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module); void ffGenerateGamepadJson(FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintGamepadHelpFormat(void); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 95a25df3b1..acc8ab0a7f 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -10,7 +10,7 @@ #include -#define FF_GPU_NUM_FORMAT_ARGS 6 +#define FF_GPU_NUM_FORMAT_ARGS 10 static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) { @@ -77,6 +77,10 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}, {FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount}, {FF_FORMAT_ARG_TYPE_STRING, type}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.total}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.used}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.total}, + {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.used}, }); } } @@ -121,7 +125,7 @@ void ffPrintGPU(FFGPUOptions* options) void ffInitGPUOptions(FFGPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, ffGenerateGPUJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, ffGenerateGPUJson, ffPrintGPUHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->forceVulkan = false; @@ -277,3 +281,19 @@ void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va ffStrbufDestroy(&gpu->driver); } } + +void ffPrintGPUHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_GPU_MODULE_NAME, "{1} {2}", FF_GPU_NUM_FORMAT_ARGS, (const char* []) { + "GPU vendor", + "GPU name", + "GPU driver", + "GPU temperature", + "GPU core count", + "GPU type", + "GPU total dedicated memory", + "GPU used dedicated memory", + "GPU total shared memory", + "GPU used shared memory", + }); +} diff --git a/src/modules/gpu/gpu.h b/src/modules/gpu/gpu.h index 73bd7fad51..0c1d73bb2e 100644 --- a/src/modules/gpu/gpu.h +++ b/src/modules/gpu/gpu.h @@ -10,3 +10,4 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char void ffDestroyGPUOptions(FFGPUOptions* options); void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module); void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintGPUHelpFormat(void); diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 30df24f127..f65f300302 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,7 +67,7 @@ void ffPrintHost(FFHostOptions* options) void ffInitHostOptions(FFHostOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, ffGenerateHostJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, ffGenerateHostJson, ffPrintHostHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -139,3 +139,14 @@ void ffGenerateHostJson(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut_doc* ffStrbufDestroy(&host.productSku); ffStrbufDestroy(&host.sysVendor); } + +void ffPrintHostHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_HOST_MODULE_NAME, "{2} {3}", FF_HOST_NUM_FORMAT_ARGS, (const char* []) { + "product family", + "product name", + "product version", + "product sku", + "sys vendor" + }); +} diff --git a/src/modules/host/host.h b/src/modules/host/host.h index 4ed4575a1c..c07789382d 100644 --- a/src/modules/host/host.h +++ b/src/modules/host/host.h @@ -10,3 +10,4 @@ bool ffParseHostCommandOptions(FFHostOptions* options, const char* key, const ch void ffDestroyHostOptions(FFHostOptions* options); void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module); void ffGenerateHostJson(FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintHostHelpFormat(void); diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 720432b70a..0b16ec141a 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -32,7 +32,7 @@ void ffPrintIcons(FFIconsOptions* options) void ffInitIconsOptions(FFIconsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, ffGenerateIconsJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, ffGenerateIconsJson, ffPrintIconsHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,10 @@ void ffGenerateIconsJson(FF_MAYBE_UNUSED FFIconsOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, module, "result", &icons); } + +void ffPrintIconsHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_ICONS_MODULE_NAME, "{1}", FF_ICONS_NUM_FORMAT_ARGS, (const char* []) { + "Combined icons" + }); +} diff --git a/src/modules/icons/icons.h b/src/modules/icons/icons.h index dab251e25e..f44c0db2db 100644 --- a/src/modules/icons/icons.h +++ b/src/modules/icons/icons.h @@ -10,3 +10,4 @@ bool ffParseIconsCommandOptions(FFIconsOptions* options, const char* key, const void ffDestroyIconsOptions(FFIconsOptions* options); void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module); void ffGenerateIconsJson(FFIconsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintIconsHelpFormat(void); diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 89aab0af12..56c81b118c 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -32,7 +32,7 @@ void ffPrintKernel(FFKernelOptions* options) void ffInitKernelOptions(FFKernelOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, ffGenerateKernelJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, ffGenerateKernelJson, ffPrintKernelHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -77,3 +77,12 @@ void ffGenerateKernelJson(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson_mut_d yyjson_mut_obj_add_strbuf(doc, obj, "version", &instance.state.platform.systemVersion); yyjson_mut_obj_add_strbuf(doc, obj, "displayVersion", &instance.state.platform.systemDisplayVersion); } + +void ffPrintKernelHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_KERNEL_MODULE_NAME, "{2}", FF_KERNEL_NUM_FORMAT_ARGS, (const char* []) { + "Kernel sysname", + "Kernel release", + "Kernel version" + }); +} diff --git a/src/modules/kernel/kernel.h b/src/modules/kernel/kernel.h index 419f2544a3..6adbe89ab9 100644 --- a/src/modules/kernel/kernel.h +++ b/src/modules/kernel/kernel.h @@ -10,3 +10,4 @@ bool ffParseKernelCommandOptions(FFKernelOptions* options, const char* key, cons void ffDestroyKernelOptions(FFKernelOptions* options); void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module); void ffGenerateKernelJson(FFKernelOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintKernelHelpFormat(void); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index f84a422a34..e64a0e8a2f 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -51,7 +51,7 @@ void ffPrintLM(FFLMOptions* options) void ffInitLMOptions(FFLMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LM_MODULE_NAME, ffParseLMCommandOptions, ffParseLMJsonObject, ffPrintLM, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LM_MODULE_NAME, ffParseLMCommandOptions, ffParseLMJsonObject, ffPrintLM, ffGenerateLMJson, ffPrintLMHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -117,3 +117,12 @@ void ffGenerateLMJson(FF_MAYBE_UNUSED FFLMOptions* options, yyjson_mut_doc* doc, ffStrbufDestroy(&result.type); ffStrbufDestroy(&result.version); } + +void ffPrintLMHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_LM_MODULE_NAME, "{1} {3} ({2})", FF_LM_NUM_FORMAT_ARGS, (const char* []) { + "LM service", + "LM type", + "LM version" + }); +} diff --git a/src/modules/lm/lm.h b/src/modules/lm/lm.h index 72509adcbd..4178e1c9fb 100644 --- a/src/modules/lm/lm.h +++ b/src/modules/lm/lm.h @@ -10,3 +10,4 @@ bool ffParseLMCommandOptions(FFLMOptions* options, const char* key, const char* void ffDestroyLMOptions(FFLMOptions* options); void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module); void ffGenerateLMJson(FFLMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintLMHelpFormat(void); diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 10c53ba3db..674e5f6f31 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -32,7 +32,7 @@ void ffPrintLocale(FFLocaleOptions* options) void ffInitLocaleOptions(FFLocaleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, ffGenerateLocaleJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, ffGenerateLocaleJson, ffPrintLocaleHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,10 @@ void ffGenerateLocaleJson(FF_MAYBE_UNUSED FFLocaleOptions* options, yyjson_mut_d yyjson_mut_obj_add_strbuf(doc, module, "result", &locale); } + +void ffPrintLocaleHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_LOCALE_MODULE_NAME, "{1}", FF_LOCALE_NUM_FORMAT_ARGS, (const char* []) { + "Locale code" + }); +} diff --git a/src/modules/locale/locale.h b/src/modules/locale/locale.h index 8570a3c8de..f0031e2bf0 100644 --- a/src/modules/locale/locale.h +++ b/src/modules/locale/locale.h @@ -10,3 +10,4 @@ bool ffParseLocaleCommandOptions(FFLocaleOptions* options, const char* key, cons void ffDestroyLocaleOptions(FFLocaleOptions* options); void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module); void ffGenerateLocaleJson(FFLocaleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintLocaleHelpFormat(void); diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 36013d5058..86b8e3a857 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -133,7 +133,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) void ffInitLocalIpOptions(FFLocalIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, ffGenerateLocalIpJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, ffGenerateLocalIpJson, ffPrintLocalIpHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->showType = FF_LOCALIP_TYPE_IPV4_BIT; @@ -326,3 +326,14 @@ void ffGenerateLocalIpJson(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjson_mut ffStrbufDestroy(&ip->mac); } } + +void ffPrintLocalIpHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_LOCALIP_MODULE_NAME, "{1}", FF_LOCALIP_NUM_FORMAT_ARGS, (const char* []) { + "Local IPv4 address", + "Local IPv6 address", + "Physical (MAC) address", + "Interface name", + "Is default route" + }); +} diff --git a/src/modules/localip/localip.h b/src/modules/localip/localip.h index 799860a429..b78f7df6b1 100644 --- a/src/modules/localip/localip.h +++ b/src/modules/localip/localip.h @@ -10,3 +10,4 @@ bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, co void ffDestroyLocalIpOptions(FFLocalIpOptions* options); void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module); void ffGenerateLocalIpJson(FFLocalIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintLocalIpHelpFormat(void); diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 7a0e01e770..61a3814a2a 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -107,7 +107,7 @@ void ffPrintMedia(FFMediaOptions* options) void ffInitMediaOptions(FFMediaOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, ffGenerateMediaJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, ffGenerateMediaJson, ffPrintMediaHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -159,3 +159,14 @@ void ffGenerateMediaJson(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "album", &media->album); yyjson_mut_obj_add_strbuf(doc, obj, "status", &media->status); } + +void ffPrintMediaHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_MEDIA_MODULE_NAME, "{3} - {1} ({5})", FF_MEDIA_NUM_FORMAT_ARGS, (const char* []) { + "Pretty media name", + "Media name", + "Artist name", + "Album name", + "Status", + }); +} diff --git a/src/modules/media/media.h b/src/modules/media/media.h index 853814d7e5..e9966c1808 100644 --- a/src/modules/media/media.h +++ b/src/modules/media/media.h @@ -10,3 +10,4 @@ bool ffParseMediaCommandOptions(FFMediaOptions* options, const char* key, const void ffDestroyMediaOptions(FFMediaOptions* options); void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module); void ffGenerateMediaJson(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintMediaHelpFormat(void); diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 1d2bba3913..faea2c7bd0 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -68,7 +68,7 @@ void ffPrintMemory(FFMemoryOptions* options) void ffInitMemoryOptions(FFMemoryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, ffGenerateMemoryJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, ffGenerateMemoryJson, ffPrintMemoryHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -119,3 +119,12 @@ void ffGenerateMemoryJson(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson_mut_d yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal); yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); } + +void ffPrintMemoryHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_MEMORY_MODULE_NAME, "{1} / {2} ({3})", FF_MEMORY_NUM_FORMAT_ARGS, (const char* []) { + "Used size", + "Total size", + "Percentage used" + }); +} diff --git a/src/modules/memory/memory.h b/src/modules/memory/memory.h index b4fefff5dc..9d86997ef5 100644 --- a/src/modules/memory/memory.h +++ b/src/modules/memory/memory.h @@ -10,3 +10,4 @@ bool ffParseMemoryCommandOptions(FFMemoryOptions* options, const char* key, cons void ffDestroyMemoryOptions(FFMemoryOptions* options); void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module); void ffGenerateMemoryJson(FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintMemoryHelpFormat(void); diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index be0e22830c..271ccc67b9 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -77,7 +77,7 @@ void ffPrintMonitor(FFMonitorOptions* options) void ffInitMonitorOptions(FFMonitorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, ffGenerateMonitorJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, ffGenerateMonitorJson, ffPrintMonitorHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -147,3 +147,16 @@ void ffGenerateMonitorJson(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut ffStrbufDestroy(&item->name); } } + +void ffPrintMonitorHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_MONITOR_MODULE_NAME, "{2}x{3} px - {4}x{5} mm ({6} inches, {7} ppi)", FF_MONITOR_NUM_FORMAT_ARGS, (const char* []) { + "Display name", + "Display native resolution width in pixels", + "Display native resolution height in pixels", + "Display physical width in millimeters", + "Display physical height in millimeters", + "Display physical diagonal length in inches", + "Display physical pixels per inch (PPI)" + }); +} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h index 8511442040..53eccd5b46 100644 --- a/src/modules/monitor/monitor.h +++ b/src/modules/monitor/monitor.h @@ -10,3 +10,4 @@ bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, co void ffDestroyMonitorOptions(FFMonitorOptions* options); void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module); void ffGenerateMonitorJson(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintMonitorHelpFormat(void); diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 3efef948fa..2ee005cb8c 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -101,7 +101,7 @@ void ffPrintNetIO(FFNetIOOptions* options) void ffInitNetIOOptions(FFNetIOOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETIO_MODULE_NAME, ffParseNetIOCommandOptions, ffParseNetIOJsonObject, ffPrintNetIO, ffGenerateNetIOJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETIO_MODULE_NAME, ffParseNetIOCommandOptions, ffParseNetIOJsonObject, ffPrintNetIO, ffGenerateNetIOJson, ffPrintNetIOHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->namePrefix); @@ -197,3 +197,13 @@ void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mu ffStrbufDestroy(&inf->name); } } + +void ffPrintNetIOHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_NETIO_MODULE_NAME, "{1} (IN) - {2} (OUT){4}", FF_NETIO_NUM_FORMAT_ARGS, (const char* []) { + "Size of data received per second (formatted)", + "Size of data sent per second (formatted)", + "Interface name", + "Is default route" + }); +} diff --git a/src/modules/netio/netio.h b/src/modules/netio/netio.h index 3562d0ccd7..b8a19169c9 100644 --- a/src/modules/netio/netio.h +++ b/src/modules/netio/netio.h @@ -12,3 +12,4 @@ bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const void ffDestroyNetIOOptions(FFNetIOOptions* options); void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module); void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintNetIOHelpFormat(void); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index afe3efa244..600dc8c7d1 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -41,7 +41,7 @@ void ffPrintOpenCL(FFOpenCLOptions* options) void ffInitOpenCLOptions(FFOpenCLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, ffGenerateOpenCLJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, ffGenerateOpenCLJson, ffPrintOpenCLHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -102,3 +102,12 @@ void ffGenerateOpenCLJson(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson_mut_d ffStrbufDestroy(&opencl.device); ffStrbufDestroy(&opencl.vendor); } + +void ffPrintOpenCLHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_OPENCL_MODULE_NAME, "{1}", FF_OPENCL_NUM_FORMAT_ARGS, (const char* []) { + "version", + "device", + "vendor" + }); +} diff --git a/src/modules/opencl/opencl.h b/src/modules/opencl/opencl.h index 592f453bf1..35c4809463 100644 --- a/src/modules/opencl/opencl.h +++ b/src/modules/opencl/opencl.h @@ -10,3 +10,4 @@ bool ffParseOpenCLCommandOptions(FFOpenCLOptions* options, const char* key, cons void ffDestroyOpenCLOptions(FFOpenCLOptions* options); void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module); void ffGenerateOpenCLJson(FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintOpenCLHelpFormat(void); diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 78bbf18428..6a98eb8b79 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -44,7 +44,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options) void ffInitOpenGLOptions(FFOpenGLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, ffGenerateOpenGLJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, ffGenerateOpenGLJson, ffPrintOpenGLHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); #if defined(__linux__) || defined(__FreeBSD__) @@ -143,3 +143,13 @@ void ffGenerateOpenGLJson(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson_mut_d ffStrbufDestroy(&result.vendor); ffStrbufDestroy(&result.slv); } + +void ffPrintOpenGLHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_OPENGL_MODULE_NAME, "{1}", FF_OPENGL_NUM_FORMAT_ARGS, (const char* []) { + "version", + "renderer", + "vendor", + "shading language version" + }); +} diff --git a/src/modules/opengl/opengl.h b/src/modules/opengl/opengl.h index 6c35ede54e..d4f84a8954 100644 --- a/src/modules/opengl/opengl.h +++ b/src/modules/opengl/opengl.h @@ -10,3 +10,4 @@ bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, cons void ffDestroyOpenGLOptions(FFOpenGLOptions* options); void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module); void ffGenerateOpenGLJson(FFOpenGLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintOpenGLHelpFormat(void); diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 120f769fc1..299e871b32 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -138,7 +138,7 @@ void ffPrintOS(FFOSOptions* options) void ffInitOSOptions(FFOSOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, ffGenerateOSJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, ffGenerateOSJson, ffPrintOSHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -196,3 +196,21 @@ void ffGenerateOSJson(FF_MAYBE_UNUSED FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "version", &os->version); yyjson_mut_obj_add_strbuf(doc, obj, "versionID", &os->versionID); } + +void ffPrintOSHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_OS_MODULE_NAME, "{3} {10} {12}", FF_OS_NUM_FORMAT_ARGS, (const char* []) { + "Name of the kernel (Linux, WIN32_NT, Darwin, FreeBSD)", + "Name of the OS", + "Pretty name of the OS", + "ID of the OS", + "ID like of the OS", + "Variant of the OS", + "Variant ID of the OS", + "Version of the OS", + "Version ID of the OS", + "Version codename of the OS", + "Build ID of the OS", + "Architecture of the OS" + }); +} diff --git a/src/modules/os/os.h b/src/modules/os/os.h index b7ed39d0d4..8b16baf4e1 100644 --- a/src/modules/os/os.h +++ b/src/modules/os/os.h @@ -10,3 +10,4 @@ bool ffParseOSCommandOptions(FFOSOptions* options, const char* key, const char* void ffDestroyOSOptions(FFOSOptions* options); void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module); void ffGenerateOSJson(FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintOSHelpFormat(void); diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 1d6ba534ab..29602e8d0e 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -102,7 +102,7 @@ void ffPrintPackages(FFPackagesOptions* options) void ffInitPackagesOptions(FFPackagesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, ffGeneratePackagesJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, ffGeneratePackagesJson, ffPrintPackagesHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -180,3 +180,33 @@ void ffGeneratePackagesJson(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_m FF_APPEND_PACKAGE_COUNT(xbps) yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } + +void ffPrintPackagesHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget)", FF_PACKAGES_NUM_FORMAT_ARGS, (const char* []) { + "Number of all packages", + "Number of pacman packages", + "Pacman branch on manjaro", + "Number of dpkg packages", + "Number of rpm packages", + "Number of emerge packages", + "Number of eopkg packages", + "Number of xbps packages", + "Number of nix-system packages", + "Number of nix-user packages", + "Number of nix-default packages", + "Number of apk packages", + "Number of pkg packages", + "Number of flatpak-system packages", + "Number of flatpak-user packages", + "Number of snap packages", + "Number of brew packages", + "Number of brew-cask packages", + "Number of macports packages", + "Number of scoop packages", + "Number of choco packages", + "Number of pkgtool packages", + "Number of paludis packages" + "Number of winget packages" + }); +} diff --git a/src/modules/packages/packages.h b/src/modules/packages/packages.h index 97b4ce239f..39114a098d 100644 --- a/src/modules/packages/packages.h +++ b/src/modules/packages/packages.h @@ -10,3 +10,4 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, void ffDestroyPackagesOptions(FFPackagesOptions* options); void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module); void ffGeneratePackagesJson(FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPackagesHelpFormat(void); diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 5ca58ba279..caba0d8475 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -75,7 +75,7 @@ void ffPrintPlayer(FFPlayerOptions* options) void ffInitPlayerOptions(FFPlayerOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, ffGeneratePlayerJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, ffGeneratePlayerJson, ffPrintPlayerHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,13 @@ void ffGeneratePlayerJson(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_do yyjson_mut_obj_add_strbuf(doc, obj, "playerId", &media->playerId); yyjson_mut_obj_add_strbuf(doc, obj, "url", &media->url); } + +void ffPrintPlayerHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PLAYER_MODULE_NAME, "{1}", FF_PLAYER_NUM_FORMAT_ARGS, (const char* []) { + "Pretty player name", + "Player name", + "Player Identifier", + "URL name" + }); +} diff --git a/src/modules/player/player.h b/src/modules/player/player.h index 829b7857a4..11a4fed8e2 100644 --- a/src/modules/player/player.h +++ b/src/modules/player/player.h @@ -11,3 +11,4 @@ bool ffParsePlayerCommandOptions(FFPlayerOptions* options, const char* key, cons void ffDestroyPlayerOptions(FFPlayerOptions* options); void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module); void ffGeneratePlayerJson(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPlayerHelpFormat(void); diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index a5ce64002c..fef71928a1 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -5,7 +5,7 @@ #include "util/stringUtils.h" #define FF_POWERADAPTER_DISPLAY_NAME "Power Adapter" -#define FF_POWERADAPTER_MODULE_ARGS 5 +#define FF_POWERADAPTER_NUM_FORMAT_ARGS 5 void ffPrintPowerAdapter(FFPowerAdapterOptions* options) { @@ -42,7 +42,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) } else { - ffPrintFormat(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_POWERADAPTER_MODULE_ARGS, (FFformatarg[]){ + ffPrintFormat(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_POWERADAPTER_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_INT, &result->watts}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer}, @@ -62,7 +62,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, ffGeneratePowerAdapterJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, ffGeneratePowerAdapterJson, ffPrintPowerAdapterHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,14 @@ void ffGeneratePowerAdapterJson(FF_MAYBE_UNUSED FFPowerAdapterOptions* options, } } } + +void ffPrintPowerAdapterHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_POWERADAPTER_MODULE_NAME, "{1}W", FF_POWERADAPTER_NUM_FORMAT_ARGS, (const char* []) { + "PowerAdapter watts", + "PowerAdapter name", + "PowerAdapter manufacturer", + "PowerAdapter model", + "PowerAdapter description" + }); +} diff --git a/src/modules/poweradapter/poweradapter.h b/src/modules/poweradapter/poweradapter.h index a99d6acabb..792409ff27 100644 --- a/src/modules/poweradapter/poweradapter.h +++ b/src/modules/poweradapter/poweradapter.h @@ -10,3 +10,4 @@ bool ffParsePowerAdapterCommandOptions(FFPowerAdapterOptions* options, const cha void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options); void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* module); void ffGeneratePowerAdapterJson(FFPowerAdapterOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPowerAdapterHelpFormat(void); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 02a8bb53f1..ce04971722 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -33,7 +33,7 @@ void ffPrintProcesses(FFProcessesOptions* options) void ffInitProcessesOptions(FFProcessesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, ffGenerateProcessesJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, ffGenerateProcessesJson, ffPrintProcessesHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -82,3 +82,10 @@ void ffGenerateProcessesJson(FF_MAYBE_UNUSED FFProcessesOptions* options, yyjson yyjson_mut_obj_add_uint(doc, module, "result", result); } + +void ffPrintProcessesHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PROCESSES_MODULE_NAME, "{1}", FF_PROCESSES_NUM_FORMAT_ARGS, (const char* []) { + "Count" + }); +} diff --git a/src/modules/processes/processes.h b/src/modules/processes/processes.h index 8f14e00e44..b2d9ac6be2 100644 --- a/src/modules/processes/processes.h +++ b/src/modules/processes/processes.h @@ -10,3 +10,4 @@ bool ffParseProcessesCommandOptions(FFProcessesOptions* options, const char* key void ffDestroyProcessesOptions(FFProcessesOptions* options); void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module); void ffGenerateProcessesJson(FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintProcessesHelpFormat(void); diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index e7c277e21e..a6ae2c9eb5 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -42,7 +42,7 @@ void ffPrintPublicIp(FFPublicIpOptions* options) void ffInitPublicIpOptions(FFPublicIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, ffGeneratePublicIpJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, ffGeneratePublicIpJson, ffPrintPublicIpHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->url); @@ -127,3 +127,11 @@ void ffGeneratePublicIpJson(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyj ffStrbufDestroy(&result.ip); ffStrbufDestroy(&result.location); } + +void ffPrintPublicIpHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PUBLICIP_MODULE_NAME, "{1} ({2})", FF_PUBLICIP_NUM_FORMAT_ARGS, (const char* []) { + "Public IP address", + "Location" + }); +} diff --git a/src/modules/publicip/publicip.h b/src/modules/publicip/publicip.h index 870591eb74..69f8752e45 100644 --- a/src/modules/publicip/publicip.h +++ b/src/modules/publicip/publicip.h @@ -12,3 +12,4 @@ bool ffParsePublicIpCommandOptions(FFPublicIpOptions* options, const char* key, void ffDestroyPublicIpOptions(FFPublicIpOptions* options); void ffParsePublicIpJsonObject(FFPublicIpOptions* options, yyjson_val* module); void ffGeneratePublicIpJson(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintPublicIpHelpFormat(void); diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 555bb2a04c..75cd4eea7e 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -77,7 +77,7 @@ void ffPrintSeparator(FFSeparatorOptions* options) void ffInitSeparatorOptions(FFSeparatorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorCommandOptions, ffParseSeparatorJsonObject, ffPrintSeparator, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorCommandOptions, ffParseSeparatorJsonObject, ffPrintSeparator, NULL, NULL); ffStrbufInit(&options->string); } diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index f7668c5882..64c074b631 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -44,7 +44,7 @@ void ffPrintShell(FFShellOptions* options) void ffInitShellOptions(FFShellOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, ffGenerateShellJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, ffGenerateShellJson, ffPrintShellHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -97,3 +97,15 @@ void ffGenerateShellJson(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->shellVersion); } + +void ffPrintShellHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_SHELL_MODULE_NAME, "{3} {4}", FF_SHELL_NUM_FORMAT_ARGS, (const char* []) { + "Shell process name", + "Shell path with exe name", + "Shell exe name", + "Shell version", + "Shell pid", + "Shell pretty name" + }); +} diff --git a/src/modules/shell/shell.h b/src/modules/shell/shell.h index 354b512290..961a94cb7e 100644 --- a/src/modules/shell/shell.h +++ b/src/modules/shell/shell.h @@ -10,3 +10,4 @@ bool ffParseShellCommandOptions(FFShellOptions* options, const char* key, const void ffDestroyShellOptions(FFShellOptions* options); void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module); void ffGenerateShellJson(FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintShellHelpFormat(void); diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 6157c32d3c..02a954d0ab 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -85,7 +85,7 @@ void ffPrintSound(FFSoundOptions* options) void ffInitSoundOptions(FFSoundOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, ffGenerateSoundJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, ffGenerateSoundJson, ffPrintSoundHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->soundType = FF_SOUND_TYPE_MAIN; @@ -189,3 +189,13 @@ void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc ffStrbufDestroy(&device->name); } } + +void ffPrintSoundHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_SOUND_MODULE_NAME, "{2} ({3}%)", FF_SOUND_NUM_FORMAT_ARGS, (const char* []) { + "Is main sound device", + "Device name", + "Volume", + "Identifier" + }); +} diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h index 03ec8fe680..b7ab196a1c 100644 --- a/src/modules/sound/sound.h +++ b/src/modules/sound/sound.h @@ -10,3 +10,4 @@ bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const void ffDestroySoundOptions(FFSoundOptions* options); void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module); void ffGenerateSoundJson(FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintSoundHelpFormat(void); diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 331cbf26dd..0e207434a2 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -75,7 +75,7 @@ void ffPrintSwap(FFSwapOptions* options) void ffInitSwapOptions(FFSwapOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, ffGenerateSwapJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, ffGenerateSwapJson, ffPrintSwapHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,12 @@ void ffGenerateSwapJson(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut_doc* yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal); yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); } + +void ffPrintSwapHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_SWAP_MODULE_NAME, "{1} / {2} ({3})", FF_SWAP_NUM_FORMAT_ARGS, (const char* []) { + "Used size", + "Total size", + "Percentage used" + }); +} diff --git a/src/modules/swap/swap.h b/src/modules/swap/swap.h index fbb125a449..1a6fbc64f3 100644 --- a/src/modules/swap/swap.h +++ b/src/modules/swap/swap.h @@ -10,3 +10,4 @@ bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const ch void ffDestroySwapOptions(FFSwapOptions* options); void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module); void ffGenerateSwapJson(FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintSwapHelpFormat(void); diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index ac68652f04..6745524fa7 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -42,7 +42,7 @@ void ffPrintTerminal(FFTerminalOptions* options) void ffInitTerminalOptions(FFTerminalOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, ffGenerateTerminalJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, ffGenerateTerminalJson, ffPrintTerminalHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -96,3 +96,15 @@ void ffGenerateTerminalJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_m yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->terminalPrettyName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->terminalVersion); } + +void ffPrintTerminalHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TERMINAL_MODULE_NAME, "{5} {6}", FF_TERMINAL_NUM_FORMAT_ARGS, (const char* []) { + "Terminal process name", + "Terminal path with exe name", + "Terminal exe name", + "Terminal pid", + "Terminal pretty name", + "Terminal version" + }); +} diff --git a/src/modules/terminal/terminal.h b/src/modules/terminal/terminal.h index 709b02e568..c10e3fba08 100644 --- a/src/modules/terminal/terminal.h +++ b/src/modules/terminal/terminal.h @@ -10,3 +10,4 @@ bool ffParseTerminalCommandOptions(FFTerminalOptions* options, const char* key, void ffDestroyTerminalOptions(FFTerminalOptions* options); void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module); void ffGenerateTerminalJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTerminalHelpFormat(void); diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index ca28576c92..2353ff869b 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -49,7 +49,7 @@ void ffPrintTerminalFont(FFTerminalFontOptions* options) void ffInitTerminalFontOptions(FFTerminalFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, ffGenerateTerminalFontJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, ffGenerateTerminalFontJson, ffPrintTerminalFontHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -124,3 +124,13 @@ void ffGenerateTerminalFontJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjs ffFontDestroy(&result.font); ffFontDestroy(&result.fallback); } + +void ffPrintTerminalFontHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TERMINALFONT_MODULE_NAME, "{1}", FF_TERMINALFONT_NUM_FORMAT_ARGS, (const char* []) { + "Terminal font combined", + "Terminal font name", + "Terminal font size", + "Terminal font styles" + }); +} diff --git a/src/modules/terminalfont/terminalfont.h b/src/modules/terminalfont/terminalfont.h index 434eb1a1f7..a117c82898 100644 --- a/src/modules/terminalfont/terminalfont.h +++ b/src/modules/terminalfont/terminalfont.h @@ -10,3 +10,4 @@ bool ffParseTerminalFontCommandOptions(FFTerminalFontOptions* options, const cha void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options); void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* module); void ffGenerateTerminalFontJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTerminalFontHelpFormat(void); diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 22ef849efe..8d4f454bdd 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -41,7 +41,7 @@ void ffPrintTerminalSize(FFTerminalSizeOptions* options) void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, ffGenerateTerminalSizeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, ffGenerateTerminalSizeJson, ffPrintTerminalSizeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -93,3 +93,13 @@ void ffGenerateTerminalSizeJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjs yyjson_mut_obj_add_uint(doc, obj, "width", result.width); yyjson_mut_obj_add_uint(doc, obj, "height", result.height); } + +void ffPrintTerminalSizeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TERMINALSIZE_MODULE_NAME, "{1} columns x {2} rows ({3}px x {4}px)", FF_TERMINALSIZE_NUM_FORMAT_ARGS, (const char* []) { + "Terminal rows", + "Terminal columns", + "Terminal width (in pixels)", + "Terminal height (in pixels)" + }); +} diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h index 33699057d5..312ccaf5a8 100644 --- a/src/modules/terminalsize/terminalsize.h +++ b/src/modules/terminalsize/terminalsize.h @@ -10,3 +10,4 @@ bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const cha void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* module); void ffGenerateTerminalSizeJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTerminalSizeHelpFormat(void); diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 2fc89549bd..8c0e60af51 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -32,7 +32,7 @@ void ffPrintTheme(FFThemeOptions* options) void ffInitThemeOptions(FFThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, ffGenerateThemeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, ffGenerateThemeJson, ffPrintThemeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,10 @@ void ffGenerateThemeJson(FF_MAYBE_UNUSED FFThemeOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, module, "result", &theme); } + +void ffPrintThemeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_THEME_MODULE_NAME, "{1}", FF_THEME_NUM_FORMAT_ARGS, (const char* []) { + "Combined themes" + }); +} diff --git a/src/modules/theme/theme.h b/src/modules/theme/theme.h index c0cee8584b..cf658de211 100644 --- a/src/modules/theme/theme.h +++ b/src/modules/theme/theme.h @@ -10,3 +10,4 @@ bool ffParseThemeCommandOptions(FFThemeOptions* options, const char* key, const void ffDestroyThemeOptions(FFThemeOptions* options); void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module); void ffGenerateThemeJson(FFThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintThemeHelpFormat(void); diff --git a/src/modules/title/title.c b/src/modules/title/title.c index a0174322a5..2116a9e4be 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -71,7 +71,7 @@ void ffPrintTitle(FFTitleOptions* options) void ffInitTitleOptions(FFTitleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, ffGenerateTitleJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, ffGenerateTitleJson, ffPrintTitleHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); @@ -172,3 +172,17 @@ void ffGenerateTitleJson(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath); yyjson_mut_obj_add_strbuf(doc, obj, "userShell", &instance.state.platform.userShell); } + +void ffPrintTitleHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_TITLE_MODULE_NAME, "{6}{7}{8}", FF_TITLE_NUM_FORMAT_ARGS, (const char* []) { + "User name", + "Host name", + "Home directory", + "Executable path of current process", + "User's default shell", + "User name (colored)", + "@ symbol (colored)", + "Host name (colored)" + }); +} diff --git a/src/modules/title/title.h b/src/modules/title/title.h index 76bec364d9..bad3a99c86 100644 --- a/src/modules/title/title.h +++ b/src/modules/title/title.h @@ -10,3 +10,4 @@ bool ffParseTitleCommandOptions(FFTitleOptions* options, const char* key, const void ffDestroyTitleOptions(FFTitleOptions* options); void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module); void ffGenerateTitleJson(FFTitleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintTitleHelpFormat(void); diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 96be154563..d0ed2630dd 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -91,7 +91,7 @@ void ffPrintUptime(FFUptimeOptions* options) void ffInitUptimeOptions(FFUptimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, ffGenerateUptimeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, ffGenerateUptimeJson, ffPrintUptimeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -142,3 +142,13 @@ void ffGenerateUptimeJson(FF_MAYBE_UNUSED FFUptimeOptions* options, yyjson_mut_d yyjson_mut_obj_add_uint(doc, obj, "uptime", result.uptime); yyjson_mut_obj_add_uint(doc, obj, "bootTime", result.bootTime); } + +void ffPrintUptimeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_UPTIME_MODULE_NAME, "{1} days {2} hours {3} mins", FF_UPTIME_NUM_FORMAT_ARGS, (const char* []) { + "Days", + "Hours", + "Minutes", + "Seconds" + }); +} diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h index 2fa12e9638..4cd9537825 100644 --- a/src/modules/uptime/uptime.h +++ b/src/modules/uptime/uptime.h @@ -10,3 +10,4 @@ bool ffParseUptimeCommandOptions(FFUptimeOptions* options, const char* key, cons void ffDestroyUptimeOptions(FFUptimeOptions* options); void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module); void ffGenerateUptimeJson(FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintUptimeHelpFormat(void); diff --git a/src/modules/users/users.c b/src/modules/users/users.c index ab58440c2e..ba5e6e75c5 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -93,7 +93,7 @@ void ffPrintUsers(FFUsersOptions* options) void ffInitUsersOptions(FFUsersOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, ffGenerateUsersJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, ffGenerateUsersJson, ffPrintUsersHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->compact = false; @@ -175,3 +175,14 @@ void ffGenerateUsersJson(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc ffStrbufDestroy(&user->name); } } + +void ffPrintUsersHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_USERS_MODULE_NAME, "{1}@{2} - login time {5}", FF_USERS_NUM_FORMAT_ARGS, (const char* []) { + "User name", + "Host name", + "TTY name", + "Client IP", + "Login Time" + }); +} diff --git a/src/modules/users/users.h b/src/modules/users/users.h index 3ef57a1cf7..71a4449ec2 100644 --- a/src/modules/users/users.h +++ b/src/modules/users/users.h @@ -10,3 +10,4 @@ bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const void ffDestroyUsersOptions(FFUsersOptions* options); void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module); void ffGenerateUsersJson(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintUsersHelpFormat(void); diff --git a/src/modules/version/version.c b/src/modules/version/version.c index a5a6ca7d8b..69911fb107 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -47,7 +47,7 @@ void ffPrintVersion(FFVersionOptions* options) void ffInitVersionOptions(FFVersionOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, ffGenerateVersionJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, ffGenerateVersionJson, ffPrintVersionHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -114,3 +114,18 @@ void ffGenerateVersionJson(FF_MAYBE_UNUSED FFVersionOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, obj, "libc", &buf); } } + +void ffPrintVersionHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_VERSION_MODULE_NAME, "{1} {2}{3} ({5})", FF_VERSION_NUM_FORMAT_ARGS, (const char* []) { + "Project name", + "Version", + "Version tweak", + "Build type (debug or release)", + "Architecture", + "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)", + "Date time when compiling", + "Compiler used", + "Libc used" + }); +} diff --git a/src/modules/version/version.h b/src/modules/version/version.h index bb1e4c15f7..3daaccd1c6 100644 --- a/src/modules/version/version.h +++ b/src/modules/version/version.h @@ -10,3 +10,4 @@ bool ffParseVersionCommandOptions(FFVersionOptions* options, const char* key, co void ffDestroyVersionOptions(FFVersionOptions* options); void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module); void ffGenerateVersionJson(FFVersionOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintVersionHelpFormat(void); diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 14c37153ac..81760efa2c 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -46,7 +46,7 @@ void ffPrintVulkan(FFVulkanOptions* options) void ffInitVulkanOptions(FFVulkanOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, ffGenerateVulkanJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, ffGenerateVulkanJson, ffPrintVulkanHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -136,3 +136,12 @@ void ffGenerateVulkanJson(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson_mut_d yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->vulkanDeviceId); } } + +void ffPrintVulkanHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_VULKAN_MODULE_NAME, "{2} - {1}", FF_VULKAN_NUM_FORMAT_ARGS, (const char* []) { + "Driver name", + "API version", + "Conformance version" + }); +} diff --git a/src/modules/vulkan/vulkan.h b/src/modules/vulkan/vulkan.h index a0b378394e..fad7884bf3 100644 --- a/src/modules/vulkan/vulkan.h +++ b/src/modules/vulkan/vulkan.h @@ -10,3 +10,4 @@ bool ffParseVulkanCommandOptions(FFVulkanOptions* options, const char* key, cons void ffDestroyVulkanOptions(FFVulkanOptions* options); void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module); void ffGenerateVulkanJson(FFVulkanOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintVulkanHelpFormat(void); diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index 947a1031e5..17213dfc56 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -44,7 +44,7 @@ void ffPrintWallpaper(FFWallpaperOptions* options) void ffInitWallpaperOptions(FFWallpaperOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, ffGenerateWallpaperJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, ffGenerateWallpaperJson, ffPrintWallpaperHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -91,3 +91,10 @@ void ffGenerateWallpaperJson(FF_MAYBE_UNUSED FFWallpaperOptions* options, yyjson } yyjson_mut_obj_add_strbuf(doc, module, "result", &fullpath); } + +void ffPrintWallpaperHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WALLPAPER_MODULE_NAME, "{1}", FF_WALLPAPER_NUM_FORMAT_ARGS, (const char* []) { + "Wallpaper image file" + }); +} diff --git a/src/modules/wallpaper/wallpaper.h b/src/modules/wallpaper/wallpaper.h index 3925784b27..a811cf515e 100644 --- a/src/modules/wallpaper/wallpaper.h +++ b/src/modules/wallpaper/wallpaper.h @@ -10,3 +10,4 @@ bool ffParseWallpaperCommandOptions(FFWallpaperOptions* options, const char* key void ffDestroyWallpaperOptions(FFWallpaperOptions* options); void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module); void ffGenerateWallpaperJson(FFWallpaperOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWallpaperHelpFormat(void); diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index ec25374b5d..2fdb578d33 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -33,7 +33,7 @@ void ffPrintWeather(FFWeatherOptions* options) void ffInitWeatherOptions(FFWeatherOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, ffGenerateWeatherJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, ffGenerateWeatherJson, ffPrintWeatherHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->location); @@ -124,3 +124,10 @@ void ffGenerateWeatherJson(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjso yyjson_mut_obj_add_strbuf(doc, module, "result", &result); } + +void ffPrintWeatherHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WEATHER_MODULE_NAME, "{1}", FF_WEATHER_NUM_FORMAT_ARGS, (const char* []) { + "Weather result" + }); +} diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h index a769402448..6fdff6f974 100644 --- a/src/modules/weather/weather.h +++ b/src/modules/weather/weather.h @@ -12,3 +12,4 @@ bool ffParseWeatherCommandOptions(FFWeatherOptions* options, const char* key, co void ffDestroyWeatherOptions(FFWeatherOptions* options); void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module); void ffGenerateWeatherJson(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWeatherHelpFormat(void); diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 449b82e67a..2268e830e0 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -72,7 +72,7 @@ void ffPrintWifi(FFWifiOptions* options) void ffInitWifiOptions(FFWifiOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, ffGenerateWifiJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, ffGenerateWifiJson, ffPrintWifiHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -153,3 +153,19 @@ void ffGenerateWifiJson(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut_doc* ffStrbufDestroy(&item->conn.security); } } + +void ffPrintWifiHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WIFI_MODULE_NAME, "{4} - {10}", FF_WIFI_NUM_FORMAT_ARGS, (const char* []) { + "Interface description", + "Interface status", + "Connection status", + "Connection SSID", + "Connection mac address", + "Connection protocol", + "Connection signal quality (percentage)", + "Connection RX rate", + "Connection TX rate", + "Connection Security algorithm" + }); +} diff --git a/src/modules/wifi/wifi.h b/src/modules/wifi/wifi.h index 2957f876d8..96ad129503 100644 --- a/src/modules/wifi/wifi.h +++ b/src/modules/wifi/wifi.h @@ -10,3 +10,4 @@ bool ffParseWifiCommandOptions(FFWifiOptions* options, const char* key, const ch void ffDestroyWifiOptions(FFWifiOptions* options); void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module); void ffGenerateWifiJson(FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWifiHelpFormat(void); diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 371b48deb8..dcfbf94ec3 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -43,7 +43,7 @@ void ffPrintWM(FFWMOptions* options) void ffInitWMOptions(FFWMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, ffGenerateWMJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, ffGenerateWMJson, ffPrintWMHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -93,3 +93,12 @@ void ffGenerateWMJson(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->wmPrettyName); yyjson_mut_obj_add_strbuf(doc, obj, "protocolName", &result->wmProtocolName); } + +void ffPrintWMHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WM_MODULE_NAME, "{2} ({3})", FF_WM_NUM_FORMAT_ARGS, (const char* []) { + "WM process name", + "WM pretty name", + "WM protocol name" + }); +} diff --git a/src/modules/wm/wm.h b/src/modules/wm/wm.h index fe960b6885..52f9275150 100644 --- a/src/modules/wm/wm.h +++ b/src/modules/wm/wm.h @@ -10,3 +10,4 @@ bool ffParseWMCommandOptions(FFWMOptions* options, const char* key, const char* void ffDestroyWMOptions(FFWMOptions* options); void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module); void ffGenerateWMJson(FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWMHelpFormat(void); diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 3560769223..d506d634c8 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -32,7 +32,7 @@ void ffPrintWMTheme(FFWMThemeOptions* options) void ffInitWMThemeOptions(FFWMThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, ffGenerateWMThemeJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, ffGenerateWMThemeJson, ffPrintWMthemeHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); } @@ -79,3 +79,10 @@ void ffGenerateWMThemeJson(FF_MAYBE_UNUSED FFWMThemeOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, module, "result", &themeOrError); } + +void ffPrintWMthemeHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_WMTHEME_MODULE_NAME, "{1}", FF_WMTHEME_NUM_FORMAT_ARGS, (const char* []) { + "WM theme" + }); +} diff --git a/src/modules/wmtheme/wmtheme.h b/src/modules/wmtheme/wmtheme.h index e90f9e2530..0e9dd5b130 100644 --- a/src/modules/wmtheme/wmtheme.h +++ b/src/modules/wmtheme/wmtheme.h @@ -10,3 +10,4 @@ bool ffParseWMThemeCommandOptions(FFWMThemeOptions* options, const char* key, co void ffDestroyWMThemeOptions(FFWMThemeOptions* options); void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module); void ffGenerateWMThemeJson(FFWMThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintWMthemeHelpFormat(void); diff --git a/src/util/stringUtils.h b/src/util/stringUtils.h index 80894ad26f..d3ff894c6d 100644 --- a/src/util/stringUtils.h +++ b/src/util/stringUtils.h @@ -34,6 +34,15 @@ static inline bool ffStrEndsWith(const char* str, const char* compareTo) return memcmp(str + strLength - compareToLength, compareTo, compareToLength) == 0; } +static inline bool ffStrEndsWithIgnCase(const char* str, const char* compareTo) +{ + size_t strLength = strlen(str); + size_t compareToLength = strlen(compareTo); + if (strLength < compareToLength) + return false; + return strncasecmp(str + strLength - compareToLength, compareTo, compareToLength) == 0; +} + static inline bool ffStrEquals(const char* str, const char* compareTo) { return strcmp(str, compareTo) == 0; From c77a758741d518670c2379646dc9dbfc2bf7c29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 14:02:16 +0800 Subject: [PATCH 15/74] Packages (Linux): support opkg Fix #574 --- src/detection/packages/packages.h | 1 + src/detection/packages/packages_linux.c | 1 + src/modules/packages/packages.c | 11 +++++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index ae36b5078e..475d39301e 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -19,6 +19,7 @@ typedef struct FFPackagesResult uint32_t nixDefault; uint32_t nixSystem; uint32_t nixUser; + uint32_t opkg; uint32_t pacman; uint32_t paludis; uint32_t pkg; diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 1aa2c2433a..93a7560120 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -280,6 +280,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts) packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR); packageCounts->brew += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Cellar", DT_DIR); packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2"); + packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt } static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts) diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 29602e8d0e..d21c2bd070 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 24 +#define FF_PACKAGES_NUM_FORMAT_ARGS 25 void ffPrintPackages(FFPackagesOptions* options) { @@ -64,6 +64,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE(pkgtool) FF_PRINT_PACKAGE(paludis) FF_PRINT_PACKAGE(winget) + FF_PRINT_PACKAGE(opkg) putchar('\n'); } @@ -94,6 +95,7 @@ void ffPrintPackages(FFPackagesOptions* options) {FF_FORMAT_ARG_TYPE_UINT, &counts.pkgtool}, {FF_FORMAT_ARG_TYPE_UINT, &counts.paludis}, {FF_FORMAT_ARG_TYPE_UINT, &counts.winget}, + {FF_FORMAT_ARG_TYPE_UINT, &counts.opkg}, }); } @@ -183,7 +185,7 @@ void ffGeneratePackagesJson(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_m void ffPrintPackagesHelpFormat(void) { - ffPrintModuleFormatHelp(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget)", FF_PACKAGES_NUM_FORMAT_ARGS, (const char* []) { + ffPrintModuleFormatHelp(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg)", FF_PACKAGES_NUM_FORMAT_ARGS, (const char* []) { "Number of all packages", "Number of pacman packages", "Pacman branch on manjaro", @@ -206,7 +208,8 @@ void ffPrintPackagesHelpFormat(void) "Number of scoop packages", "Number of choco packages", "Number of pkgtool packages", - "Number of paludis packages" - "Number of winget packages" + "Number of paludis packages", + "Number of winget packages", + "Number of opkg packages" }); } From d7ef7bc078a4eabfa7cd9ba096fa88a6a82d2d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 15:14:16 +0800 Subject: [PATCH 16/74] Doc: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f0e41a06a..8f04c805a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ # 2.1.1 +Features: +* Support opkg (Packages, Linux) + Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) * Fix possible crashes caused by uninitialized strings (Users, Windows) +* Improve support of `--help *-format` and several bugs are found and fixed # 2.1.0 From 4c96d0453efd8679723baea96888eae238f17839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 15:15:24 +0800 Subject: [PATCH 17/74] TerminalShell (Linux): add `ash` as a known shell --- src/detection/terminalshell/terminalshell_linux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 957a0b304d..ad2c09dd37 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -150,6 +150,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) //Known shells if ( + strcasecmp(name, "ash") == 0 || strcasecmp(name, "bash") == 0 || strcasecmp(name, "zsh") == 0 || strcasecmp(name, "ksh") == 0 || From 41551ef200a53c7f493ba4563cdc0f5db3406738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 15:15:39 +0800 Subject: [PATCH 18/74] Sound: fix typo --- src/modules/sound/sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 02a954d0ab..cd0ea1ff13 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -177,7 +177,7 @@ void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc if (item->volume != FF_SOUND_VOLUME_UNKNOWN) yyjson_mut_obj_add_uint(doc, obj, "volume", item->volume); else - yyjson_mut_obj_add_null(doc, obj, "volumne"); + yyjson_mut_obj_add_null(doc, obj, "volume"); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier); From 3077f885d88104bbe71f894570a533ae350c5d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 15:43:13 +0800 Subject: [PATCH 19/74] Sound (macOS): ignore input devices --- CHANGELOG.md | 1 + src/detection/sound/sound_apple.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f04c805a3..ffdc06726f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) * Fix possible crashes caused by uninitialized strings (Users, Windows) * Improve support of `--help *-format` and several bugs are found and fixed +* Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS) # 2.1.0 diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index 092d4479d1..1d19621640 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -41,6 +41,14 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */) }, 0, NULL, &dataSize, &name) != kAudioHardwareNoError) continue; + // Ignore input devices + if(AudioObjectGetPropertyDataSize(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyStreams, + kAudioObjectPropertyScopeInput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize) == kAudioHardwareNoError && dataSize > 0) + continue; + uint32_t connected; dataSize = sizeof(connected); if(AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ From 90ea096ca3e4faedcb22aea5ce7282b9ad7cf834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 15:51:05 +0800 Subject: [PATCH 20/74] macOS: don't keep variable `matchDict` --- src/detection/battery/battery_apple.c | 6 +----- src/detection/brightness/brightness_apple.c | 6 +----- src/detection/cpu/cpu_apple.c | 6 +----- src/detection/disk/disk_bsd.c | 3 +-- src/detection/gpu/gpu_apple.c | 3 +-- src/detection/poweradapter/poweradapter_apple.c | 6 +----- src/detection/temps/temps_apple.c | 6 +----- 7 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 52f1797803..c0950c0eef 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -17,12 +17,8 @@ static double detectBatteryTemp(void) const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) { - CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery"); - if (matchDict == NULL) - return "IOServiceMatching(\"AppleSmartBattery\") failed"; - io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; io_registry_entry_t registryEntry; diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index 947115bfb9..7a05ce87ff 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -57,12 +57,8 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* if (!IOAVServiceCreate || !IOAVServiceReadI2C) return "IOAVService is not available"; - CFMutableDictionaryRef matchDict = IOServiceMatching("DCPAVServiceProxy"); - if (matchDict == NULL) - return "IOServiceMatching(\"DCPAVServiceProxy\") failed"; - io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate(); diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index ded5e0d899..418ab21651 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -29,12 +29,8 @@ static const char* detectFrequency(FFCPUResult* cpu) { // https://github.com/giampaolo/psutil/pull/2222/files - CFMutableDictionaryRef matchDict = IOServiceMatching("AppleARMIODevice"); - if (matchDict == NULL) - return "IOServiceMatching(\"AppleARMIODevice\") failed"; - io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; io_registry_entry_t registryEntry; diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 461b31861f..a89f9bd6d8 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -53,9 +53,8 @@ void detectDiskType(FFDisk* disk) // Not thread safe io_iterator_t iterator; char temp = *numEnd; *numEnd = '\0'; // Check for root disk directly - CFMutableDictionaryRef matchDict = IOBSDNameMatching(MACH_PORT_NULL, 0, disk->mountFrom.chars + strlen("/dev/")); *numEnd = temp; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) == kIOReturnSuccess) + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, disk->mountFrom.chars + strlen("/dev/")), &iterator) == kIOReturnSuccess) { for (io_registry_entry_t registryEntry = IOIteratorNext(iterator); registryEntry; IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, ®istryEntry)) { diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 6cb786d6a3..616a62cc99 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -30,9 +30,8 @@ static double detectGpuTemp(const FFstrbuf* gpuName) const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { - CFMutableDictionaryRef matchDict = IOServiceMatching(kIOAcceleratorClassName); io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; io_registry_entry_t registryEntry; diff --git a/src/detection/poweradapter/poweradapter_apple.c b/src/detection/poweradapter/poweradapter_apple.c index 06d8a8df6b..435532ee45 100644 --- a/src/detection/poweradapter/poweradapter_apple.c +++ b/src/detection/poweradapter/poweradapter_apple.c @@ -6,12 +6,8 @@ const char* ffDetectPowerAdapterImpl(FFlist* results) { - CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery"); - if (matchDict == NULL) - return "IOServiceMatching(\"AppleSmartBattery\") failed"; - io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; io_registry_entry_t registryEntry; diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index 7af1e12fe5..7054a3ed33 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -140,12 +140,8 @@ static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcV static const char *smcOpen(io_connect_t *conn) { - CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSMC"); - if (matchDict == NULL) - return "IOServiceMatching(\"AppleSmartBattery\") failed"; - io_iterator_t iterator; - if (IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSMC"), &iterator) != kIOReturnSuccess) return "IOServiceGetMatchingServices() failed"; io_object_t device = IOIteratorNext(iterator); From fe4eb564e105e415f43be67c7d2851021b80966f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 16:12:37 +0800 Subject: [PATCH 21/74] NetIO: add missing `#pragma once` --- src/detection/netio/netio.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/netio/netio.h b/src/detection/netio/netio.h index 295c4478ed..1dd9586a4c 100644 --- a/src/detection/netio/netio.h +++ b/src/detection/netio/netio.h @@ -1,3 +1,5 @@ +#pragma once + #include "fastfetch.h" typedef struct FFNetIOResult From 55f0f75c956e80f198a5deb220f1b757a15f2999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 17:20:39 +0800 Subject: [PATCH 22/74] Packages (Linux): print opkg in JSON format --- src/modules/packages/packages.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index d21c2bd070..2534849262 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -180,6 +180,7 @@ void ffGeneratePackagesJson(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_m FF_APPEND_PACKAGE_COUNT(snap) FF_APPEND_PACKAGE_COUNT(winget) FF_APPEND_PACKAGE_COUNT(xbps) + FF_APPEND_PACKAGE_COUNT(opkg) yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } From b1d63e03d8d80376b937a670a734afd50474a3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 21:06:31 +0800 Subject: [PATCH 23/74] NetIO: fix `--help netio-format` --- src/modules/netio/netio.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 2ee005cb8c..3f6410257d 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -200,10 +200,18 @@ void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mu void ffPrintNetIOHelpFormat(void) { - ffPrintModuleFormatHelp(FF_NETIO_MODULE_NAME, "{1} (IN) - {2} (OUT){4}", FF_NETIO_NUM_FORMAT_ARGS, (const char* []) { + ffPrintModuleFormatHelp(FF_NETIO_MODULE_NAME, "{1} (IN) - {2} (OUT)", FF_NETIO_NUM_FORMAT_ARGS, (const char* []) { "Size of data received per second (formatted)", "Size of data sent per second (formatted)", "Interface name", - "Is default route" + "Is default route", + "Size of data received per second (in bytes)", + "Size of data sent per second (in bytes)", + "Number of packets received per second", + "Number of packets sent per second", + "Number of errors received per second", + "Number of errors sent per second", + "Number of packets dropped when receiving per second", + "Number of packets dropped when sending per second", }); } From 276e22f6b0b7165234fafe283963c68364bdbbe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Oct 2023 16:21:26 +0800 Subject: [PATCH 24/74] DiskIO: init module --- CMakeLists.txt | 5 + src/common/init.c | 2 + src/common/modules.c | 1 + src/detection/disk/disk_windows.c | 2 - src/detection/diskio/diskio.c | 67 +++++++++ src/detection/diskio/diskio.h | 16 +++ src/detection/diskio/diskio_apple.c | 41 ++++++ src/detection/diskio/diskio_linux.c | 93 ++++++++++++ src/detection/diskio/diskio_windows.c | 57 ++++++++ src/fastfetch.h | 1 + src/modules/diskio/diskio.c | 196 ++++++++++++++++++++++++++ src/modules/diskio/diskio.h | 15 ++ src/modules/diskio/option.h | 13 ++ src/modules/modules.h | 1 + src/modules/options.h | 1 + 15 files changed, 509 insertions(+), 2 deletions(-) create mode 100644 src/detection/diskio/diskio.c create mode 100644 src/detection/diskio/diskio.h create mode 100644 src/detection/diskio/diskio_apple.c create mode 100644 src/detection/diskio/diskio_linux.c create mode 100644 src/detection/diskio/diskio_windows.c create mode 100644 src/modules/diskio/diskio.c create mode 100644 src/modules/diskio/diskio.h create mode 100644 src/modules/diskio/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 47af8e6afb..776317577a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,6 +273,7 @@ set(LIBFASTFETCH_SRC src/detection/cpu/cpu.c src/detection/cpuusage/cpuusage.c src/detection/disk/disk.c + src/detection/diskio/diskio.c src/detection/displayserver/displayserver.c src/detection/font/font.c src/detection/gpu/gpu.c @@ -310,6 +311,7 @@ set(LIBFASTFETCH_SRC src/modules/datetime/datetime.c src/modules/de/de.c src/modules/disk/disk.c + src/modules/diskio/diskio.c src/modules/font/font.c src/modules/gpu/gpu.c src/modules/host/host.c @@ -375,6 +377,7 @@ if(LINUX) src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_linux.c src/detection/disk/disk_linux.c + src/detection/diskio/diskio_linux.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/wayland.c src/detection/displayserver/linux/wmde.c @@ -534,6 +537,7 @@ elseif(APPLE) src/detection/cpuusage/cpuusage_apple.c src/detection/cursor/cursor_apple.m src/detection/disk/disk_bsd.c + src/detection/diskio/diskio_apple.c src/detection/displayserver/displayserver_apple.c src/detection/font/font_apple.m src/detection/gpu/gpu_apple.c @@ -584,6 +588,7 @@ elseif(WIN32) src/detection/cpuusage/cpuusage_windows.c src/detection/cursor/cursor_windows.c src/detection/disk/disk_windows.c + src/detection/diskio/diskio_windows.c src/detection/displayserver/displayserver_windows.c src/detection/font/font_windows.c src/detection/gpu/gpu_windows.c diff --git a/src/common/init.c b/src/common/init.c index 4510a261ef..15b4391e80 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -93,6 +93,7 @@ static void defaultConfig(void) ffInitDEOptions(&instance.config.de); ffInitDateTimeOptions(&instance.config.dateTime); ffInitDiskOptions(&instance.config.disk); + ffInitDiskIOOptions(&instance.config.diskio); ffInitDisplayOptions(&instance.config.display); ffInitFontOptions(&instance.config.font); ffInitGPUOptions(&instance.config.gpu); @@ -307,6 +308,7 @@ static void destroyConfig(void) ffDestroyDEOptions(&instance.config.de); ffDestroyDateTimeOptions(&instance.config.dateTime); ffDestroyDiskOptions(&instance.config.disk); + ffDestroyDiskIOOptions(&instance.config.diskio); ffDestroyDisplayOptions(&instance.config.display); ffDestroyFontOptions(&instance.config.font); ffDestroyGPUOptions(&instance.config.gpu); diff --git a/src/common/modules.c b/src/common/modules.c index 420903c8ee..3d0cf284ab 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -30,6 +30,7 @@ static FFModuleBaseInfo* D[] = { (void*) &instance.config.de, (void*) &instance.config.display, (void*) &instance.config.disk, + (void*) &instance.config.diskio, NULL, }; diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index 35f1722c49..d67338ff16 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -57,9 +57,7 @@ const char* ffDetectDisksImpl(FFlist* disks) } if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName))) - { ffStrbufInitWS(&disk->mountFrom, volumeName); - } else ffStrbufInit(&disk->mountFrom); diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c new file mode 100644 index 0000000000..5d49e6268b --- /dev/null +++ b/src/detection/diskio/diskio.c @@ -0,0 +1,67 @@ +#include "diskio.h" + +#include "common/time.h" + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options); + +static FFlist ioCounters1; +static uint64_t time1; + +void ffPrepareDiskIO(FFDiskIOOptions* options) +{ + ffListInit(&ioCounters1, sizeof(FFDiskIOOptions)); + ffDiskIOGetIoCounters(&ioCounters1, options); + time1 = ffTimeGetNow(); +} + +const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) +{ + const char* error = NULL; + if (time1 == 0) + { + ffListInit(&ioCounters1, sizeof(FFDiskIOResult)); + error = ffDiskIOGetIoCounters(&ioCounters1, options); + if (error) + return error; + time1 = ffTimeGetNow(); + } + + if (ioCounters1.length == 0) + return "No physical disk found"; + + uint64_t time2 = ffTimeGetNow(); + while (time2 - time1 < 1000) + { + ffTimeSleep((uint32_t) (1000 - (time2 - time1))); + time2 = ffTimeGetNow(); + } + + error = ffDiskIOGetIoCounters(result, options); + if (error) + return error; + + if (result->length != ioCounters1.length) + return "Different number of physical disks. Hardware change?"; + + for (uint32_t i = 0; i < result->length; ++i) + { + FFDiskIOResult* icPrev = (FFDiskIOResult*)ffListGet(&ioCounters1, i); + FFDiskIOResult* icCurr = (FFDiskIOResult*)ffListGet(result, i); + if (!ffStrbufEqual(&icPrev->name, &icCurr->name)) + return "Network interface name changed"; + + static_assert(sizeof(FFDiskIOResult) - offsetof(FFDiskIOResult, bytesRead) == sizeof(uint64_t) * 4, "Unexpected struct FFDiskIOResult layout"); + for (size_t off = offsetof(FFDiskIOResult, bytesRead); off < sizeof(FFDiskIOResult); off += sizeof(uint64_t)) + { + uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); + uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); + uint64_t temp = *currValue; + *currValue -= *prevValue; + *currValue /= (time2 - time1) / 1000 /* seconds */; + *prevValue = temp; + } + } + time1 = time2; + + return NULL; +} diff --git a/src/detection/diskio/diskio.h b/src/detection/diskio/diskio.h new file mode 100644 index 0000000000..d0d8d0b4e6 --- /dev/null +++ b/src/detection/diskio/diskio.h @@ -0,0 +1,16 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFDiskIOResult +{ + FFstrbuf name; + FFstrbuf type; + FFstrbuf devPath; + uint64_t bytesRead; + uint64_t readCount; + uint64_t bytesWritten; + uint64_t writeCount; +} FFDiskIOResult; + +const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options); diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c new file mode 100644 index 0000000000..dad4bd2947 --- /dev/null +++ b/src/detection/diskio/diskio_apple.c @@ -0,0 +1,41 @@ +#include "diskio.h" + +#include +#include +#include + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + io_iterator_t iterator; + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != kIOReturnSuccess) + return "IOServiceGetMatchingServices() failed"; + + io_registry_entry_t registryEntry; + while((registryEntry = IOIteratorNext(iterator)) != 0) + { + CFMutableDictionaryRef properties; + if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) + { + IOObjectRelease(registryEntry); + continue; + } + + io_registry_entry_t parent; + IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parent); + if(IOObjectConformsTo(parent, kIOBlockStorageDriverClass)) continue; + + io_name_t name; + if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS) + continue; + + // NSDictionary* props = (__bridge NSDictionary*) properties; + + // id statistics = [props valueForKey:@(kIOBlockStorageDriverStatisticsKey)]; + // if (!statistics) continue; + + // id volGroupaMntFromName = [props valueForKey:@"VolGroupMntFromName"]; + // if (!volGroupaMntFromName) continue; + + // NSLog(@"%@", props); + } +} diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c new file mode 100644 index 0000000000..18db094537 --- /dev/null +++ b/src/detection/diskio/diskio_linux.c @@ -0,0 +1,93 @@ +#include "diskio.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +#include +#include + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS("/dev/disk/by-id/"); + uint32_t baseDirLength = baseDir.length; + + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); + if(dirp == NULL) + return "opendir(batteryDir) == NULL"; + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (entry->d_name[0] == '.') + continue; + + char* part = strstr(entry->d_name, "-part"); + if (part && isdigit(part[strlen("-part")])) + continue; + + if (ffStrStartsWith(entry->d_name, "nvme-eui.")) // NVMe drive indentifier + continue; + + // Other exceptions? + + ffStrbufAppendS(&baseDir, entry->d_name); + char pathDev[PATH_MAX]; + ssize_t pathLen = readlink(baseDir.chars, pathDev, PATH_MAX); + ffStrbufSubstrBefore(&baseDir, baseDirLength); + + if (pathLen < 0) continue; + pathDev[pathLen] = '\0'; // ../../nvme0n1 + + char pathDev1[PATH_MAX]; + const char* devName = basename(pathDev); + snprintf(pathDev1, PATH_MAX, "/dev/%s", devName); + + // Avoid duplicated disks + bool flag = false; + FF_LIST_FOR_EACH(FFDiskIOResult, disk, *result) + { + if (ffStrbufEqualS(&disk->devPath, pathDev1)) + { + flag = true; + break; + } + } + if (flag) continue; + + char pathSysBlockStat[PATH_MAX]; + snprintf(pathSysBlockStat, PATH_MAX, "/sys/block/%s/stat", devName); + + FF_AUTO_CLOSE_FILE FILE* sysBlockStat = fopen(pathSysBlockStat, "r"); + if (!sysBlockStat) continue; + + // I/Os merges sectors ticks ... + uint64_t nRead, sectorRead, nWritten, sectorWritten; + if (fscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, §orRead, &nWritten, §orWritten) == 0) + continue; + + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + char* slash = strchr(entry->d_name, '-'); + if (slash) + { + char* slash2 = strchr(slash + 1, '-'); + if (slash2) + ffStrbufInitNS(&device->name, (uint32_t) (slash2 - slash - 1), slash + 1); + else + ffStrbufInitS(&device->name, slash + 1); + ffStrbufInitNS(&device->type, (uint32_t) (slash - entry->d_name), entry->d_name); + } + else + { + ffStrbufInitS(&device->name, entry->d_name); + ffStrbufInit(&device->type); + } + ffStrbufReplaceAllC(&device->name, '_', ' '); + + ffStrbufInitS(&device->devPath, pathDev1); + device->bytesRead = sectorRead * 512; + device->bytesWritten = sectorWritten * 512; + device->readCount = nRead; + device->writeCount = nWritten; + } + + return NULL; +} diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c new file mode 100644 index 0000000000..2a894b4d4e --- /dev/null +++ b/src/detection/diskio/diskio_windows.c @@ -0,0 +1,57 @@ +#include "diskio.h" +#include "common/io/io.h" +#include "util/windows/registry.h" +#include "util/windows/unicode.h" + +#include + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + FF_HKEY_AUTO_DESTROY hKey = NULL; + if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", &hKey, NULL)) + return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum\") failed"; + + uint32_t nDevices; + if (!ffRegReadUint(hKey, L"Count", &nDevices, NULL)) + return "ffRegReadUint(hKey, L\"Count\", &nDevices) failed"; + + wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive"; + wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive"); + for (uint32_t idev = 0; idev <= nDevices; ++idev) { + _ultow(idev, pNum, 10); + + FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + continue; + + DISK_PERFORMANCE diskPerformance; + DWORD ioctrlSize = sizeof(diskPerformance); + DWORD dwSize; + if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance, ioctrlSize, &dwSize, NULL)) + { + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + ffStrbufInit(&device->name); + ffStrbufInit(&device->type); + if (ffRegReadStrbuf(hKey, pNum, &device->name, NULL)) + { + // SCSI\Disk&Ven_NVMe&Prod_WDC_PC_SN810_SDC\5&19cebb7&0&000000 + uint32_t index = ffStrbufFirstIndexC(&device->name, '\\'); + if (index != device->name.length) + ffStrbufAppendNS(&device->type, index, device->name.chars); // SCSI + ffStrbufSubstrAfterFirstS(&device->name, "&Prod_"); + ffStrbufSubstrBeforeLastC(&device->name, '\\'); + ffStrbufReplaceAllC(&device->name, '_', ' '); + } + else + ffStrbufSetWS(&device->name, szDevice); + + ffStrbufInitWS(&device->devPath, szDevice); + device->bytesRead = (uint64_t) diskPerformance.BytesRead.QuadPart; + device->readCount = (uint64_t) diskPerformance.ReadCount; + device->bytesWritten = (uint64_t) diskPerformance.BytesWritten.QuadPart; + device->writeCount = (uint64_t) diskPerformance.WriteCount; + } + } + + return NULL; +} diff --git a/src/fastfetch.h b/src/fastfetch.h index 0877c1088a..04d19970ee 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -99,6 +99,7 @@ typedef struct FFconfig FFDEOptions de; FFDateTimeOptions dateTime; FFDiskOptions disk; + FFDiskIOOptions diskio; FFDisplayOptions display; FFFontOptions font; FFGPUOptions gpu; diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c new file mode 100644 index 0000000000..07acbc7b18 --- /dev/null +++ b/src/modules/diskio/diskio.c @@ -0,0 +1,196 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "common/parsing.h" +#include "detection/diskio/diskio.h" +#include "modules/diskio/diskio.h" +#include "util/stringUtils.h" + +#define FF_DISKIO_DISPLAY_NAME "Disk IO" +#define FF_DISKIO_NUM_FORMAT_ARGS 7 + +static int sortDevices(const FFDiskIOResult* left, const FFDiskIOResult* right) +{ + return ffStrbufComp(&left->name, &right->name); +} + +static void formatKey(const FFDiskIOOptions* options, FFDiskIOResult* dev, uint32_t index, FFstrbuf* key) +{ + if(options->moduleArgs.key.length == 0) + { + if(!dev->name.length) + ffStrbufSetF(&dev->name, "unknown %u", (unsigned) index); + + ffStrbufSetF(key, FF_DISKIO_DISPLAY_NAME " (%s)", dev->name.chars); + } + else + { + ffStrbufClear(key); + ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->type}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, + }); + } +} + +void ffPrintDiskIO(FFDiskIOOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFDiskIOResult)); + const char* error = ffDetectDiskIO(&result, options); + + if(error) + { + ffPrintError(FF_DISKIO_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); + return; + } + + ffListSort(&result, (const void*) sortDevices); + + uint32_t index = 0; + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + formatKey(options, dev, result.length == 1 ? 0 : index + 1, &key); + ffStrbufClear(&buffer); + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + ffParseSize(dev->bytesRead, &buffer); + ffStrbufAppendS(&buffer, "/s (R) - "); + ffParseSize(dev->bytesWritten, &buffer); + ffStrbufAppendS(&buffer, "/s (W)"); + ffStrbufPutTo(&buffer, stdout); + } + else + { + ffStrbufClear(&buffer2); + ffParseSize(dev->bytesRead, &buffer); + ffStrbufAppendS(&buffer, "/s"); + ffParseSize(dev->bytesWritten, &buffer2); + ffStrbufAppendS(&buffer2, "/s"); + + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISKIO_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->type}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesRead}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesWritten}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->readCount}, + {FF_FORMAT_ARG_TYPE_UINT64, &dev->writeCount}, + }); + } + ++index; + } + + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + ffStrbufDestroy(&dev->name); + ffStrbufDestroy(&dev->type); + ffStrbufDestroy(&dev->devPath); + } +} + +void ffInitDiskIOOptions(FFDiskIOOptions* options) +{ + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISKIO_MODULE_NAME, ffParseDiskIOCommandOptions, ffParseDiskIOJsonObject, ffPrintDiskIO, ffGenerateDiskIOJson, ffPrintDiskIOHelpFormat); + ffOptionInitModuleArg(&options->moduleArgs); + + ffStrbufInit(&options->namePrefix); +} + +bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_DISKIO_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + if (ffStrEqualsIgnCase(subKey, "name-prefix")) + { + ffOptionParseString(key, value, &options->namePrefix); + return true; + } + + return false; +} + +void ffDestroyDiskIOOptions(FFDiskIOOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); +} + +void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + if (ffStrEqualsIgnCase(key, "namePrefix")) + { + ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + continue; + } + + ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); + } +} + +void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFDiskIOResult)); + const char* error = ffDetectDiskIO(&result, options); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFDiskIOResult, counter, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); + yyjson_mut_obj_add_strbuf(doc, obj, "type", &counter->type); + yyjson_mut_obj_add_uint(doc, obj, "bytesRead", counter->bytesRead); + yyjson_mut_obj_add_uint(doc, obj, "bytesWritten", counter->bytesWritten); + yyjson_mut_obj_add_uint(doc, obj, "readCount", counter->readCount); + yyjson_mut_obj_add_uint(doc, obj, "writeCount", counter->writeCount); + } + + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) + { + ffStrbufDestroy(&dev->name); + ffStrbufDestroy(&dev->type); + ffStrbufDestroy(&dev->devPath); + } +} + +void ffPrintDiskIOHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_DISKIO_MODULE_NAME, "{1} (R) - {2} (W)", FF_DISKIO_NUM_FORMAT_ARGS, (const char* []) { + "Size of data read per second (formatted)", + "Size of data written per second (formatted)", + "Device name", + "Device type", + "Size of data read per second (in bytes)", + "Size of data written per second (in bytes)", + "Number of reads", + "Number of writes", + }); +} diff --git a/src/modules/diskio/diskio.h b/src/modules/diskio/diskio.h new file mode 100644 index 0000000000..ab4502f11a --- /dev/null +++ b/src/modules/diskio/diskio.h @@ -0,0 +1,15 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_DISKIO_MODULE_NAME "DiskIO" + +void ffPrepareDiskIO(FFDiskIOOptions* options); + +void ffPrintDiskIO(FFDiskIOOptions* options); +void ffInitDiskIOOptions(FFDiskIOOptions* options); +bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, const char* value); +void ffDestroyDiskIOOptions(FFDiskIOOptions* options); +void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module); +void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); +void ffPrintDiskIOHelpFormat(void); diff --git a/src/modules/diskio/option.h b/src/modules/diskio/option.h new file mode 100644 index 0000000000..b3e3303553 --- /dev/null +++ b/src/modules/diskio/option.h @@ -0,0 +1,13 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFDiskIOOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; + + FFstrbuf namePrefix; +} FFDiskIOOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 64ab6ea213..57632fb7dc 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -17,6 +17,7 @@ #include "modules/custom/custom.h" #include "modules/datetime/datetime.h" #include "modules/disk/disk.h" +#include "modules/diskio/diskio.h" #include "modules/display/display.h" #include "modules/de/de.h" #include "modules/font/font.h" diff --git a/src/modules/options.h b/src/modules/options.h index 1be2e88e0c..191767c770 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -18,6 +18,7 @@ #include "modules/datetime/option.h" #include "modules/de/option.h" #include "modules/disk/option.h" +#include "modules/diskio/option.h" #include "modules/display/option.h" #include "modules/font/option.h" #include "modules/host/option.h" From e4a6bf17e4f3d7e4fae5d48a5947a145f19a25cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 09:24:13 +0800 Subject: [PATCH 25/74] Terminal: support kgx (gnome console) Fix #577 --- .../terminalfont/terminalfont_linux.c | 25 ++++++++++++++++++- src/detection/terminalshell/terminalshell.c | 14 +++++++++++ .../terminalshell/terminalshell_linux.c | 4 ++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 6833ba0863..1349e96b25 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -27,6 +27,27 @@ static const char* getSystemMonospaceFont(void) return ffSettingsGet("/org/gnome/desktop/interface/monospace-font-name", "org.gnome.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue; } +static void detectKgx(FFTerminalFontResult* terminalFont) +{ + // kgx (gnome terminal) doesn't support profiles + if(!ffSettingsGet("/org/gnome/Console/use-system-font", "org.gnome.Console", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue) + { + FF_AUTO_FREE const char* fontName = ffSettingsGet("/org/gnome/Console/custom-font", "org.gnome.Console", NULL, "custom-font", FF_VARIANT_TYPE_STRING).strValue; + if(ffStrSet(fontName)) + ffFontInitPango(&terminalFont->font, fontName); + else + ffStrbufAppendF(&terminalFont->error, "Couldn't get terminal font from GSettings (org.gnome.Console::custom-font)"); + } + else + { + FF_AUTO_FREE const char* fontName = getSystemMonospaceFont(); + if(ffStrSet(fontName)) + ffFontInitPango(&terminalFont->font, fontName); + else + ffStrbufAppendS(&terminalFont->error, "Could't get system monospace font name from GSettings / DConf"); + } +} + static void detectFromGSettings(const char* profilePath, const char* profileList, const char* profile, const char* defaultProfileKey, FFTerminalFontResult* terminalFont) { FF_AUTO_FREE const char* defaultProfile = ffSettingsGetGSettings(profileList, NULL, defaultProfileKey, FF_VARIANT_TYPE_STRING).strValue; @@ -51,7 +72,7 @@ static void detectFromGSettings(const char* profilePath, const char* profileList } else { - const char* fontName = getSystemMonospaceFont(); + FF_AUTO_FREE const char* fontName = getSystemMonospaceFont(); if(ffStrSet(fontName)) ffFontInitPango(&terminalFont->font, fontName); else @@ -243,6 +264,8 @@ void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FF detectFromGSettings("/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", "default", terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "gnome-terminal-")) detectFromGSettings("/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", "default", terminalFont); + else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kgx")) + detectKgx(terminalFont); else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "mate-terminal")) detectFromGSettings("/org/mate/terminal/profiles/", "org.mate.terminal.global", "org.mate.terminal.profile", "default-profile", terminalFont); else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "deepin-terminal")) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index cad8c5cbcc..822812882f 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -206,6 +206,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version) return true; } +FF_MAYBE_UNUSED static bool getTerminalVersionKgx(FFstrbuf* version) +{ + if(ffProcessAppendStdOut(version, (char* const[]){ + "gnome-terminal", + "--version", + NULL + })) return false; + + //# KGX 45.0 using VTE 0.74.0 +BIDI +GNUTLS +ICU +SYSTEMD + ffStrbufSubstrAfterFirstS(version, "KGX "); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* version) { const char* konsoleVersion = getenv("KONSOLE_VERSION"); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index ad2c09dd37..810fe90bc9 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -385,7 +385,9 @@ const FFTerminalShellResult* ffDetectTerminalShell() #elif defined(__linux__) || defined(__FreeBSD__) else if(ffStrbufStartsWithS(&result.terminalProcessName, "gnome-terminal-")) - ffStrbufInitStatic(&result.terminalPrettyName, "gnome-terminal"); + ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Terminal"); + else if(ffStrbufStartsWithS(&result.terminalProcessName, "kgx")) + ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Console"); #elif defined(__APPLE__) From 49e2acd15ef20d774e278add7e1769cc883ec243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 09:46:40 +0800 Subject: [PATCH 26/74] Printing: fix `--help *-format` --- src/common/printing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/printing.c b/src/common/printing.c index d03d7b40eb..b5a32175ba 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -143,7 +143,7 @@ void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs puts("The following values are passed:"); for(unsigned i = 0; i < numArgs; i++) - printf(" {%u}: %s\n", i, args[i]); + printf(" {%u}: %s\n", i + 1, args[i]); printf("The default is something similar to \"%s\".\n", def); } From d7649d9f8f7e6c5f9443e87b9e84826dcfc305bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 09:51:13 +0800 Subject: [PATCH 27/74] DiskIO: fix building --- CMakeLists.txt | 2 ++ src/detection/diskio/diskio_apple.c | 4 ++++ src/detection/diskio/diskio_bsd.c | 11 +++++++++++ 3 files changed, 17 insertions(+) create mode 100644 src/detection/diskio/diskio_bsd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 776317577a..0b2b551463 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -432,6 +432,7 @@ elseif(ANDROID) src/detection/cursor/cursor_nosupport.c src/detection/cpuusage/cpuusage_linux.c src/detection/disk/disk_linux.c + src/detection/diskio/diskio_linux.c src/detection/displayserver/displayserver_android.c src/detection/font/font_nosupport.c src/detection/gpu/gpu_nosupport.c @@ -482,6 +483,7 @@ elseif(BSD) src/detection/cpuusage/cpuusage_bsd.c src/detection/cursor/cursor_linux.c src/detection/disk/disk_bsd.c + src/detection/diskio/diskio_bsd.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/wayland.c src/detection/displayserver/linux/wmde.c diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c index dad4bd2947..8841ba8a05 100644 --- a/src/detection/diskio/diskio_apple.c +++ b/src/detection/diskio/diskio_apple.c @@ -38,4 +38,8 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) // NSLog(@"%@", props); } + + IOObjectRelease(iterator); + + return NULL; } diff --git a/src/detection/diskio/diskio_bsd.c b/src/detection/diskio/diskio_bsd.c new file mode 100644 index 0000000000..b86f3a0a3d --- /dev/null +++ b/src/detection/diskio/diskio_bsd.c @@ -0,0 +1,11 @@ +#include "diskio.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +#include +#include + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + return "Not supported on this platform"; +} From 4c9d9f6223b0ece25d128d7779b7d9916dd49b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 09:53:32 +0800 Subject: [PATCH 28/74] TerminalFont (Linux): fix typo --- CHANGELOG.md | 1 + src/detection/terminalfont/terminalfont_linux.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffdc06726f..c4b7dec245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Features: * Support opkg (Packages, Linux) +* Support GNOME Console terminal version and font detection (Terminal, Linux) Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 1349e96b25..c9f1b34215 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -29,7 +29,7 @@ static const char* getSystemMonospaceFont(void) static void detectKgx(FFTerminalFontResult* terminalFont) { - // kgx (gnome terminal) doesn't support profiles + // kgx (gnome console) doesn't support profiles if(!ffSettingsGet("/org/gnome/Console/use-system-font", "org.gnome.Console", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue) { FF_AUTO_FREE const char* fontName = ffSettingsGet("/org/gnome/Console/custom-font", "org.gnome.Console", NULL, "custom-font", FF_VARIANT_TYPE_STRING).strValue; From 78249bf4f72c98e94b3e332589a45bbeb16c76c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 10:09:56 +0800 Subject: [PATCH 29/74] CPU: add new option `--cpu-freq-ndigits` Fix #578 --- CHANGELOG.md | 1 + doc/json_schema.json | 7 +++++++ src/data/help.txt | 9 +++++---- src/modules/cpu/cpu.c | 15 ++++++++++++++- src/modules/cpu/option.h | 1 + 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b7dec245..a363ec15db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Features: * Support opkg (Packages, Linux) * Support GNOME Console terminal version and font detection (Terminal, Linux) +* Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU) Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) diff --git a/doc/json_schema.json b/doc/json_schema.json index d7e681566c..910192a9ba 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -737,6 +737,13 @@ "type": "boolean", "default": false }, + "freqNdigits": { + "title": "Set the number of digits to keep after the decimal point when printing CPU frequency", + "type": "integer", + "minimum": 0, + "maximum": 9, + "default": 2 + }, "key": { "$ref": "#/$defs/key" }, diff --git a/src/data/help.txt b/src/data/help.txt index 94ba7f6175..440ff9aa41 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -138,11 +138,12 @@ Module specific options: --display-precise-refresh-rate: :Set if decimal refresh rates should not be rounded into integers when printing. Default is true --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 - --gpu-force-vulkan : Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false + --cpu-temp : Detect and display CPU temperature if supported. Default is false + --cpu-freq-ndigits : Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2 + --gpu-temp : Detect and display GPU temperature if supported. Default is false + --gpu-force-vulkan : Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false --gpu-hide-type : Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none - --battery-temp : Detect and display Battery temperature 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-mac : Show mac addresses in local ip module. Default is false diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 8626466141..133bebec95 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -48,7 +48,7 @@ void ffPrintCPU(FFCPUOptions* options) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); if(cpu.frequencyMax > 0.0) - ffStrbufAppendF(&str, " @ %.9g GHz", cpu.frequencyMax); + ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, cpu.frequencyMax); if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET { @@ -82,6 +82,7 @@ void ffInitCPUOptions(FFCPUOptions* options) ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, ffGenerateCPUJson, ffPrintCPUHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; + options->freqNdigits = 2; } bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char* value) @@ -97,6 +98,12 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char return true; } + if (ffStrEqualsIgnCase(subKey, "freq-ndigits")) + { + options->freqNdigits = (uint8_t) ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -124,6 +131,12 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "freqNdigits")) + { + options->freqNdigits = (uint8_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } diff --git a/src/modules/cpu/option.h b/src/modules/cpu/option.h index 1902ddfc27..ae5699939c 100644 --- a/src/modules/cpu/option.h +++ b/src/modules/cpu/option.h @@ -10,4 +10,5 @@ typedef struct FFCPUOptions FFModuleArgs moduleArgs; bool temp; + uint8_t freqNdigits; } FFCPUOptions; From 085d0924dbe3876b1ce980606cabc649cb5dcb24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 10:34:01 +0800 Subject: [PATCH 30/74] Brightness (Linux): try improving compatibility of ddcutil 2.0 ddcutil 2.0 increases SONAME version to `libddcutil.so.5`. More testing needed Ref: #576 --- src/detection/brightness/brightness_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index b3e75b2347..d46599a851 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -94,7 +94,7 @@ static const char* detectWithBacklight(FFlist* result) static const char* detectWithDdcci(FFlist* result) { - FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 4); + FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type) From b2130477ae7ce274b3084fde98451e55efca3dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 15:57:31 +0800 Subject: [PATCH 31/74] DiskIO (macOS): add support --- src/detection/diskio/diskio_apple.c | 65 ++++++++++++++++++++--------- src/util/apple/cf_helpers.c | 23 ++++++++++ src/util/apple/cf_helpers.h | 1 + 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c index 8841ba8a05..0bdd7a515f 100644 --- a/src/detection/diskio/diskio_apple.c +++ b/src/detection/diskio/diskio_apple.c @@ -1,45 +1,70 @@ #include "diskio.h" +#include "util/apple/cf_helpers.h" #include +#include #include #include +#include + +static inline void wrapIoObjectRelease(io_service_t* service) +{ + assert(service); + if (*service) + IOObjectRelease(*service); +} +#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease))) const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) { - io_iterator_t iterator; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != kIOReturnSuccess) + FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0; + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS) return "IOServiceGetMatchingServices() failed"; io_registry_entry_t registryEntry; while((registryEntry = IOIteratorNext(iterator)) != 0) { - CFMutableDictionaryRef properties; - if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) - { - IOObjectRelease(registryEntry); + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry; + + io_name_t deviceName; + if (IORegistryEntryGetName(registryEntry, deviceName) != KERN_SUCCESS) continue; - } - io_registry_entry_t parent; - IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parent); - if(IOObjectConformsTo(parent, kIOBlockStorageDriverClass)) continue; + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDriver = 0; + if (IORegistryEntryGetParentEntry(entryPartition, kIOServicePlane, &entryDriver) != KERN_SUCCESS) + continue; - io_name_t name; - if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS) + if (!IOObjectConformsTo(entryDriver, kIOBlockStorageDriverClass)) // physical disk only continue; - // NSDictionary* props = (__bridge NSDictionary*) properties; + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef statistics = IORegistryEntryCreateCFProperty(entryDriver, CFSTR(kIOBlockStorageDriverStatisticsKey), kCFAllocatorDefault, kNilOptions); + if (!statistics) + continue; - // id statistics = [props valueForKey:@(kIOBlockStorageDriverStatisticsKey)]; - // if (!statistics) continue; + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + ffStrbufInitS(&device->name, deviceName); + ffStrbufInit(&device->devPath); + ffStrbufInit(&device->type); + ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey), (int64_t*) &device->bytesRead); + ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey), (int64_t*) &device->bytesWritten); + ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey), (int64_t*) &device->readCount); + ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey), (int64_t*) &device->writeCount); - // id volGroupaMntFromName = [props valueForKey:@"VolGroupMntFromName"]; - // if (!volGroupaMntFromName) continue; + FF_CFTYPE_AUTO_RELEASE CFStringRef bsdName = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions); + if (bsdName) + { + ffCfStrGetString(bsdName, &device->devPath); + ffStrbufPrependS(&device->devPath, "/dev/"); + } - // NSLog(@"%@", props); + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0; + if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS) + { + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions); + if (protocolCharacteristics) + ffCfDictGetString(protocolCharacteristics, CFSTR("Physical Interconnect"), &device->type); + } } - IOObjectRelease(iterator); - return NULL; } diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 2ce563d5ed..96b7651141 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -83,6 +83,29 @@ const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) return "TypeID is neither 'CFNumber' nor 'CFData'"; } +const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result) +{ + CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); + if(cf == NULL) + return "CFDictionaryGetValue() failed"; + + if(CFGetTypeID(cf) == CFNumberGetTypeID()) + { + if(!CFNumberGetValue((CFNumberRef)cf, kCFNumberSInt64Type, result)) + return "Number type is not SInt64"; + return NULL; + } + else if(CFGetTypeID(cf) == CFDataGetTypeID()) + { + if(CFDataGetLength((CFDataRef)cf) != sizeof(int64_t)) + return "Data length is not sizeof(int64_t)"; + CFDataGetBytes((CFDataRef)cf, CFRangeMake(0, sizeof(int64_t)), (uint8_t*)result); + return NULL; + } + + return "TypeID is neither 'CFNumber' nor 'CFData'"; +} + const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length) { CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index a8d9804a3f..2137766bb2 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -11,6 +11,7 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result); const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result); const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result); const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result); +const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result); const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length); const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result); From 0b0e286b9c336627c694af7870ae61228b1841e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 16:30:09 +0800 Subject: [PATCH 32/74] DiskIO: support `--diskio-name-prefix` --- src/common/commandoption.c | 3 +++ src/common/init.c | 4 ++-- src/common/jsonconfig.c | 8 ++++++++ src/common/modules.c | 2 +- src/detection/diskio/diskio_apple.c | 3 +++ src/detection/diskio/diskio_linux.c | 8 ++++++++ src/detection/diskio/diskio_windows.c | 8 ++++++++ src/fastfetch.h | 2 +- 8 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/common/commandoption.c b/src/common/commandoption.c index e8a7e8001d..7b0402b51c 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -60,6 +60,9 @@ void ffPrepareCommandOption(FFdata* data) if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME)) ffPrepareCPUUsage(); + if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME)) + ffPrepareDiskIO(&instance.config.diskIo); + if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME)) ffPrepareNetIO(&instance.config.netIo); diff --git a/src/common/init.c b/src/common/init.c index 15b4391e80..eab996eaa1 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -93,7 +93,7 @@ static void defaultConfig(void) ffInitDEOptions(&instance.config.de); ffInitDateTimeOptions(&instance.config.dateTime); ffInitDiskOptions(&instance.config.disk); - ffInitDiskIOOptions(&instance.config.diskio); + ffInitDiskIOOptions(&instance.config.diskIo); ffInitDisplayOptions(&instance.config.display); ffInitFontOptions(&instance.config.font); ffInitGPUOptions(&instance.config.gpu); @@ -308,7 +308,7 @@ static void destroyConfig(void) ffDestroyDEOptions(&instance.config.de); ffDestroyDateTimeOptions(&instance.config.dateTime); ffDestroyDiskOptions(&instance.config.disk); - ffDestroyDiskIOOptions(&instance.config.diskio); + ffDestroyDiskIOOptions(&instance.config.diskIo); ffDestroyDisplayOptions(&instance.config.display); ffDestroyFontOptions(&instance.config.font); ffDestroyGPUOptions(&instance.config.gpu); diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 6d8fee3291..26dd884d68 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -112,6 +112,14 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) ffPrepareCPUUsage(); break; } + case 'd': case 'D': { + if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME)) + { + if (module) ffParseDiskIOJsonObject(&cfg->diskIo, module); + ffPrepareDiskIO(&cfg->diskIo); + } + break; + } case 'n': case 'N': { if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) { diff --git a/src/common/modules.c b/src/common/modules.c index 3d0cf284ab..2164701448 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -30,7 +30,7 @@ static FFModuleBaseInfo* D[] = { (void*) &instance.config.de, (void*) &instance.config.display, (void*) &instance.config.disk, - (void*) &instance.config.diskio, + (void*) &instance.config.diskIo, NULL, }; diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c index 0bdd7a515f..89f8ed3cfe 100644 --- a/src/detection/diskio/diskio_apple.c +++ b/src/detection/diskio/diskio_apple.c @@ -30,6 +30,9 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) if (IORegistryEntryGetName(registryEntry, deviceName) != KERN_SUCCESS) continue; + if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDriver = 0; if (IORegistryEntryGetParentEntry(entryPartition, kIOServicePlane, &entryDriver) != KERN_SUCCESS) continue; diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c index 18db094537..fdd73c8f79 100644 --- a/src/detection/diskio/diskio_linux.c +++ b/src/detection/diskio/diskio_linux.c @@ -82,6 +82,14 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) } ffStrbufReplaceAllC(&device->name, '_', ' '); + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + ffStrbufDestroy(&device->type); + result->length--; + continue; + } + ffStrbufInitS(&device->devPath, pathDev1); device->bytesRead = sectorRead * 512; device->bytesWritten = sectorWritten * 512; diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index 2a894b4d4e..b535e8299f 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -45,6 +45,14 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) else ffStrbufSetWS(&device->name, szDevice); + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + ffStrbufDestroy(&device->type); + result->length--; + continue; + } + ffStrbufInitWS(&device->devPath, szDevice); device->bytesRead = (uint64_t) diskPerformance.BytesRead.QuadPart; device->readCount = (uint64_t) diskPerformance.ReadCount; diff --git a/src/fastfetch.h b/src/fastfetch.h index 04d19970ee..cbb307a15f 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -99,7 +99,7 @@ typedef struct FFconfig FFDEOptions de; FFDateTimeOptions dateTime; FFDiskOptions disk; - FFDiskIOOptions diskio; + FFDiskIOOptions diskIo; FFDisplayOptions display; FFFontOptions font; FFGPUOptions gpu; From 5c5c66d960aeab7cda85f8148ce5bf966e3d184b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 16:38:50 +0800 Subject: [PATCH 33/74] DiskIO: fix segfault... --- src/detection/diskio/diskio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c index 5d49e6268b..cb452743e6 100644 --- a/src/detection/diskio/diskio.c +++ b/src/detection/diskio/diskio.c @@ -9,7 +9,7 @@ static uint64_t time1; void ffPrepareDiskIO(FFDiskIOOptions* options) { - ffListInit(&ioCounters1, sizeof(FFDiskIOOptions)); + ffListInit(&ioCounters1, sizeof(FFDiskIOResult)); ffDiskIOGetIoCounters(&ioCounters1, options); time1 = ffTimeGetNow(); } From 8df6409cb14d97ae7fb32df36ce2780bc504033c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 16:46:53 +0800 Subject: [PATCH 34/74] DiskIO (Windows): better device name detection --- src/detection/diskio/diskio_windows.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index b535e8299f..452f90bccb 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -38,8 +38,9 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) uint32_t index = ffStrbufFirstIndexC(&device->name, '\\'); if (index != device->name.length) ffStrbufAppendNS(&device->type, index, device->name.chars); // SCSI - ffStrbufSubstrAfterFirstS(&device->name, "&Prod_"); ffStrbufSubstrBeforeLastC(&device->name, '\\'); + ffStrbufSubstrAfterFirstS(&device->name, "&Ven_"); + ffStrbufRemoveS(&device->name, "&Prod"); ffStrbufReplaceAllC(&device->name, '_', ' '); } else From 1f23e9395103533144092c376a93c298f1a2b154 Mon Sep 17 00:00:00 2001 From: Jami Kettunen Date: Fri, 6 Oct 2023 02:09:51 +0300 Subject: [PATCH 35/74] Logo: add Chimera Linux Ref: https://github.com/chimera-linux/cports/blob/master/contrib/neofetch/patches/chimera.patch --- CHANGELOG.md | 3 +++ README.md | 2 +- src/logo/ascii/ChimeraLinux.txt | 18 ++++++++++++++++++ src/logo/builtin.c | 13 +++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/logo/ascii/ChimeraLinux.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index a363ec15db..62f6bc7909 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ Bugfixes: * Improve support of `--help *-format` and several bugs are found and fixed * Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS) +Logo: +* Add Chimera Linux + # 2.1.0 This release introduces a new output format: JSON result diff --git a/README.md b/README.md index 3148465d55..64307ce8f9 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsa ``` -AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin +AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, Chimera Linux, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin ``` Run `fastfetch --print-logos` to print them diff --git a/src/logo/ascii/ChimeraLinux.txt b/src/logo/ascii/ChimeraLinux.txt new file mode 100644 index 0000000000..c66b6db795 --- /dev/null +++ b/src/logo/ascii/ChimeraLinux.txt @@ -0,0 +1,18 @@ +${c3}ddddddddddddddc ${c1},cc: +${c3}ddddddddddddddc ${c1},cc: +${c3}ddddddddddddddd ${c1},cc: +${c3}ddddddddddddl:' ${c1},cc: +${c3}dddddddddl' ${c1}..;cc: +${c3}dddddddo. ${c1},:cccccc: +${c3}ddddddl ${c1},ccc:''''' +${c3}dddddo. ${c1};ccc. ............ + .ccc. cccccccccccc +${c2}...... ${c1}.ccc. .ccc''''''''' +${c2}OOOOOk. ${c1};ccc. .ccc; ...... +${c2}OOOOOOd ${c1}'ccc:,....,:ccc' ${c4}coooooo +${c2}OOOOOOOx. ${c1}':cccccccc:' ${c4}.looooooo +${c2}OOOOOOOOOd, ${c1}`'''` ${c4}.coooooooo +${c2}OOOOOOOOOOOOdc,. ${c4}..,coooooooooooo +${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo +${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo +${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 2063635713..a9c05200b5 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -826,6 +826,19 @@ static const FFlogo C[] = { .colorKeys = FF_COLOR_FG_GREEN, .colorTitle = FF_COLOR_FG_WHITE, }, + // Chimera Linux + { + .names = {"Chimera Linux"}, + .lines = FASTFETCH_DATATEXT_LOGO_CHIMERALINUX, + .colors = { + FF_COLOR_FG_RED, + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_BLUE, + FF_COLOR_FG_RED, + }, + .colorKeys = FF_COLOR_FG_MAGENTA, + .colorTitle = FF_COLOR_FG_RED, + }, // ChonkySealOS { .names = {"ChonkySealOS"}, From dc50e24a2904b286dcb9eeaf3068a0f96c7f2a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 21:02:31 +0800 Subject: [PATCH 36/74] Doc: update changelog and readme --- CHANGELOG.md | 1 + README.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f6bc7909..a698d4b202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Features: * Support opkg (Packages, Linux) * Support GNOME Console terminal version and font detection (Terminal, Linux) * Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU) +* New module to detect physical disk I/O usage (DiskIO) Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) diff --git a/README.md b/README.md index 64307ce8f9..34d534559e 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ Run `fastfetch --print-logos` to print them ##### Package managers ``` -apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps +apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, opkg, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps ``` ##### WM themes @@ -137,7 +137,7 @@ Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4 ##### Terminal fonts ``` -Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake +Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Console, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake ``` ## Building From 2e60f34cd8767a85f8515c301acc88d70acc85c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 21:02:48 +0800 Subject: [PATCH 37/74] DiskIO: add to `presets/all` --- presets/all | 2 +- presets/all.jsonc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/presets/all b/presets/all index b0ed3cab52..20442e13fe 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:Version:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:DiskIO:Version:Break:Colors diff --git a/presets/all.jsonc b/presets/all.jsonc index f8d4cc82ed..f26925af69 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -52,6 +52,7 @@ "gamepad", "weather", "netio", + "diskio", "version", "break", "colors" From fa46dce0e1ffb355a36cd3f74c0308180f02650d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Oct 2023 21:03:10 +0800 Subject: [PATCH 38/74] CMake: detect uclibc and musl version --- CMakeLists.txt | 9 +++++++++ src/detection/libc/libc_linux.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b2b551463..c23bd15e21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -663,6 +663,15 @@ if(yyjson_FOUND) target_link_libraries(libfastfetch PRIVATE yyjson) endif() +if(LINUX AND EXISTS "/lib/ld-musl-x86_64.so.1") + execute_process(COMMAND "/lib/ld-musl-x86_64.so.1" + ERROR_VARIABLE LD_MUSL_VERSION) + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LD_MUSL_VERSION "${LD_MUSL_VERSION}") + if(NOT LD_MUSL_VERSION STREQUAL "") + target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${LD_MUSL_VERSION}") + endif() +endif() + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1) if(WIN32) target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1) diff --git a/src/detection/libc/libc_linux.c b/src/detection/libc/libc_linux.c index 399a678705..19e8e83282 100644 --- a/src/detection/libc/libc_linux.c +++ b/src/detection/libc/libc_linux.c @@ -7,12 +7,19 @@ const char* ffDetectLibc(FFLibcResult* result) { -#ifdef __GNU_LIBRARY__ +#ifdef __UCLIBC__ + result->name = "uClibc"; + result->version = FF_STR(__UCLIBC_MAJOR__) "." FF_STR(__UCLIBC_MINOR__) "." FF_STR(__UCLIBC_SUBLEVEL__); +#elif defined(__GNU_LIBRARY__) result->name = "glibc"; result->version = FF_STR(__GLIBC__) "." FF_STR(__GLIBC_MINOR__); #else result->name = "musl"; - result->version = NULL; + #ifdef FF_MUSL_VERSION + result->version = FF_MUSL_VERSION; + #else + result->version = NULL; + #endif #endif return NULL; From 685676bd0f4dfba21d57ea1ce6022944e4c15400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 09:05:11 +0800 Subject: [PATCH 39/74] CMake: don't hardcode system arch --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c23bd15e21..73e234df14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -663,8 +663,8 @@ if(yyjson_FOUND) target_link_libraries(libfastfetch PRIVATE yyjson) endif() -if(LINUX AND EXISTS "/lib/ld-musl-x86_64.so.1") - execute_process(COMMAND "/lib/ld-musl-x86_64.so.1" +if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1") + execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1" ERROR_VARIABLE LD_MUSL_VERSION) string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LD_MUSL_VERSION "${LD_MUSL_VERSION}") if(NOT LD_MUSL_VERSION STREQUAL "") From 1188db9475b6eb70793b4e7950e463f1e45abd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 10:43:40 +0800 Subject: [PATCH 40/74] CMake: simplify musl version detection --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e234df14..3d672362ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -665,10 +665,9 @@ endif() if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1") execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1" - ERROR_VARIABLE LD_MUSL_VERSION) - string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LD_MUSL_VERSION "${LD_MUSL_VERSION}") - if(NOT LD_MUSL_VERSION STREQUAL "") - target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${LD_MUSL_VERSION}") + ERROR_VARIABLE LD_MUSL_RESULT) + if("${LD_MUSL_RESULT}" MATCHES "Version ([0-9]+\\.[0-9]+\\.[0-9]+)") + target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${CMAKE_MATCH_1}") endif() endif() From 430da1578db93cda9a1fead53137a86c855a968b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 10:43:58 +0800 Subject: [PATCH 41/74] Libc (macOS): detect `libSystem` version --- CMakeLists.txt | 9 ++++++++- src/detection/libc/libc_apple.c | 13 +++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/detection/libc/libc_apple.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d672362ac..94cbd5ae5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -546,7 +546,7 @@ elseif(APPLE) src/detection/host/host_apple.c src/detection/lm/lm_nosupport.c src/detection/icons/icons_nosupport.c - src/detection/libc/libc_nosupport.c + src/detection/libc/libc_apple.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m @@ -670,6 +670,13 @@ if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1") target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${CMAKE_MATCH_1}") endif() endif() +if(APPLE AND EXISTS "/usr/bin/otool") + execute_process(COMMAND /usr/bin/otool -L /usr/bin/otool + OUTPUT_VARIABLE OTOOL_OTOOL_RESULT) + if("${OTOOL_OTOOL_RESULT}" MATCHES "libSystem\\.B\\.dylib \\(.*current version ([0-9]+\\.[0-9]+\\.[0-9]+)\\)") + target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}") + endif() +endif() target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1) if(WIN32) diff --git a/src/detection/libc/libc_apple.c b/src/detection/libc/libc_apple.c new file mode 100644 index 0000000000..dbaa20d91d --- /dev/null +++ b/src/detection/libc/libc_apple.c @@ -0,0 +1,13 @@ +#include "libc.h" + +const char* ffDetectLibc(FFLibcResult* result) +{ + result->name = "libSystem"; + +#ifdef FF_LIBSYSTEM_VERSION + result->version = FF_LIBSYSTEM_VERSION; +#else + result->version = NULL; +#endif + return NULL; +} From 2d2e0ddc6d83eee97ca7dec38cbf24ddbc724e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 13:28:30 +0800 Subject: [PATCH 42/74] Libc (FreeBSD): detect FBSD version --- CMakeLists.txt | 9 ++++++++- src/detection/libc/libc_bsd.c | 13 +++++++++++++ src/detection/libc/libc_nosupport.c | 9 --------- 3 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 src/detection/libc/libc_bsd.c delete mode 100644 src/detection/libc/libc_nosupport.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 94cbd5ae5c..6be4f1535b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,7 +495,7 @@ elseif(BSD) src/detection/host/host_bsd.c src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c - src/detection/libc/libc_nosupport.c + src/detection/libc/libc_bsd.c src/detection/localip/localip_linux.c src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c @@ -677,6 +677,13 @@ if(APPLE AND EXISTS "/usr/bin/otool") target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}") endif() endif() +if(BSD AND EXISTS "/usr/local/bin/objdump") + execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[^ )]*' -o | sort -Vru | head -1" + OUTPUT_VARIABLE OBJDUMP_T_RESULT) + if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)") + target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}") + endif() +endif() target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1) if(WIN32) diff --git a/src/detection/libc/libc_bsd.c b/src/detection/libc/libc_bsd.c new file mode 100644 index 0000000000..0b6ee49439 --- /dev/null +++ b/src/detection/libc/libc_bsd.c @@ -0,0 +1,13 @@ +#include "libc.h" + +const char* ffDetectLibc(FFLibcResult* result) +{ + result->name = "FBSD"; + +#ifdef FF_FBSD_VERSION + result->version = FF_FBSD_VERSION; +#else + result->version = NULL; +#endif + return NULL; +} diff --git a/src/detection/libc/libc_nosupport.c b/src/detection/libc/libc_nosupport.c deleted file mode 100644 index 0c6a968a3d..0000000000 --- a/src/detection/libc/libc_nosupport.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "libc.h" - -#define FF_STR_INDIR(x) #x -#define FF_STR(x) FF_STR_INDIR(x) - -const char* ffDetectLibc(FF_MAYBE_UNUSED FFLibcResult* result) -{ - return "Not supported on this platform"; -} From b76d6e9faa43c1a24818bd5f3fdb2a960d99d3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 14:16:12 +0800 Subject: [PATCH 43/74] DiskIO (FreeBSD): add support --- CMakeLists.txt | 1 + src/detection/diskio/diskio_bsd.c | 48 +++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6be4f1535b..5b4037c199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -890,6 +890,7 @@ elseif(BSD) target_link_libraries(libfastfetch PRIVATE "m" PRIVATE "usbhid" + PRIVATE "devstat" ) elseif(ANDROID) CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC) diff --git a/src/detection/diskio/diskio_bsd.c b/src/detection/diskio/diskio_bsd.c index b86f3a0a3d..f73f48f2c0 100644 --- a/src/detection/diskio/diskio_bsd.c +++ b/src/detection/diskio/diskio_bsd.c @@ -1,11 +1,49 @@ #include "diskio.h" -#include "common/io/io.h" -#include "util/stringUtils.h" -#include -#include +#include +#include const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) { - return "Not supported on this platform"; + if (devstat_checkversion(NULL) < 0) + return "devstat_checkversion() failed"; + + struct statinfo stats = { + .dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)), + }; + if (devstat_getdevs(NULL, &stats) < 0) + return "devstat_getdevs() failed"; + + for (int i = 0; i < stats.dinfo->numdevs; i++) + { + struct devstat* current = &stats.dinfo->devices[i]; + + char deviceName[128]; + snprintf(deviceName, sizeof(deviceName), "%s%d", current->device_name, current->unit_number); + + if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + ffStrbufInitS(&device->name, deviceName); + ffStrbufInitF(&device->devPath, "/dev/%s", deviceName); + + ffStrbufInit(&device->type); + switch (current->device_type & DEVSTAT_TYPE_IF_MASK) + { + case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->type, "SCSI"); break; + case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->type, "IDE"); break; + case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->type, "OTHER"); break; + } + device->bytesRead = current->bytes[DEVSTAT_READ]; + device->readCount = current->operations[DEVSTAT_READ]; + device->bytesWritten = current->bytes[DEVSTAT_WRITE]; + device->writeCount = current->operations[DEVSTAT_WRITE]; + } + + if (stats.dinfo->mem_ptr) + free(stats.dinfo->mem_ptr); + free(stats.dinfo); + + return NULL; } From 5ccd196ae4aeeb5f568c8cf34657230a9912cf8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 14:24:29 +0800 Subject: [PATCH 44/74] DiskIO: print `devPath` --- src/modules/diskio/diskio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 07acbc7b18..450dcf9751 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -80,6 +80,7 @@ void ffPrintDiskIO(FFDiskIOOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->type}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesRead}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesWritten}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->readCount}, @@ -167,6 +168,7 @@ void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); yyjson_mut_obj_add_strbuf(doc, obj, "type", &counter->type); + yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &counter->devPath); yyjson_mut_obj_add_uint(doc, obj, "bytesRead", counter->bytesRead); yyjson_mut_obj_add_uint(doc, obj, "bytesWritten", counter->bytesWritten); yyjson_mut_obj_add_uint(doc, obj, "readCount", counter->readCount); @@ -188,6 +190,7 @@ void ffPrintDiskIOHelpFormat(void) "Size of data written per second (formatted)", "Device name", "Device type", + "Device raw file path", "Size of data read per second (in bytes)", "Size of data written per second (in bytes)", "Number of reads", From 44b417decad7266ff99b1fe0dcee75901508c4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 14:26:51 +0800 Subject: [PATCH 45/74] DiskIO (FreeBSD): skip `/dev/pass*` --- src/detection/diskio/diskio_bsd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/diskio/diskio_bsd.c b/src/detection/diskio/diskio_bsd.c index f73f48f2c0..e941a6a8d0 100644 --- a/src/detection/diskio/diskio_bsd.c +++ b/src/detection/diskio/diskio_bsd.c @@ -17,6 +17,8 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) for (int i = 0; i < stats.dinfo->numdevs; i++) { struct devstat* current = &stats.dinfo->devices[i]; + if (current->device_type & DEVSTAT_TYPE_PASS) + continue; char deviceName[128]; snprintf(deviceName, sizeof(deviceName), "%s%d", current->device_name, current->unit_number); From a0343d6bf7b82c32b2e447b3f5057872db8dae3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 14:56:28 +0800 Subject: [PATCH 46/74] CI: run `--format json` --- .github/workflows/ci.yml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6832bdcfb..7d8de61d54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,10 +44,13 @@ jobs: run: ctest - name: run fastfetch - run: ./fastfetch --stat --show-errors --no-buffer --load-config presets/all + run: time ./fastfetch -c presets/ci + + - name: run fastfetch --format json + run: time ./fastfetch -c presets/ci --format json - name: run flashfetch - run: ./flashfetch + run: time ./flashfetch linux: name: Linux @@ -84,6 +87,9 @@ jobs: - name: run fastfetch run: time ./fastfetch -c presets/ci + - name: run fastfetch --format json + run: time ./fastfetch -c presets/ci --format json + - name: run flashfetch run: time ./flashfetch @@ -136,6 +142,9 @@ jobs: - name: run fastfetch run: time ./fastfetch -c presets/ci + - name: run fastfetch --format json + run: time ./fastfetch -c presets/ci --format json + - name: run flashfetch run: time ./flashfetch @@ -165,12 +174,13 @@ jobs: uses: vmactions/freebsd-vm@v0 with: prepare: | - pkg install -y cmake git pkgconf pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio + pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio run: | cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . cmake --build . --target package ./fastfetch --list-features time ./fastfetch -c presets/ci + time ./fastfetch -c presets/ci --format json time ./flashfetch ldd fastfetch ctest @@ -227,6 +237,9 @@ jobs: - name: run fastfetch run: time ./fastfetch -c presets/ci + - name: run fastfetch --format json + run: time ./fastfetch -c presets/ci --format json + - name: run flashfetch run: time ./flashfetch @@ -291,6 +304,9 @@ jobs: - name: run fastfetch run: time ./fastfetch -c presets/ci + - name: run fastfetch --format json + run: time ./fastfetch -c presets/ci --format json + - name: run flashfetch run: time ./flashfetch From 4194e5691239be6f9b7f659329c17cd1ce137dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 15:39:34 +0800 Subject: [PATCH 47/74] DiskIO (Windows): better name detection for Github Action --- src/detection/diskio/diskio_windows.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index 452f90bccb..e45599cd66 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -37,11 +37,15 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) // SCSI\Disk&Ven_NVMe&Prod_WDC_PC_SN810_SDC\5&19cebb7&0&000000 uint32_t index = ffStrbufFirstIndexC(&device->name, '\\'); if (index != device->name.length) + { ffStrbufAppendNS(&device->type, index, device->name.chars); // SCSI + ffStrbufSubstrAfter(&device->name, index + 1); + } ffStrbufSubstrBeforeLastC(&device->name, '\\'); ffStrbufSubstrAfterFirstS(&device->name, "&Ven_"); ffStrbufRemoveS(&device->name, "&Prod"); ffStrbufReplaceAllC(&device->name, '_', ' '); + ffStrbufTrim(&device->name, ' '); } else ffStrbufSetWS(&device->name, szDevice); From 8fa6aee571539f9c0c38c5a9528488e02dee765d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 16:23:42 +0800 Subject: [PATCH 48/74] Disk: move `physicalType` to module `DiskIO` Physical type applies to physical disks, not partitions --- src/detection/disk/disk.h | 8 ----- src/detection/disk/disk_bsd.c | 50 -------------------------- src/detection/disk/disk_linux.c | 22 +++--------- src/detection/disk/disk_windows.c | 28 --------------- src/detection/diskio/diskio.h | 10 +++++- src/detection/diskio/diskio_apple.c | 20 +++++++++-- src/detection/diskio/diskio_bsd.c | 10 +++--- src/detection/diskio/diskio_linux.c | 19 ++++++---- src/detection/diskio/diskio_windows.c | 25 +++++++++++-- src/modules/disk/disk.c | 27 -------------- src/modules/diskio/diskio.c | 52 ++++++++++++++++++++------- 11 files changed, 112 insertions(+), 159 deletions(-) diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index 06611f85c2..3ccab52c4f 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -5,13 +5,6 @@ #include "fastfetch.h" -typedef enum FFDiskPhysicalType -{ - FF_DISK_PHYSICAL_TYPE_UNKNOWN, - FF_DISK_PHYSICAL_TYPE_HDD, - FF_DISK_PHYSICAL_TYPE_SSD, -} FFDiskPhysicalType; - typedef struct FFDisk { FFstrbuf mountFrom; @@ -19,7 +12,6 @@ typedef struct FFDisk FFstrbuf filesystem; FFstrbuf name; FFDiskVolumeType type; - FFDiskPhysicalType physicalType; uint64_t bytesUsed; uint64_t bytesFree; diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index a89f9bd6d8..f885563d12 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -25,8 +25,6 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk) #include #include -#include -#include struct VolAttrBuf { uint32_t length; @@ -34,51 +32,6 @@ struct VolAttrBuf { char volNameSpace[MAXPATHLEN]; } __attribute__((aligned(4), packed)); -void detectDiskType(FFDisk* disk) // Not thread safe -{ - if (!ffStrbufStartsWithS(&disk->mountFrom, "/dev/disk")) return; - - static uint8_t cache[100]; // disk_id => physical_type + 1 - const char* numStart = disk->mountFrom.chars + strlen("/dev/disk"); - char* numEnd = NULL; - unsigned long diskId = strtoul(numStart, &numEnd, 10); - if (numEnd == numStart || diskId >= 100) - return; - - if (cache[diskId]) - { - disk->physicalType = cache[diskId] - 1; - return; - } - - io_iterator_t iterator; - char temp = *numEnd; *numEnd = '\0'; // Check for root disk directly - *numEnd = temp; - if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, disk->mountFrom.chars + strlen("/dev/")), &iterator) == kIOReturnSuccess) - { - for (io_registry_entry_t registryEntry = IOIteratorNext(iterator); registryEntry; IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, ®istryEntry)) - { - FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = (CFDictionaryRef) IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions); - if (!deviceCharacteristics) - continue; - - CFStringRef diskType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); - if (diskType) - { - if (CFStringCompare(diskType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0) - disk->physicalType = FF_DISK_PHYSICAL_TYPE_SSD; - else if (CFStringCompare(diskType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0) - disk->physicalType = FF_DISK_PHYSICAL_TYPE_HDD; - } - break; - } - - IOObjectRelease(iterator); - } - - cache[diskId] = (uint8_t) (disk->physicalType + 1); -} - void detectFsInfo(struct statfs* fs, FFDisk* disk) { if(fs->f_flags & MNT_DONTBROWSE) @@ -94,8 +47,6 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk) .volattr = ATTR_VOL_INFO | ATTR_VOL_NAME, }, &attrBuf, sizeof(attrBuf), 0) == 0) ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace); - - detectDiskType(disk); } #endif @@ -122,7 +73,6 @@ const char* ffDetectDisksImpl(FFlist* disks) #endif FFDisk* disk = ffListAdd(disks); - disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; disk->bytesTotal = fs->f_blocks * fs->f_bsize; disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize; diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index bc53eb7834..a04571d734 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -195,7 +195,7 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) return false; } -static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk) +static bool isRemovable(FFDisk* currentDisk) { // https://stackoverflow.com/a/73302025 // Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does. @@ -218,20 +218,10 @@ static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk) if (!ffStrStartsWith(partitionName, entry->d_name)) continue; - ffStrbufAppendS(&basePath, entry->d_name); - index = basePath.length; - // /sys/block/sdx/queue/rotational - ffStrbufAppendS(&basePath, "/queue/rotational"); - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - if (ffReadFileBuffer(basePath.chars, &buffer)) - currentDisk->physicalType = ffStrbufEqualS(&buffer, "1") ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD; - else - currentDisk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; - ffStrbufSubstrBefore(&basePath, index); - // /sys/block/sdx/removable + ffStrbufAppendS(&basePath, entry->d_name); ffStrbufAppendS(&basePath, "/removable"); - + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1"); } @@ -240,10 +230,9 @@ static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk) static void detectType(const FFlist* disks, FFDisk* currentDisk) { - bool isRemovable = detectPhysicalTypeAndReturnRemovable(currentDisk); - if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return; - if(isRemovable) + + if(isRemovable(currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; @@ -289,7 +278,6 @@ const char* ffDetectDisksImpl(FFlist* disks) //We have a valid device, add it to the list FFDisk* disk = ffListAdd(disks); disk->type = FF_DISK_VOLUME_TYPE_NONE; - disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; //detect mountFrom ffStrbufInitS(&disk->mountFrom, device->mnt_fsname); diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index d67338ff16..24a1651bab 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -28,34 +28,6 @@ const char* ffDetectDisksImpl(FFlist* disks) ffStrbufInitWS(&disk->mountpoint, mountpoint); wchar_t volumeName[64]; - - disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; - if(mountpoint[1] == ':') - { - memcpy(volumeName, L"\\\\.\\ :", sizeof(L"\\\\.\\ :")); - volumeName[4] = mountpoint[0]; - FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(volumeName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (handle != INVALID_HANDLE_VALUE) - { - DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; - DWORD retSize = 0; - if(DeviceIoControl( - handle, - IOCTL_STORAGE_QUERY_PROPERTY, - &(STORAGE_PROPERTY_QUERY) { - .PropertyId = StorageDeviceSeekPenaltyProperty, - .QueryType = PropertyStandardQuery, - }, - sizeof(STORAGE_PROPERTY_QUERY), - &dspd, - sizeof(dspd), - &retSize, - NULL - ) && retSize == sizeof(dspd)) - disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD; - } - } - if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName))) ffStrbufInitWS(&disk->mountFrom, volumeName); else diff --git a/src/detection/diskio/diskio.h b/src/detection/diskio/diskio.h index d0d8d0b4e6..7bde1cc325 100644 --- a/src/detection/diskio/diskio.h +++ b/src/detection/diskio/diskio.h @@ -2,10 +2,18 @@ #include "fastfetch.h" +typedef enum FFDiskIOPhysicalType +{ + FF_DISKIO_PHYSICAL_TYPE_UNKNOWN, + FF_DISKIO_PHYSICAL_TYPE_HDD, + FF_DISKIO_PHYSICAL_TYPE_SSD, +} FFDiskIOPhysicalType; + typedef struct FFDiskIOResult { FFstrbuf name; - FFstrbuf type; + FFstrbuf interconnect; + FFDiskIOPhysicalType type; FFstrbuf devPath; uint64_t bytesRead; uint64_t readCount; diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c index 89f8ed3cfe..cdaadfa579 100644 --- a/src/detection/diskio/diskio_apple.c +++ b/src/detection/diskio/diskio_apple.c @@ -5,6 +5,7 @@ #include #include #include +#include #include static inline void wrapIoObjectRelease(io_service_t* service) @@ -47,7 +48,8 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); ffStrbufInitS(&device->name, deviceName); ffStrbufInit(&device->devPath); - ffStrbufInit(&device->type); + device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; + ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey), (int64_t*) &device->bytesRead); ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey), (int64_t*) &device->bytesWritten); ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey), (int64_t*) &device->readCount); @@ -60,12 +62,26 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) ffStrbufPrependS(&device->devPath, "/dev/"); } + ffStrbufInit(&device->interconnect); FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0; if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS) { FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions); if (protocolCharacteristics) - ffCfDictGetString(protocolCharacteristics, CFSTR("Physical Interconnect"), &device->type); + ffCfDictGetString(protocolCharacteristics, CFSTR("Physical Interconnect"), &device->interconnect); + + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions); + if (deviceCharacteristics) + { + CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); + if (mediumType) + { + if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0) + device->type = FF_DISKIO_PHYSICAL_TYPE_SSD; + else if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0) + device->type = FF_DISKIO_PHYSICAL_TYPE_HDD; + } + } } } diff --git a/src/detection/diskio/diskio_bsd.c b/src/detection/diskio/diskio_bsd.c index e941a6a8d0..62b8aa2520 100644 --- a/src/detection/diskio/diskio_bsd.c +++ b/src/detection/diskio/diskio_bsd.c @@ -29,13 +29,13 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); ffStrbufInitS(&device->name, deviceName); ffStrbufInitF(&device->devPath, "/dev/%s", deviceName); - - ffStrbufInit(&device->type); + device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; + ffStrbufInit(&device->interconnect); switch (current->device_type & DEVSTAT_TYPE_IF_MASK) { - case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->type, "SCSI"); break; - case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->type, "IDE"); break; - case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->type, "OTHER"); break; + case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break; + case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break; + case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break; } device->bytesRead = current->bytes[DEVSTAT_READ]; device->readCount = current->operations[DEVSTAT_READ]; diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c index fdd73c8f79..9ac39915d1 100644 --- a/src/detection/diskio/diskio_linux.c +++ b/src/detection/diskio/diskio_linux.c @@ -53,10 +53,10 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) } if (flag) continue; - char pathSysBlockStat[PATH_MAX]; - snprintf(pathSysBlockStat, PATH_MAX, "/sys/block/%s/stat", devName); + char pathSysBlock[PATH_MAX]; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/stat", devName); - FF_AUTO_CLOSE_FILE FILE* sysBlockStat = fopen(pathSysBlockStat, "r"); + FF_AUTO_CLOSE_FILE FILE* sysBlockStat = fopen(pathSysBlock, "r"); if (!sysBlockStat) continue; // I/Os merges sectors ticks ... @@ -73,19 +73,19 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) ffStrbufInitNS(&device->name, (uint32_t) (slash2 - slash - 1), slash + 1); else ffStrbufInitS(&device->name, slash + 1); - ffStrbufInitNS(&device->type, (uint32_t) (slash - entry->d_name), entry->d_name); + ffStrbufInitNS(&device->interconnect, (uint32_t) (slash - entry->d_name), entry->d_name); } else { ffStrbufInitS(&device->name, entry->d_name); - ffStrbufInit(&device->type); + ffStrbufInit(&device->interconnect); } ffStrbufReplaceAllC(&device->name, '_', ' '); if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { ffStrbufDestroy(&device->name); - ffStrbufDestroy(&device->type); + ffStrbufDestroy(&device->interconnect); result->length--; continue; } @@ -95,6 +95,13 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) device->bytesWritten = sectorWritten * 512; device->readCount = nRead; device->writeCount = nWritten; + + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffReadFileBuffer(pathSysBlock, &buffer)) + device->type = ffStrbufEqualS(&buffer, "1") ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD; + else + device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; } return NULL; diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index e45599cd66..804327cf93 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -31,14 +31,14 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) { FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); ffStrbufInit(&device->name); - ffStrbufInit(&device->type); + ffStrbufInit(&device->interconnect); if (ffRegReadStrbuf(hKey, pNum, &device->name, NULL)) { // SCSI\Disk&Ven_NVMe&Prod_WDC_PC_SN810_SDC\5&19cebb7&0&000000 uint32_t index = ffStrbufFirstIndexC(&device->name, '\\'); if (index != device->name.length) { - ffStrbufAppendNS(&device->type, index, device->name.chars); // SCSI + ffStrbufAppendNS(&device->interconnect, index, device->name.chars); // SCSI ffStrbufSubstrAfter(&device->name, index + 1); } ffStrbufSubstrBeforeLastC(&device->name, '\\'); @@ -53,7 +53,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { ffStrbufDestroy(&device->name); - ffStrbufDestroy(&device->type); + ffStrbufDestroy(&device->interconnect); result->length--; continue; } @@ -63,6 +63,25 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) device->readCount = (uint64_t) diskPerformance.ReadCount; device->bytesWritten = (uint64_t) diskPerformance.BytesWritten.QuadPart; device->writeCount = (uint64_t) diskPerformance.WriteCount; + + DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; + DWORD retSize = 0; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceSeekPenaltyProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &dspd, + sizeof(dspd), + &retSize, + NULL + ) && retSize == sizeof(dspd)) + device->type = dspd.IncursSeekPenalty ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD; + else + device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; } } diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index f075ac123e..1e789d433e 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -112,19 +112,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT); bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT); bool isReadOnly = !!(disk->type & FF_DISK_VOLUME_TYPE_READONLY_BIT); - const char* physicalType; - switch(disk->physicalType) - { - case FF_DISK_PHYSICAL_TYPE_HDD: - physicalType = "HDD"; - break; - case FF_DISK_PHYSICAL_TYPE_SSD: - physicalType = "SSD"; - break; - default: - physicalType = "Unknown"; - break; - } ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, @@ -137,7 +124,6 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) {FF_FORMAT_ARG_TYPE_STRBUF, &disk->filesystem}, {FF_FORMAT_ARG_TYPE_STRBUF, &disk->name}, {FF_FORMAT_ARG_TYPE_BOOL, &isReadOnly}, - {FF_FORMAT_ARG_TYPE_STRING, physicalType} }); } } @@ -429,19 +415,6 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ yyjson_mut_arr_add_str(doc, typeArr, "Hidden"); if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT) yyjson_mut_arr_add_str(doc, typeArr, "Read-only"); - - switch(item->physicalType) - { - case FF_DISK_PHYSICAL_TYPE_HDD: - yyjson_mut_obj_add_str(doc, obj, "physicalType", "HDD"); - break; - case FF_DISK_PHYSICAL_TYPE_SSD: - yyjson_mut_obj_add_str(doc, obj, "physicalType", "SSD"); - break; - default: - yyjson_mut_obj_add_null(doc, obj, "physicalType"); - break; - } } FF_LIST_FOR_EACH(FFDisk, item, disks) diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 450dcf9751..fee2dfcb9a 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -28,7 +28,6 @@ static void formatKey(const FFDiskIOOptions* options, FFDiskIOResult* dev, uint3 ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_UINT, &index}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, - {FF_FORMAT_ARG_TYPE_STRBUF, &dev->type}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, }); } @@ -75,11 +74,26 @@ void ffPrintDiskIO(FFDiskIOOptions* options) ffParseSize(dev->bytesWritten, &buffer2); ffStrbufAppendS(&buffer2, "/s"); + const char* physicalType; + switch(dev->type) + { + case FF_DISKIO_PHYSICAL_TYPE_HDD: + physicalType = "HDD"; + break; + case FF_DISKIO_PHYSICAL_TYPE_SSD: + physicalType = "SSD"; + break; + default: + physicalType = "Unknown"; + break; + } + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISKIO_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, - {FF_FORMAT_ARG_TYPE_STRBUF, &dev->type}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->interconnect}, + {FF_FORMAT_ARG_TYPE_STRING, physicalType}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesRead}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesWritten}, @@ -93,7 +107,7 @@ void ffPrintDiskIO(FFDiskIOOptions* options) FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) { ffStrbufDestroy(&dev->name); - ffStrbufDestroy(&dev->type); + ffStrbufDestroy(&dev->interconnect); ffStrbufDestroy(&dev->devPath); } } @@ -163,22 +177,36 @@ void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_ } yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); - FF_LIST_FOR_EACH(FFDiskIOResult, counter, result) + FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); - yyjson_mut_obj_add_strbuf(doc, obj, "type", &counter->type); - yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &counter->devPath); - yyjson_mut_obj_add_uint(doc, obj, "bytesRead", counter->bytesRead); - yyjson_mut_obj_add_uint(doc, obj, "bytesWritten", counter->bytesWritten); - yyjson_mut_obj_add_uint(doc, obj, "readCount", counter->readCount); - yyjson_mut_obj_add_uint(doc, obj, "writeCount", counter->writeCount); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name); + yyjson_mut_obj_add_strbuf(doc, obj, "interconnect", &dev->interconnect); + yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &dev->devPath); + + switch(dev->type) + { + case FF_DISKIO_PHYSICAL_TYPE_HDD: + yyjson_mut_obj_add_str(doc, obj, "type", "HDD"); + break; + case FF_DISKIO_PHYSICAL_TYPE_SSD: + yyjson_mut_obj_add_str(doc, obj, "type", "SSD"); + break; + default: + yyjson_mut_obj_add_null(doc, obj, "type"); + break; + } + + yyjson_mut_obj_add_uint(doc, obj, "bytesRead", dev->bytesRead); + yyjson_mut_obj_add_uint(doc, obj, "bytesWritten", dev->bytesWritten); + yyjson_mut_obj_add_uint(doc, obj, "readCount", dev->readCount); + yyjson_mut_obj_add_uint(doc, obj, "writeCount", dev->writeCount); } FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) { ffStrbufDestroy(&dev->name); - ffStrbufDestroy(&dev->type); + ffStrbufDestroy(&dev->interconnect); ffStrbufDestroy(&dev->devPath); } } From d16bdb30b9f7811c3be3fe7b5843e5fd1d3e84de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 16:40:47 +0800 Subject: [PATCH 49/74] DiskIO: update formatting help messages; update json keys --- src/modules/diskio/diskio.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index fee2dfcb9a..cb7c981dc2 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -6,7 +6,7 @@ #include "util/stringUtils.h" #define FF_DISKIO_DISPLAY_NAME "Disk IO" -#define FF_DISKIO_NUM_FORMAT_ARGS 7 +#define FF_DISKIO_NUM_FORMAT_ARGS 10 static int sortDevices(const FFDiskIOResult* left, const FFDiskIOResult* right) { @@ -181,19 +181,19 @@ void ffGenerateDiskIOJson(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_ { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name); - yyjson_mut_obj_add_strbuf(doc, obj, "interconnect", &dev->interconnect); + yyjson_mut_obj_add_strbuf(doc, obj, "interconnectType", &dev->interconnect); yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &dev->devPath); switch(dev->type) { case FF_DISKIO_PHYSICAL_TYPE_HDD: - yyjson_mut_obj_add_str(doc, obj, "type", "HDD"); + yyjson_mut_obj_add_str(doc, obj, "physicalType", "HDD"); break; case FF_DISKIO_PHYSICAL_TYPE_SSD: - yyjson_mut_obj_add_str(doc, obj, "type", "SSD"); + yyjson_mut_obj_add_str(doc, obj, "physicalType", "SSD"); break; default: - yyjson_mut_obj_add_null(doc, obj, "type"); + yyjson_mut_obj_add_null(doc, obj, "physicalType"); break; } @@ -217,7 +217,8 @@ void ffPrintDiskIOHelpFormat(void) "Size of data read per second (formatted)", "Size of data written per second (formatted)", "Device name", - "Device type", + "Device interconnect type", + "Device physical type (SSD / HDD)", "Device raw file path", "Size of data read per second (in bytes)", "Size of data written per second (in bytes)", From ccbb2524661242455b4f2ba4813a6eda230bd4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 19:24:25 +0800 Subject: [PATCH 50/74] DiskIO: update doc and json schema --- doc/json_schema.json | 26 ++++++++++++++++++++++++++ src/data/help.txt | 5 +++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 910192a9ba..05b16dbbdf 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -545,6 +545,7 @@ "datetime", "display", "disk", + "diskio", "de", "font", "gamepad", @@ -932,6 +933,31 @@ }, "additionalProperties": false }, + { + "title": "Physical disk throughput (usage)", + "properties": { + "type": { + "const": "diskio" + }, + "namePrefix": { + "title": "Show disks with given name prefix only", + "type": "string" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "GPU", "properties": { diff --git a/src/data/help.txt b/src/data/help.txt index 440ff9aa41..154dd7a0e5 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -132,6 +132,7 @@ Module specific options: --disk-show-readonly : Set if read only volumes should be printed. Default is false --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false --disk-use-available : Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false + --diskio-name-prefix : Show disks with given name prefix only. Default is empty --bluetooth-show-disconnected: : Set if disconnected bluetooth devices should be printed. Default is false --display-compact-type: : Set if all displays should be printed in one line. Default is none --display-detect-name: : Set if display name should be detected and printed (if supported). Default is false @@ -151,8 +152,8 @@ Module specific options: --localip-name-prefix : Show interfaces with given interface name prefix only. Default is empty --localip-default-route-only : Show the interface that is used for default routing only. Default is false --localip-compact : Show all IPs in one line. Default is false - --netio-name-prefix : Show interfaces with given name prefix only. Default is empty - --netio-default-route-only : Show the interfac that is used for default routing only. Default is false + --netio-name-prefix : Show interfaces with given name prefix only. Default is empty + --netio-default-route-only : Show the interfac that is used for default routing only. Default is false --publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) --publicip-url: The URL of public IP detection server to be used. --weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`). From 42f6d029b04b774556beb5d9494a2b39aeb76352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Oct 2023 20:27:40 +0800 Subject: [PATCH 51/74] Doc: update JSON schema; make it more IDE friendly --- README.md | 2 +- doc/json_schema.json | 218 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 175 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 34d534559e..81cae05a0a 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,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, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, DiskIO, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme ``` ##### Builtin logos diff --git a/doc/json_schema.json b/doc/json_schema.json index 05b16dbbdf..d3e36fed83 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -596,7 +596,6 @@ ], "properties": { "type": { - "title": "Module type", "type": "string" } }, @@ -615,45 +614,159 @@ "title": "No additional properties", "properties": { "type": { - "enum": [ - "bios", - "board", - "brightness", - "chassis", - "cpuusage", - "cursor", - "datetime", - "de", - "font", - "gamepad", - "host", - "icons", - "kernel", - "lm", - "locale", - "media", - "memory", - "monitor", - "opencl", - "os", - "packages", - "player", - "poweradapter", - "processes", - "shell", - "swap", - "terminal", - "terminalfont", - "terminalsize", - "theme", - "uptime", - "users", - "version", - "vulkan", - "wallpaper", - "wm", - "wifi", - "wmtheme" + "anyOf": [ + { + "const": "bios", + "description": "Print BIOS name, version, release date, etc" + }, + { + "const": "board", + "description": "Print mather board name and other info" + }, + { + "const": "brightness", + "description": "Print brightness of your monitors" + }, + { + "const": "chassis", + "description": "Print chassis type (desktop, laptop, etc)" + }, + { + "const": "cpuusage", + "description": "Print CPU usage. Costs some time to collect data" + }, + { + "const": "cursor", + "description": "Print cursor style name" + }, + { + "const": "datetime", + "description": "Print current date and time" + }, + { + "const": "de", + "description": "Print desktop environment name" + }, + { + "const": "font", + "description": "Print system font name" + }, + { + "const": "gamepad", + "description": "List connected gamepads" + }, + { + "const": "host", + "description": "Print product name of your computer" + }, + { + "const": "icons", + "description": "Print icon style name" + }, + { + "const": "kernel", + "description": "Print system kernel version" + }, + { + "const": "lm", + "description": "Print login manager (desktop manager) name and version" + }, + { + "const": "locale", + "description": "Print system locale name" + }, + { + "const": "media", + "description": "Print playing song name" + }, + { + "const": "memory", + "description": "Print system memory usage info" + }, + { + "const": "monitor", + "description": "Print connected physical monitor information" + }, + { + "const": "opencl", + "description": "Print highest OpenCL version supported by the GPU" + }, + { + "const": "os", + "description": "Print operating system name and version" + }, + { + "const": "packages", + "description": "List installed package managers and count of installed packages" + }, + { + "const": "player", + "description": "Print music player name" + }, + { + "const": "poweradapter", + "description": "Print power adapter name and charging watts" + }, + { + "const": "processes", + "description": "Count running processes" + }, + { + "const": "shell", + "description": "Print current shell name and version" + }, + { + "const": "swap", + "description": "Print swap (paging file) space usage" + }, + { + "const": "terminal", + "description": "Print current terminal name and version" + }, + { + "const": "terminalfont", + "description": "Print font name and size used by current terminal" + }, + { + "const": "terminalsize", + "description": "Print current terminal size" + }, + { + "const": "theme", + "description": "Print current theme information" + }, + { + "const": "uptime", + "description": "Print system uptime" + }, + { + "const": "users", + "description": "List users currently logged in" + }, + { + "const": "version", + "description": "Print Fastfetch version" + }, + { + "const": "vulkan", + "description": "Print highest Vulkan version supported by the GPU" + }, + { + "const": "wallpaper", + "description": "Print image file path of current wallpaper" + }, + { + "const": "wm", + "description": "Print window manager name and version" + }, + { + "const": "wifi", + "description": "Print connected Wi-Fi info (SSID, connection and security protocol)" + }, + { + "const": "wmtheme", + "description": "Print current theme of window manager" + } ] }, "key": { @@ -675,7 +788,8 @@ "title": "Battery", "properties": { "type": { - "const": "battery" + "const": "battery", + "description": "Print battery capacity, status, etc" }, "dir": { "title": "The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only", @@ -705,6 +819,7 @@ "title": "Bluetooth", "properties": { "type": { + "description": "List bluetooth devices", "const": "bluetooth" }, "showDisconnected": { @@ -731,6 +846,7 @@ "title": "CPU", "properties": { "type": { + "description": "Print CPU name, frequency, etc", "const": "cpu" }, "temp": { @@ -764,6 +880,7 @@ "title": "Colors", "properties": { "type": { + "description": "Print some colored blocks", "const": "colors" }, "symbol": { @@ -791,6 +908,7 @@ "title": "Command", "properties": { "type": { + "description": "Running custom shell scripts", "const": "command" }, "shell": { @@ -818,9 +936,9 @@ }, { "title": "Custom", - "description": "Print a custom string, with or without key", "properties": { "type": { + "description": "Print a custom string, with or without key", "const": "custom" }, "key": { @@ -847,6 +965,7 @@ "title": "Display", "properties": { "type": { + "description": "Print resolutions, refresh rates, etc", "const": "display" }, "compactType": { @@ -882,6 +1001,7 @@ "title": "Disk", "properties": { "type": { + "description": "Print partitions, space usage, disk type, etc", "const": "disk" }, "folders": { @@ -934,9 +1054,10 @@ "additionalProperties": false }, { - "title": "Physical disk throughput (usage)", + "title": "DiskIO", "properties": { "type": { + "description": "Print physical disk I/O throughput", "const": "diskio" }, "namePrefix": { @@ -962,6 +1083,7 @@ "title": "GPU", "properties": { "type": { + "description": "Print GPU names, graphic memory size, type, etc", "const": "gpu" }, "temp": { @@ -1002,6 +1124,7 @@ "title": "Local IP", "properties": { "type": { + "description": "List local IP addresses (v4 or v6), MAC addresses, etc", "const": "localip" }, "showIpv4": { @@ -1054,9 +1177,10 @@ "additionalProperties": false }, { - "title": "Network throughput (usage)", + "title": "NetIO", "properties": { "type": { + "description": "Print network I/O throughput", "const": "netio" }, "namePrefix": { @@ -1087,6 +1211,7 @@ "title": "OpenGL", "properties": { "type": { + "description": "Print highest OpenGL version supported by the GPU", "const": "opengl" }, "library": { @@ -1118,6 +1243,7 @@ "title": "Public IP", "properties": { "type": { + "description": "Print your public IP address, etc", "const": "publicip" }, "url": { @@ -1151,6 +1277,7 @@ "title": "Separator", "properties": { "type": { + "description": "Print a separator line", "const": "separator" }, "string": { @@ -1165,6 +1292,7 @@ "title": "Sound", "properties": { "type": { + "description": "Print sound devices, volume, etc", "const": "sound" }, "soundType": { @@ -1196,6 +1324,7 @@ "title": "Title", "properties": { "type": { + "description": "Print title, which contains your user name, hostname", "const": "title" }, "fqdn": { @@ -1240,6 +1369,7 @@ "title": "Weather", "properties": { "type": { + "description": "Print weather information", "const": "weather" }, "location": { From e7df94495c624f112dc5d65129b43b82bce5e4e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 09:28:31 +0800 Subject: [PATCH 52/74] Temp (FreeBSD): improve CPU temp detection --- src/detection/cpu/cpu_bsd.c | 5 ++++- src/detection/temps/temps_bsd.c | 11 +++++++++++ src/detection/temps/temps_bsd.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 835bdd4f6a..2d6a1bd28d 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -16,7 +16,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) cpu->temperature = FF_CPU_TEMP_UNSET; if (options->temp) - ffDetectThermalTemp(&cpu->temperature); + { + if (!ffDetectCpuTemp(&cpu->temperature)) + ffDetectThermalTemp(&cpu->temperature); + } return NULL; } diff --git a/src/detection/temps/temps_bsd.c b/src/detection/temps/temps_bsd.c index 39693d65de..2355ac8bfe 100644 --- a/src/detection/temps/temps_bsd.c +++ b/src/detection/temps/temps_bsd.c @@ -1,6 +1,17 @@ #include "temps_bsd.h" #include "common/sysctl.h" +const char* ffDetectCpuTemp(double* current) +{ + int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999); + if (temp == -999999) + return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed"; + + // In tenth of degrees Celsius + *current = (double) temp / 10; + return NULL; +} + const char* ffDetectThermalTemp(double* current) { int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999); diff --git a/src/detection/temps/temps_bsd.h b/src/detection/temps/temps_bsd.h index a41aba6bc2..b126811a05 100644 --- a/src/detection/temps/temps_bsd.h +++ b/src/detection/temps/temps_bsd.h @@ -3,6 +3,7 @@ #ifndef FF_INCLUDED_detection_temps_windows #define FF_INCLUDED_detection_temps_windows +const char* ffDetectCpuTemp(double* current); const char* ffDetectThermalTemp(double* current); #endif From 2feb53149a8788f7fde04ea2eb10c8642fa16c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 11:14:04 +0800 Subject: [PATCH 53/74] Revert "CpuUsage (apple): simplify implementation" This reverts commit cabd36d07888e6d1bc398d5c9fe636df8a85ab19. --- src/detection/cpuusage/cpuusage_apple.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/detection/cpuusage/cpuusage_apple.c b/src/detection/cpuusage/cpuusage_apple.c index b946152193..d0dd42920f 100644 --- a/src/detection/cpuusage/cpuusage_apple.c +++ b/src/detection/cpuusage/cpuusage_apple.c @@ -6,18 +6,23 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) { - host_cpu_load_info_data_t cpustats; - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - + natural_t numCPUs = 0U; + processor_info_array_t cpuInfo; + mach_msg_type_number_t numCpuInfo; *inUseAll = *totalAll = 0; - 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]; + 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"; + 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 c96d21c7c073beedc037fb3e66e24c313dce2c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 11:18:22 +0800 Subject: [PATCH 54/74] CPUUsage (Linux): count cpu cores separately --- src/detection/cpuusage/cpuusage_linux.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index 78c64215ea..ac73d39c8e 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -1,14 +1,13 @@ #include "fastfetch.h" #include "detection/cpuusage/cpuusage.h" +#include "common/io/io.h" #include #include const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) { - uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; - - FILE* procStat = fopen("/proc/stat", "r"); + FF_AUTO_CLOSE_FILE FILE* procStat = fopen("/proc/stat", "r"); if(procStat == NULL) { #ifdef __ANDROID__ @@ -17,16 +16,21 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) return "fopen(\"""/proc/stat\", \"r\") == NULL"; #endif } + // Skip first line + if (fscanf(procStat, "cpu%*[^\n]\n") < 0) + return "fscanf() first line failed"; + + *inUseAll = 0; + *totalAll = 0; - if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) + uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; + while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) { - fclose(procStat); - return "fscanf() failed"; + uint64_t inUse = user + nice + system; + uint64_t total = inUse + idle + iowait + irq + softirq; + *inUseAll += inUse; + *totalAll += total; } - *inUseAll = user + nice + system; - *totalAll = *inUseAll + idle + iowait + irq + softirq; - - fclose(procStat); return NULL; } From 6b008ed93b57f23d5157f16ed96f7b40423defdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 13:40:00 +0800 Subject: [PATCH 55/74] CPUUsage (FreeBSD): count cpu cores separately --- src/detection/cpuusage/cpuusage_bsd.c | 29 +++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/detection/cpuusage/cpuusage_bsd.c b/src/detection/cpuusage/cpuusage_bsd.c index fa1945aaa5..8f888491bb 100644 --- a/src/detection/cpuusage/cpuusage_bsd.c +++ b/src/detection/cpuusage/cpuusage_bsd.c @@ -1,19 +1,32 @@ #include "detection/cpuusage/cpuusage.h" +#include "util/mallocHelper.h" #include -#include #include +#include +#include const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) { - // interrupt processing, user processes, system processing, lock spinning, and idling - uint64_t cpTime[5]; - size_t neededLength = sizeof(cpTime); - if(sysctlbyname("kern.cp_time", cpTime, &neededLength, NULL, 0) != 0) - return "sysctlbyname(kern.cp_time) failed"; + size_t neededLength = 0; + if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0) + return "sysctlbyname(kern.cp_times, NULL) failed"; - *inUseAll = cpTime[0] + cpTime[1] + cpTime[2] + cpTime[3]; - *totalAll = *inUseAll + cpTime[4]; + uint32_t coreCount = neededLength / (CPUSTATES * sizeof(uint64_t)); + assert(coreCount > 0); + + FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength); + if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0) + return "sysctlbyname(kern.cp_times, cpTime) failed"; + + for (uint32_t i = 0; i < coreCount; ++i) + { + uint64_t* cpTime = cpTimes[i]; + uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS]; + uint64_t total = cpTime[CP_INTR] + cpTime[CP_IDLE]; + *inUseAll += inUse; + *totalAll += total; + } return NULL; } From 42cf88be9dab87154603e50f729f09bc80dcee8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 16:00:23 +0800 Subject: [PATCH 56/74] CPUUsage: support display value per core --- src/detection/cpuusage/cpuusage.c | 58 +++++++----- src/detection/cpuusage/cpuusage.h | 10 +- src/detection/cpuusage/cpuusage_apple.c | 14 ++- src/detection/cpuusage/cpuusage_bsd.c | 12 ++- src/detection/cpuusage/cpuusage_linux.c | 13 +-- src/detection/cpuusage/cpuusage_windows.c | 15 +-- src/modules/cpuusage/cpuusage.c | 106 ++++++++++++++++++---- src/modules/cpuusage/option.h | 7 ++ src/util/FFlist.h | 5 + 9 files changed, 179 insertions(+), 61 deletions(-) diff --git a/src/detection/cpuusage/cpuusage.c b/src/detection/cpuusage/cpuusage.c index 563c6fae52..040d68780b 100644 --- a/src/detection/cpuusage/cpuusage.c +++ b/src/detection/cpuusage/cpuusage.c @@ -4,42 +4,54 @@ #include -// We need to use uint64_t because sizeof(long) == 4 on Windows -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll); - -static uint64_t inUseAll1, totalAll1; +static FFlist cpuTimes1; void ffPrepareCPUUsage(void) { - ffGetCpuUsageInfo(&inUseAll1, &totalAll1); + assert(cpuTimes1.elementSize == 0); + ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo)); + ffGetCpuUsageInfo(&cpuTimes1); } -const char* ffGetCpuUsageResult(double* result) +const char* ffGetCpuUsageResult(FFlist* result) { const char* error = NULL; - if(inUseAll1 == 0 && totalAll1 == 0) + if(cpuTimes1.elementSize == 0) { - error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1); - if(error) - return error; + ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo)); + error = ffGetCpuUsageInfo(&cpuTimes1); + if(error) return error; ffTimeSleep(200); } - while(true) - { - uint64_t inUseAll2, totalAll2; - error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2); - if(error) - return error; + if(cpuTimes1.length == 0) return "No CPU cores found"; + + FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo)); - if(inUseAll2 != inUseAll1) +retry: + error = ffGetCpuUsageInfo(&cpuTimes2); + if(error) return error; + if(cpuTimes1.length != cpuTimes2.length) return "Unexpected CPU usage result"; + + for (uint32_t i = 0; i < cpuTimes1.length; ++i) + { + FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i); + FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i); + if (cpuTime2->totalAll <= cpuTime1->totalAll) { - *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; - inUseAll1 = inUseAll2; - totalAll1 = totalAll2; - return NULL; - } - else + ffListClear(&cpuTimes2); ffTimeSleep(200); + goto retry; + } + } + + for (uint32_t i = 0; i < cpuTimes1.length; ++i) + { + FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i); + FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i); + *(double*) ffListAdd(result) = (double)(cpuTime2->inUseAll - cpuTime1->inUseAll) / (double)(cpuTime2->totalAll - cpuTime1->totalAll) * 100; + cpuTime1->inUseAll = cpuTime2->inUseAll; + cpuTime1->totalAll = cpuTime2->totalAll; } + return NULL; } diff --git a/src/detection/cpuusage/cpuusage.h b/src/detection/cpuusage/cpuusage.h index fb3c81e8e5..655239350f 100644 --- a/src/detection/cpuusage/cpuusage.h +++ b/src/detection/cpuusage/cpuusage.h @@ -3,6 +3,14 @@ #ifndef FF_INCLUDED_detection_cpuusage_cpuusage #define FF_INCLUDED_detection_cpuusage_cpuusage -const char* ffGetCpuUsageResult(double* result); +#include "fastfetch.h" + +typedef struct FFCpuUsageInfo { + uint64_t inUseAll; + uint64_t totalAll; +} FFCpuUsageInfo; +const char* ffGetCpuUsageInfo(FFlist* cpuTimes); + +const char* ffGetCpuUsageResult(FFlist* result); // list of double #endif diff --git a/src/detection/cpuusage/cpuusage_apple.c b/src/detection/cpuusage/cpuusage_apple.c index d0dd42920f..513b5e9304 100644 --- a/src/detection/cpuusage/cpuusage_apple.c +++ b/src/detection/cpuusage/cpuusage_apple.c @@ -4,25 +4,29 @@ #include #include -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) +const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { natural_t numCPUs = 0U; processor_info_array_t cpuInfo; mach_msg_type_number_t numCpuInfo; - *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"; - for (natural_t i = 0U; i < numCPUs; ++i) { + 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; + + FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); + *info = (FFCpuUsageInfo) { + .inUseAll = (uint64_t)inUse, + .totalAll = (uint64_t)total, + }; } return NULL; } diff --git a/src/detection/cpuusage/cpuusage_bsd.c b/src/detection/cpuusage/cpuusage_bsd.c index 8f888491bb..6c58832e03 100644 --- a/src/detection/cpuusage/cpuusage_bsd.c +++ b/src/detection/cpuusage/cpuusage_bsd.c @@ -6,13 +6,13 @@ #include #include -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) +const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { size_t neededLength = 0; if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0) return "sysctlbyname(kern.cp_times, NULL) failed"; - uint32_t coreCount = neededLength / (CPUSTATES * sizeof(uint64_t)); + uint32_t coreCount = neededLength / (CPUSTATES * (uint32_t) sizeof(uint64_t)); assert(coreCount > 0); FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength); @@ -24,8 +24,12 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) uint64_t* cpTime = cpTimes[i]; uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS]; uint64_t total = cpTime[CP_INTR] + cpTime[CP_IDLE]; - *inUseAll += inUse; - *totalAll += total; + + FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); + *info = (FFCpuUsageInfo) { + .inUseAll = (uint64_t)inUse, + .totalAll = (uint64_t)total, + }; } return NULL; diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index ac73d39c8e..85b63c4501 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -5,7 +5,7 @@ #include #include -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) +const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { FF_AUTO_CLOSE_FILE FILE* procStat = fopen("/proc/stat", "r"); if(procStat == NULL) @@ -20,16 +20,17 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) if (fscanf(procStat, "cpu%*[^\n]\n") < 0) return "fscanf() first line failed"; - *inUseAll = 0; - *totalAll = 0; - uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) { uint64_t inUse = user + nice + system; uint64_t total = inUse + idle + iowait + irq + softirq; - *inUseAll += inUse; - *totalAll += total; + + FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); + *info = (FFCpuUsageInfo) { + .inUseAll = (uint64_t)inUse, + .totalAll = (uint64_t)total, + }; } return NULL; diff --git a/src/detection/cpuusage/cpuusage_windows.c b/src/detection/cpuusage/cpuusage_windows.c index a22250d834..cf513340e1 100644 --- a/src/detection/cpuusage/cpuusage_windows.c +++ b/src/detection/cpuusage/cpuusage_windows.c @@ -6,7 +6,7 @@ #include #include -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) +const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { ULONG size = 0; if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) @@ -16,8 +16,6 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size))) return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, size) failed"; - *inUseAll = *totalAll = 0; - for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i) { SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i; @@ -28,9 +26,14 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart; coreInfo->KernelTime.QuadPart += dpcTime + interruptTime; - LONGLONG inUse = coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart; - *inUseAll += (uint64_t)inUse; - *totalAll += (uint64_t)(inUse + coreInfo->IdleTime.QuadPart); + uint64_t inUse = (uint64_t) (coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart); + uint64_t total = inUse + (uint64_t)coreInfo->IdleTime.QuadPart; + + FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); + *info = (FFCpuUsageInfo) { + .inUseAll = (uint64_t)inUse, + .totalAll = (uint64_t)total, + }; } return NULL; diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index f658d832f4..26b24e8ecf 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -6,12 +6,12 @@ #include "util/stringUtils.h" #define FF_CPUUSAGE_DISPLAY_NAME "CPU Usage" -#define FF_CPUUSAGE_NUM_FORMAT_ARGS 1 +#define FF_CPUUSAGE_NUM_FORMAT_ARGS 5 void ffPrintCPUUsage(FFCPUUsageOptions* options) { - double percentage = 0.0/0.0; - const char* error = ffGetCpuUsageResult(&percentage); + FF_LIST_AUTO_DESTROY percentages = ffListCreate(sizeof(double)); + const char* error = ffGetCpuUsageResult(&percentages); if(error) { @@ -19,27 +19,68 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) return; } + double maxValue = -999, minValue = 999, sumValue = 0; + uint32_t maxIndex = 999, minIndex = 999; + + uint32_t index = 0; + FF_LIST_FOR_EACH(double, percent, percentages) + { + sumValue += *percent; + if (*percent > maxValue) + { + maxValue = *percent; + maxIndex = index; + } + if (*percent < minValue) + { + minValue = *percent; + minIndex = index; + } + ++index; + } + double avgValue = sumValue / (double) percentages.length; + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) - ffAppendPercentBar(&str, percentage, 0, 50, 80); - if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if (options->displayType == FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT) { - if(str.length > 0) - ffStrbufAppendC(&str, ' '); - ffAppendPercentNum(&str, percentage, 50, 80, str.length > 0); + if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffAppendPercentBar(&str, avgValue, 0, 50, 80); + if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + { + if(str.length > 0) + ffStrbufAppendC(&str, ' '); + ffAppendPercentNum(&str, avgValue, 50, 80, str.length > 0); + } + } + else + { + FF_LIST_FOR_EACH(double, percent, percentages) + { + if(str.length > 0) + ffStrbufAppendC(&str, ' '); + ffAppendPercentNum(&str, *percent, 50, 80, false); + } } ffStrbufPutTo(&str, stdout); } else { - FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate(); - ffAppendPercentNum(&percentageStr, percentage, 50, 80, false); + FF_STRBUF_AUTO_DESTROY avgStr = ffStrbufCreate(); + ffAppendPercentNum(&avgStr, avgValue, 50, 80, false); + FF_STRBUF_AUTO_DESTROY minStr = ffStrbufCreate(); + ffAppendPercentNum(&minStr, minValue, 50, 80, false); + FF_STRBUF_AUTO_DESTROY maxStr = ffStrbufCreate(); + ffAppendPercentNum(&maxStr, maxValue, 50, 80, false); ffPrintFormat(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_CPUUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr} + {FF_FORMAT_ARG_TYPE_STRBUF, &avgStr}, + {FF_FORMAT_ARG_TYPE_STRBUF, &maxStr}, + {FF_FORMAT_ARG_TYPE_UINT, &maxIndex}, + {FF_FORMAT_ARG_TYPE_STRBUF, &minStr}, + {FF_FORMAT_ARG_TYPE_UINT, &minIndex}, }); } } @@ -57,6 +98,16 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffStrEqualsIgnCase(subKey, "display-type")) + { + options->displayType = (FFCPUUsageDisplayType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT }, + { "separate", FF_CPUUSAGE_DISPLAY_TYPE_SEPARATE }, + {}, + }); + return true; + } + return false; } @@ -78,26 +129,49 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffStrEqualsIgnCase(key, "display-type")) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "default", FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT }, + { "separate", FF_CPUUSAGE_DISPLAY_TYPE_SEPARATE }, + {}, + }); + if (error) + ffPrintErrorString(FF_CPUUSAGE_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", key, error); + else + options->displayType = (FFCPUUsageDisplayType) value; + continue; + } + ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } void ffGenerateCPUUsageJson(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - double percentage = 0.0/0.0; - const char* error = ffGetCpuUsageResult(&percentage); + FF_LIST_AUTO_DESTROY percentages = ffListCreate(sizeof(double)); + const char* error = ffGetCpuUsageResult(&percentages); if(error) { yyjson_mut_obj_add_str(doc, module, "error", error); return; } - yyjson_mut_obj_add_real(doc, module, "result", percentage); + yyjson_mut_val* result = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(double, percent, percentages) + { + yyjson_mut_arr_add_real(doc, result, *percent); + } } void ffPrintCPUUsageHelpFormat(void) { ffPrintModuleFormatHelp(FF_CPUUSAGE_MODULE_NAME, "{1}", FF_CPUUSAGE_NUM_FORMAT_ARGS, (const char* []) { - "CPU usage (percentage)" + "CPU usage (percentage, average)", + "CPU usage (percentage, maximum)", + "CPU core index of maximum usage", + "CPU usage (percentage, minimum)", + "CPU core index of minimum usage", }); } diff --git a/src/modules/cpuusage/option.h b/src/modules/cpuusage/option.h index 9468553016..3a7069bce0 100644 --- a/src/modules/cpuusage/option.h +++ b/src/modules/cpuusage/option.h @@ -4,8 +4,15 @@ #include "common/option.h" +typedef enum FFCPUUsageDisplayType { + FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT, + FF_CPUUSAGE_DISPLAY_TYPE_SEPARATE, +} FFCPUUsageDisplayType; + typedef struct FFCPUUsageOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + FFCPUUsageDisplayType displayType; } FFCPUUsageOptions; diff --git a/src/util/FFlist.h b/src/util/FFlist.h index 4961adda3f..276a65e130 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -90,6 +90,11 @@ static inline void ffListDestroy(FFlist* list) list->data = NULL; } +static inline void ffListClear(FFlist* list) +{ + list->length = 0; +} + #define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \ assert(sizeof(itemType) == (listVar).elementSize); \ for(itemType* itemVarName = (itemType*)(listVar).data; \ From e297144fe2625e2e6d63d5476b395a302e544586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 18:46:59 +0800 Subject: [PATCH 57/74] CPUUsage: fix multi core data detection --- src/detection/cpuusage/cpuusage_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index 85b63c4501..784f680b59 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -21,7 +21,7 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes) return "fscanf() first line failed"; uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; - while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) + while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) { uint64_t inUse = user + nice + system; uint64_t total = inUse + idle + iowait + irq + softirq; From 0847432dd9375d7725f4e3c3d4abd82ac763f8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 19:01:48 +0800 Subject: [PATCH 58/74] CPUUsage: rename `cpuusage-display-type` to `separate` --- CHANGELOG.md | 1 + doc/json_schema.json | 18 ++++++++++++++---- src/data/help.txt | 1 + src/modules/cpuusage/cpuusage.c | 23 +++++------------------ src/modules/cpuusage/option.h | 7 +------ 5 files changed, 22 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a698d4b202..4a46f2408b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Features: * Support GNOME Console terminal version and font detection (Terminal, Linux) * Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU) * New module to detect physical disk I/O usage (DiskIO) +* Add `--cpuusage-separate` to display CPU usage per CPU logical core Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) diff --git a/doc/json_schema.json b/doc/json_schema.json index d3e36fed83..3c4b031e71 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -631,10 +631,6 @@ "const": "chassis", "description": "Print chassis type (desktop, laptop, etc)" }, - { - "const": "cpuusage", - "description": "Print CPU usage. Costs some time to collect data" - }, { "const": "cursor", "description": "Print cursor style name" @@ -876,6 +872,20 @@ }, "additionalProperties": false }, + { + "title": "CPU Usage", + "properties": { + "type": { + "const": "cpuusage", + "description": "Print CPU usage. Costs some time to collect data" + }, + "separate": { + "type": "boolean", + "description": "Display CPU usage per CPU logical core, instead of an average result", + "default": false + } + } + }, { "title": "Colors", "properties": { diff --git a/src/data/help.txt b/src/data/help.txt index 154dd7a0e5..a9ea8aab65 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -141,6 +141,7 @@ Module specific options: --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 --cpu-freq-ndigits : Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2 + --cpuusage-separate : Display CPU usage per CPU logical core, instead of an average result. Default is false --gpu-temp : Detect and display GPU temperature if supported. Default is false --gpu-force-vulkan : Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false --gpu-hide-type : Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 26b24e8ecf..c5cd12345a 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -45,7 +45,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - if (options->displayType == FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT) + if (!options->separate) { if(instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) ffAppendPercentBar(&str, avgValue, 0, 50, 80); @@ -98,13 +98,9 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; - if (ffStrEqualsIgnCase(subKey, "display-type")) + if (ffStrEqualsIgnCase(subKey, "separate")) { - options->displayType = (FFCPUUsageDisplayType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "default", FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT }, - { "separate", FF_CPUUSAGE_DISPLAY_TYPE_SEPARATE }, - {}, - }); + options->separate = ffOptionParseBoolean(value); return true; } @@ -129,18 +125,9 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "display-type")) + if (ffStrEqualsIgnCase(key, "separate")) { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "default", FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT }, - { "separate", FF_CPUUSAGE_DISPLAY_TYPE_SEPARATE }, - {}, - }); - if (error) - ffPrintErrorString(FF_CPUUSAGE_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", key, error); - else - options->displayType = (FFCPUUsageDisplayType) value; + options->separate = yyjson_get_bool(val); continue; } diff --git a/src/modules/cpuusage/option.h b/src/modules/cpuusage/option.h index 3a7069bce0..d7fea247d7 100644 --- a/src/modules/cpuusage/option.h +++ b/src/modules/cpuusage/option.h @@ -4,15 +4,10 @@ #include "common/option.h" -typedef enum FFCPUUsageDisplayType { - FF_CPUUSAGE_DISPLAY_TYPE_DEFAULT, - FF_CPUUSAGE_DISPLAY_TYPE_SEPARATE, -} FFCPUUsageDisplayType; - typedef struct FFCPUUsageOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFCPUUsageDisplayType displayType; + bool separate; } FFCPUUsageOptions; From 4e75fa958d9604abb17c00c9c7f912dfe08edefe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 19:20:33 +0800 Subject: [PATCH 59/74] Logo (Builtin): add EndeavourSmall Ref: https://github.com/dylanaraps/neofetch/pull/2391 --- CHANGELOG.md | 1 + src/logo/ascii/endeavour_small.txt | 7 +++++++ src/logo/builtin.c | 11 +++++++++++ 3 files changed, 19 insertions(+) create mode 100644 src/logo/ascii/endeavour_small.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a46f2408b..0ed8f45aa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Bugfixes: Logo: * Add Chimera Linux +* Add EndeavourSmall # 2.1.0 diff --git a/src/logo/ascii/endeavour_small.txt b/src/logo/ascii/endeavour_small.txt new file mode 100644 index 0000000000..7265f4dead --- /dev/null +++ b/src/logo/ascii/endeavour_small.txt @@ -0,0 +1,7 @@ + /${c2}o${c3}. +${c1} :${c2}sssso${c3}- +${c1} :${c2}ossssssso${c3}: +${c1} /${c2}ssssssssssso${c3}+ +${c1} -+${c2}ssssssssssssssso${c3}+ +${c1} //${c2}osssssssssssssso${c3}+- + `+++++++++++++++-` diff --git a/src/logo/builtin.c b/src/logo/builtin.c index a9c05200b5..5298d47a6d 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1277,6 +1277,17 @@ static const FFlogo E[] = { .colorKeys = FF_COLOR_FG_MAGENTA, .colorTitle = FF_COLOR_FG_RED, }, + // EndeavourSmall + { + .names = {"Endeavour_small", "endeavour-linux_small", "endeavouros_small", "endeavouros-linux_small"}, + .lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL, + .type = FF_LOGO_LINE_TYPE_SMALL_BIT, + .colors = { + FF_COLOR_FG_RED, + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_BLUE, + }, + }, // Endless { .names = {"Endless"}, From 5493f418edc6abc6209b8d5ca374248f49b404cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 20:21:11 +0800 Subject: [PATCH 60/74] Users: fix crashing on Windows; rename `tty` to more common name `sessionName` --- src/detection/users/users.h | 2 +- src/detection/users/users_linux.c | 2 +- src/detection/users/users_windows.c | 3 ++- src/modules/users/users.c | 14 +++++++------- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/detection/users/users.h b/src/detection/users/users.h index 8ddc2a0cf4..38b3cf2040 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -10,7 +10,7 @@ typedef struct FFUserResult FFstrbuf name; FFstrbuf hostName; FFstrbuf clientIp; - FFstrbuf tty; + FFstrbuf sessionName; uint64_t loginTime; // ms } FFUserResult; diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index 294c69b3e1..f10b9559d2 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -31,7 +31,7 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitS(&user->name, n->ut_user); ffStrbufInitS(&user->hostName, n->ut_host); - ffStrbufInitS(&user->tty, n->ut_line); + ffStrbufInitS(&user->sessionName, n->ut_line); #ifdef __linux__ if(n->ut_addr_v6[0] || n->ut_addr_v6[1] || n->ut_addr_v6[2] || n->ut_addr_v6[3]) ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", n->ut_addr_v6[0], n->ut_addr_v6[1], n->ut_addr_v6[2], n->ut_addr_v6[3]); diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 21e4353a12..115f7935d6 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -28,7 +28,8 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitWS(&user->name, session->pUserName); ffStrbufInitWS(&user->hostName, session->pHostName); - ffStrbufInitS(&user->clientIp, "0.0.0.0"); + ffStrbufInitWS(&user->sessionName, session->pSessionName); + ffStrbufInit(&user->clientIp); user->loginTime = 0; DWORD bytes = 0; diff --git a/src/modules/users/users.c b/src/modules/users/users.c index ba5e6e75c5..3565fbe8a3 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -75,7 +75,7 @@ void ffPrintUsers(FFUsersOptions* options) ffPrintFormat(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &user->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &user->hostName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &user->tty}, + {FF_FORMAT_ARG_TYPE_STRBUF, &user->sessionName}, {FF_FORMAT_ARG_TYPE_STRBUF, &user->clientIp}, {FF_FORMAT_ARG_TYPE_UINT64, &user->loginTime}, }); @@ -86,7 +86,7 @@ void ffPrintUsers(FFUsersOptions* options) { ffStrbufDestroy(&user->clientIp); ffStrbufDestroy(&user->hostName); - ffStrbufDestroy(&user->tty); + ffStrbufDestroy(&user->sessionName); ffStrbufDestroy(&user->name); } } @@ -159,11 +159,11 @@ void ffGenerateUsersJson(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc FF_LIST_FOR_EACH(FFUserResult, user, results) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_strbuf(doc, obj, "clientIp", &user->clientIp); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &user->name); yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &user->hostName); + yyjson_mut_obj_add_strbuf(doc, obj, "sessionName", &user->sessionName); + yyjson_mut_obj_add_strbuf(doc, obj, "clientIp", &user->clientIp); yyjson_mut_obj_add_uint(doc, obj, "loginTime", user->loginTime); - yyjson_mut_obj_add_strbuf(doc, obj, "name", &user->name); - yyjson_mut_obj_add_strbuf(doc, obj, "tty", &user->tty); } exit: @@ -171,7 +171,7 @@ void ffGenerateUsersJson(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc { ffStrbufDestroy(&user->clientIp); ffStrbufDestroy(&user->hostName); - ffStrbufDestroy(&user->tty); + ffStrbufDestroy(&user->sessionName); ffStrbufDestroy(&user->name); } } @@ -181,7 +181,7 @@ void ffPrintUsersHelpFormat(void) ffPrintModuleFormatHelp(FF_USERS_MODULE_NAME, "{1}@{2} - login time {5}", FF_USERS_NUM_FORMAT_ARGS, (const char* []) { "User name", "Host name", - "TTY name", + "Session name", "Client IP", "Login Time" }); From ab8448ee470c52bf4e0c8c1d07a564b484515347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Oct 2023 21:51:15 +0800 Subject: [PATCH 61/74] DiskIO (Windows): fix device name detection --- src/detection/diskio/diskio_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index 804327cf93..c2e71f41e3 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -39,7 +39,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) if (index != device->name.length) { ffStrbufAppendNS(&device->interconnect, index, device->name.chars); // SCSI - ffStrbufSubstrAfter(&device->name, index + 1); + ffStrbufSubstrAfter(&device->name, index); } ffStrbufSubstrBeforeLastC(&device->name, '\\'); ffStrbufSubstrAfterFirstS(&device->name, "&Ven_"); From e319be19de032a4e4fcb0c264e5b8ee3fe117fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Oct 2023 14:48:07 +0800 Subject: [PATCH 62/74] Wifi (macOS): print `` when we can't get SSID SSID is not available after Sonoma. According to the doc: SSID information is not available unless Location Services is enabled and the user has authorized the calling app to use location services. --- src/detection/wifi/wifi_apple.m | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 775856eec8..d76f988481 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -1,6 +1,7 @@ #include "wifi.h" #import +#import const char* ffDetectWifi(FFlist* result) { @@ -31,7 +32,12 @@ if(!inf.serviceActive) continue; - ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); + [CLLocationManager.new requestAlwaysAuthorization]; + if (inf.ssid) + ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); + else + ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 + ffStrbufAppendS(&item->conn.macAddress, inf.hardwareAddress.UTF8String); switch(inf.activePHYMode) { @@ -116,6 +122,9 @@ case 15 /*kCWSecurityOWETransition*/: ffStrbufAppendS(&item->conn.security, "OWE Transition"); break; + case kCWSecurityUnknown: + // Ignore + break; default: ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security); break; From 1fe92738d838b777f1ba4aac57da69e15455c0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Oct 2023 15:17:14 +0800 Subject: [PATCH 63/74] macOS: embed `Info.plist` --- CMakeLists.txt | 10 ++++++++++ src/util/apple/Info.plist.in | 14 ++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/util/apple/Info.plist.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b4037c199..bdecfd90c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,9 @@ fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG) configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY) configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY) +if(APPLE) + configure_file(src/util/apple/Info.plist.in Info.plist @ONLY) +endif() #################### # Ascii image data # @@ -957,6 +960,13 @@ if(WIN32) target_sources(flashfetch PRIVATE src/util/windows/version.rc ) +elseif(APPLE) + target_link_options(fastfetch + PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist + ) + target_link_options(flashfetch + PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist + ) endif() ################### diff --git a/src/util/apple/Info.plist.in b/src/util/apple/Info.plist.in new file mode 100644 index 0000000000..4fd959cfdb --- /dev/null +++ b/src/util/apple/Info.plist.in @@ -0,0 +1,14 @@ + + + + + CFBundleIdentifier + fastfetch + CFBundleName + @PROJECT_NAME@ + CFBundleShortVersionString + @PROJECT_VERSION@ + CFBundleDevelopmentRegion + English + + From 076324e60e0950ad30967040c23c67f8930d9287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Oct 2023 15:23:21 +0800 Subject: [PATCH 64/74] Wifi (macOS): remove undesired code --- src/detection/wifi/wifi_apple.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index d76f988481..57b23c4852 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -1,7 +1,6 @@ #include "wifi.h" #import -#import const char* ffDetectWifi(FFlist* result) { @@ -32,7 +31,6 @@ if(!inf.serviceActive) continue; - [CLLocationManager.new requestAlwaysAuthorization]; if (inf.ssid) ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); else From 643fed7d1cd6611d4138409b5a6dbee36a8fa261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Oct 2023 16:31:47 +0800 Subject: [PATCH 65/74] Doc: metion bug #581 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ed8f45aa2..7effc2cebd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # 2.1.1 +Changes: +* SSID detection no longer works in macOS Sonoma. It will be marked as `` before I find a solution (Wifi, macOS) + Features: * Support opkg (Packages, Linux) * Support GNOME Console terminal version and font detection (Terminal, Linux) From 582788645d7ba298601c0cbdcd9e075963af9dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Oct 2023 16:32:20 +0800 Subject: [PATCH 66/74] Doc: add information about how to make `Termux API` actually work --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81cae05a0a..d17646b1c3 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ For the image logo, WezTerm with iterm image protocol is known to work, surprisi * [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype) * [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers) -* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api) +* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Both the package [termux-api](https://github.com/termux/termux-packages/tree/master/packages/termux-api) and the Android app [Termux API](https://github.com/termux/termux-api) must be installed and the app `Termux API` must be configured to be able to self-running. In order to make Wifi detection actuall work, location privilege must be granted to the app `Termux API`. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail. * [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android. For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol. From ebab281471296b4b7aace255e11ba0ec1e807f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Oct 2023 21:09:43 +0800 Subject: [PATCH 67/74] Processes (Linux): fix implementation `sysinfo.procs` reports number of all running threads, instead of processes --- CHANGELOG.md | 1 + src/detection/processes/processes_linux.c | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7effc2cebd..2a663a8f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Bugfixes: * Fix possible crashes caused by uninitialized strings (Users, Windows) * Improve support of `--help *-format` and several bugs are found and fixed * Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS) +* Fix implementation processes counting (Processes, Linux) Logo: * Add Chimera Linux diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 7e17fbc9a8..cff71038c3 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -1,13 +1,25 @@ #include "processes.h" -#include +#include "common/io/io.h" + +#include const char* ffDetectProcesses(uint32_t* result) { - struct sysinfo info; - if(sysinfo(&info) != 0) - return "sysinfo() failed"; + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); + if(dir == NULL) + return "opendir(\"/proc\") failed"; + + uint32_t num = 0; + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) + { + if (entry->d_type == DT_DIR && isdigit(entry->d_name[0])) + ++num; + } + + *result = num; - *result = (uint32_t) info.procs; return NULL; } From 839ff311de67da0d34f5b4f1cf283d34daea26c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 13 Oct 2023 16:44:23 +0800 Subject: [PATCH 68/74] Wifi (macOS): work around #581 --- CHANGELOG.md | 3 --- src/detection/wifi/wifi_apple.m | 12 ++++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a663a8f5d..1867814d11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,5 @@ # 2.1.1 -Changes: -* SSID detection no longer works in macOS Sonoma. It will be marked as `` before I find a solution (Wifi, macOS) - Features: * Support opkg (Packages, Linux) * Support GNOME Console terminal version and font detection (Terminal, Linux) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 57b23c4852..68a86808b1 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -1,4 +1,5 @@ #include "wifi.h" +#include "common/processing.h" #import @@ -33,6 +34,17 @@ if (inf.ssid) ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); + else if (!ffProcessAppendStdOut(&item->conn.ssid, (char* []) { + "/usr/sbin/networksetup", + "-getairportnetwork", + item->inf.description.chars, + NULL + }) && item->conn.ssid.length > 0) + { + uint32_t index = ffStrbufFirstIndexC(&item->conn.ssid, ':'); + if (index < item->conn.ssid.length) + ffStrbufSubstrAfter(&item->conn.ssid, index + 1); + } else ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 From 42e87b498c51c73d52cf8b5bd2f5e31f7a0e1bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 01:38:02 +0800 Subject: [PATCH 69/74] Brightness (Linux): allow specifying busno for ddcutil Ref: #580 --- src/detection/brightness/brightness_linux.c | 95 +++++++++++++++------ src/modules/brightness/brightness.c | 24 ++++++ src/modules/brightness/option.h | 4 + 3 files changed, 97 insertions(+), 26 deletions(-) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index d46599a851..ef622464b8 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -92,18 +92,80 @@ static const char* detectWithBacklight(FFlist* result) #include +typedef struct DdcutilData +{ + FF_LIBRARY_SYMBOL(ddca_open_display2) + FF_LIBRARY_SYMBOL(ddca_get_any_vcp_value_using_explicit_type) + FF_LIBRARY_SYMBOL(ddca_free_any_vcp_value) + FF_LIBRARY_SYMBOL(ddca_close_display) +} DdcutilData; + +static void detectWithDdcciImpl(DdcutilData* data, FFlist* result, DDCA_Display_Info* dinfo) +{ + DDCA_Display_Handle handle; + if (data->ffddca_open_display2(dinfo->dref, false, &handle) >= 0) + { + DDCA_Any_Vcp_Value* vcpValue = NULL; + if (data->ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) + { + assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE); + int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue); + data->ffddca_free_any_vcp_value(vcpValue); + + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + brightness->max = max; + brightness->min = 0; + brightness->current = current; + ffStrbufInitS(&brightness->name, dinfo->model_name); + } + data->ffddca_close_display(handle); + } +} + static const char* detectWithDdcci(FFlist* result) { - FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5); + FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_create_busno_display_identifier) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_create_display_ref) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_display_identifier) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_display_ref) + + DdcutilData ddcutilData; + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_open_display2) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_get_any_vcp_value_using_explicit_type) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_free_any_vcp_value) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_close_display) libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330 + if (instance.config.brightness.busNos.length) + { + FF_SUPPRESS_IO(); + + FF_LIST_FOR_EACH(int, busno, instance.config.brightness.busNos) + { + DDCA_Display_Identifier did; + if (ffddca_create_busno_display_identifier(*busno, &did) >= 0) + { + DDCA_Display_Ref dref; + if (ffddca_create_display_ref(did, &dref) >= 0) + { + FF_AUTO_FREE DDCA_Display_Info* dinfo = NULL; + if (ffddca_get_display_info(dref, &dinfo) >= 0) + detectWithDdcciImpl(&ddcutilData, result, dinfo); + ffddca_free_display_ref(dref); + } + + ffddca_free_display_identifier(did); + } + } + + return NULL; + } + FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL; - if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0)) + if (ffddca_get_display_info_list2(false, &infoList) < 0) return "ddca_get_display_info_list2(false, &infoList) failed"; if (infoList->ct == 0) @@ -111,26 +173,7 @@ static const char* detectWithDdcci(FFlist* result) for (int index = 0; index < infoList->ct; ++index) { - const DDCA_Display_Info* display = &infoList->info[index]; - - DDCA_Display_Handle handle; - if (ffddca_open_display2(display->dref, false, &handle) >= 0) - { - DDCA_Any_Vcp_Value* vcpValue = NULL; - if (ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) - { - assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE); - int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue); - ffddca_free_any_vcp_value(vcpValue); - - FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->max = max; - brightness->min = 0; - brightness->current = current; - ffStrbufInitS(&brightness->name, display->model_name); - } - ffddca_close_display(handle); - } + detectWithDdcciImpl(&ddcutilData, result, &infoList->info[index]); } return NULL; diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index f65c30d215..2a737a9f91 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -88,6 +88,10 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson, ffPrintBrightnessHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); + + #ifdef __linux__ + ffListInit(&options->busNos, sizeof(int)); + #endif } bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value) @@ -103,6 +107,10 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); + + #ifdef __linux__ + ffListDestroy(&options->busNos); + #endif } void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module) @@ -118,6 +126,22 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + #ifdef __linux__ + if(ffStrEqualsIgnCase(key, "busNos")) + { + if (!yyjson_is_arr(val)) continue; + + yyjson_val* item; + size_t idx, max; + yyjson_arr_foreach(val, idx, max, item) + { + if (!yyjson_is_int(item)) continue; + *(int*) ffListAdd(&options->busNos) = yyjson_get_int(item); + } + continue; + } + #endif + ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index aa67ac1903..bbaebef7d0 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -8,4 +8,8 @@ typedef struct FFBrightnessOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + +#ifdef __linux__ + FFlist busNos; +#endif } FFBrightnessOptions; From af945962021c5f85ab3723dd7878da6dc44cc84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 09:35:40 +0800 Subject: [PATCH 70/74] Revert "Brightness (Linux): allow specifying busno for ddcutil" This doesn't seem to improve much performance, but increase code complexity a lot This reverts commit 42e87b498c51c73d52cf8b5bd2f5e31f7a0e1bea. --- src/detection/brightness/brightness_linux.c | 95 ++++++--------------- src/modules/brightness/brightness.c | 24 ------ src/modules/brightness/option.h | 4 - 3 files changed, 26 insertions(+), 97 deletions(-) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index ef622464b8..d46599a851 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -92,80 +92,18 @@ static const char* detectWithBacklight(FFlist* result) #include -typedef struct DdcutilData -{ - FF_LIBRARY_SYMBOL(ddca_open_display2) - FF_LIBRARY_SYMBOL(ddca_get_any_vcp_value_using_explicit_type) - FF_LIBRARY_SYMBOL(ddca_free_any_vcp_value) - FF_LIBRARY_SYMBOL(ddca_close_display) -} DdcutilData; - -static void detectWithDdcciImpl(DdcutilData* data, FFlist* result, DDCA_Display_Info* dinfo) -{ - DDCA_Display_Handle handle; - if (data->ffddca_open_display2(dinfo->dref, false, &handle) >= 0) - { - DDCA_Any_Vcp_Value* vcpValue = NULL; - if (data->ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) - { - assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE); - int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue); - data->ffddca_free_any_vcp_value(vcpValue); - - FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->max = max; - brightness->min = 0; - brightness->current = current; - ffStrbufInitS(&brightness->name, dinfo->model_name); - } - data->ffddca_close_display(handle); - } -} - static const char* detectWithDdcci(FFlist* result) { - FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5) + FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_create_busno_display_identifier) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_create_display_ref) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_display_identifier) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_display_ref) - - DdcutilData ddcutilData; - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_open_display2) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_get_any_vcp_value_using_explicit_type) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_free_any_vcp_value) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libddcutil, ddcutilData, ddca_close_display) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display) libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330 - if (instance.config.brightness.busNos.length) - { - FF_SUPPRESS_IO(); - - FF_LIST_FOR_EACH(int, busno, instance.config.brightness.busNos) - { - DDCA_Display_Identifier did; - if (ffddca_create_busno_display_identifier(*busno, &did) >= 0) - { - DDCA_Display_Ref dref; - if (ffddca_create_display_ref(did, &dref) >= 0) - { - FF_AUTO_FREE DDCA_Display_Info* dinfo = NULL; - if (ffddca_get_display_info(dref, &dinfo) >= 0) - detectWithDdcciImpl(&ddcutilData, result, dinfo); - ffddca_free_display_ref(dref); - } - - ffddca_free_display_identifier(did); - } - } - - return NULL; - } - FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL; - if (ffddca_get_display_info_list2(false, &infoList) < 0) + if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0)) return "ddca_get_display_info_list2(false, &infoList) failed"; if (infoList->ct == 0) @@ -173,7 +111,26 @@ static const char* detectWithDdcci(FFlist* result) for (int index = 0; index < infoList->ct; ++index) { - detectWithDdcciImpl(&ddcutilData, result, &infoList->info[index]); + const DDCA_Display_Info* display = &infoList->info[index]; + + DDCA_Display_Handle handle; + if (ffddca_open_display2(display->dref, false, &handle) >= 0) + { + DDCA_Any_Vcp_Value* vcpValue = NULL; + if (ffddca_get_any_vcp_value_using_explicit_type(handle, 0x10 /*brightness*/, DDCA_NON_TABLE_VCP_VALUE, &vcpValue) >= 0) + { + assert(vcpValue->value_type == DDCA_NON_TABLE_VCP_VALUE); + int current = VALREC_CUR_VAL(vcpValue), max = VALREC_MAX_VAL(vcpValue); + ffddca_free_any_vcp_value(vcpValue); + + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + brightness->max = max; + brightness->min = 0; + brightness->current = current; + ffStrbufInitS(&brightness->name, display->model_name); + } + ffddca_close_display(handle); + } } return NULL; diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 2a737a9f91..f65c30d215 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -88,10 +88,6 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson, ffPrintBrightnessHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); - - #ifdef __linux__ - ffListInit(&options->busNos, sizeof(int)); - #endif } bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value) @@ -107,10 +103,6 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); - - #ifdef __linux__ - ffListDestroy(&options->busNos); - #endif } void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module) @@ -126,22 +118,6 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - #ifdef __linux__ - if(ffStrEqualsIgnCase(key, "busNos")) - { - if (!yyjson_is_arr(val)) continue; - - yyjson_val* item; - size_t idx, max; - yyjson_arr_foreach(val, idx, max, item) - { - if (!yyjson_is_int(item)) continue; - *(int*) ffListAdd(&options->busNos) = yyjson_get_int(item); - } - continue; - } - #endif - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index bbaebef7d0..aa67ac1903 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -8,8 +8,4 @@ typedef struct FFBrightnessOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - -#ifdef __linux__ - FFlist busNos; -#endif } FFBrightnessOptions; From e9c2a43de1f3951daa38b3c53da793747c379d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 10:04:08 +0800 Subject: [PATCH 71/74] Brightness: add `--brightness-ddcci-sleep` to set the sleep times (in ms) when sending DDC/CI requests Fix #580 --- CHANGELOG.md | 1 + doc/json_schema.json | 20 +++++++++++++++---- src/data/help.txt | 1 + src/detection/brightness/brightness.h | 2 +- src/detection/brightness/brightness_apple.c | 12 +++++------ src/detection/brightness/brightness_bsd.c | 4 ++-- src/detection/brightness/brightness_linux.c | 9 ++++++--- .../brightness/brightness_nosupport.c | 2 +- .../brightness/brightness_windows.cpp | 2 +- src/modules/brightness/brightness.c | 18 +++++++++++++++-- src/modules/brightness/option.h | 2 ++ 11 files changed, 53 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1867814d11..18ab8db190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Features: * Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU) * New module to detect physical disk I/O usage (DiskIO) * Add `--cpuusage-separate` to display CPU usage per CPU logical core +* Add `--brightness-ddcci-sleep` to set the sleep times (in ms) when sending DDC/CI requests (Brightness, #580) Bugfixes: * Fix possible crashes on Windows 7 (Disk, Windows) diff --git a/doc/json_schema.json b/doc/json_schema.json index 3c4b031e71..e309dee87f 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -623,10 +623,6 @@ "const": "board", "description": "Print mather board name and other info" }, - { - "const": "brightness", - "description": "Print brightness of your monitors" - }, { "const": "chassis", "description": "Print chassis type (desktop, laptop, etc)" @@ -838,6 +834,22 @@ }, "additionalProperties": false }, + { + "title": "Brightness", + "properties": { + "type": { + "const": "brightness", + "description": "Print current brightness / luminance of your monitors" + }, + "ddcciSleep": { + "type": "integer", + "description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee for detail", + "minimum": 0, + "maximum": 400, + "default": 10 + } + } + }, { "title": "CPU", "properties": { diff --git a/src/data/help.txt b/src/data/help.txt index a9ea8aab65..a83a81b8e7 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -137,6 +137,7 @@ Module specific options: --display-compact-type: : Set if all displays should be printed in one line. Default is none --display-detect-name: : Set if display name should be detected and printed (if supported). Default is false --display-precise-refresh-rate: :Set if decimal refresh rates should not be rounded into integers when printing. Default is true + --brightness-ddcci-sleep: Set the sleep times (in ms) when sending DDC/CI requests. See for detail. Default is 10 --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 diff --git a/src/detection/brightness/brightness.h b/src/detection/brightness/brightness.h index 58aeed20a2..b32e5d15c7 100644 --- a/src/detection/brightness/brightness.h +++ b/src/detection/brightness/brightness.h @@ -12,6 +12,6 @@ typedef struct FFBrightnessResult double min, max, current; } FFBrightnessResult; -const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult +const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result); // list of FFBrightnessResult #endif diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index 7a05ce87ff..4c58b5e6ab 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -52,7 +52,7 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa #ifdef __aarch64__ // https://github.com/waydabber/m1ddc // Works for Apple Silicon and USB-C adapter connection ( but not HTMI ) -static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFlist* result) +static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) { if (!IOAVServiceCreate || !IOAVServiceReadI2C) return "IOAVService is not available"; @@ -93,7 +93,7 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* for (uint32_t i = 0; i < 2; ++i) { IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, sizeof(i2cIn)); - usleep(10000); + usleep(options->ddcciSleep * 1000); } } @@ -121,7 +121,7 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* return NULL; } #else -static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) +static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) { if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available"; @@ -156,7 +156,7 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F .sendTransactionType = kIOI2CSimpleTransactionType, .sendBuffer = (vm_address_t) i2cIn, .sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]), - .minReplyDelay = 10, + .minReplyDelay = options->ddcciSleep, .replyAddress = 0x6F, .replySubAddress = 0x51, .replyTransactionType = kIOI2CDDCciReplyTransactionType, @@ -186,14 +186,14 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F } #endif -const char* ffDetectBrightness(FFlist* result) +const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result) { const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); detectWithDisplayServices(displayServer, result); if (displayServer->displays.length > result->length) - detectWithDdcci(displayServer, result); + detectWithDdcci(displayServer, options, result); return NULL; } diff --git a/src/detection/brightness/brightness_bsd.c b/src/detection/brightness/brightness_bsd.c index 72f1e54762..71bf8c9103 100644 --- a/src/detection/brightness/brightness_bsd.c +++ b/src/detection/brightness/brightness_bsd.c @@ -9,7 +9,7 @@ #include #include -const char* ffDetectBrightness(FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) { // https://man.freebsd.org/cgi/man.cgi?query=backlight&sektion=9 char path[] = "/dev/backlight/backlight0"; @@ -42,7 +42,7 @@ const char* ffDetectBrightness(FFlist* result) #else -const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result) { return "Backlight is supported only on FreeBSD 13 and newer"; } diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index d46599a851..85713f2259 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -92,7 +92,7 @@ static const char* detectWithBacklight(FFlist* result) #include -static const char* detectWithDdcci(FFlist* result) +static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result) { FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2) @@ -100,8 +100,11 @@ static const char* detectWithDdcci(FFlist* result) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_set_default_sleep_multiplier) libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330 + ffddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0); + FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL; if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0)) return "ddca_get_display_info_list2(false, &infoList) failed"; @@ -137,14 +140,14 @@ static const char* detectWithDdcci(FFlist* result) } #endif -const char* ffDetectBrightness(FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) { detectWithBacklight(result); #ifdef FF_HAVE_DDCUTIL const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); if (result->length < displayServer->displays.length) - detectWithDdcci(result); + detectWithDdcci(options, result); #endif return NULL; diff --git a/src/detection/brightness/brightness_nosupport.c b/src/detection/brightness/brightness_nosupport.c index 4bd83c4ded..3ad99ed336 100644 --- a/src/detection/brightness/brightness_nosupport.c +++ b/src/detection/brightness/brightness_nosupport.c @@ -1,6 +1,6 @@ #include "brightness.h" -const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result) { return "Not supported on this platform"; } diff --git a/src/detection/brightness/brightness_windows.cpp b/src/detection/brightness/brightness_windows.cpp index 06c1690178..01e3c03140 100644 --- a/src/detection/brightness/brightness_windows.cpp +++ b/src/detection/brightness/brightness_windows.cpp @@ -73,7 +73,7 @@ static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer) } extern "C" -const char* ffDetectBrightness(FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result) { const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index f65c30d215..eaedf10a96 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -11,7 +11,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFBrightnessResult)); - const char* error = ffDetectBrightness(&result); + const char* error = ffDetectBrightness(options, &result); if(error) { @@ -88,6 +88,8 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson, ffPrintBrightnessHelpFormat); ffOptionInitModuleArg(&options->moduleArgs); + + options->ddcciSleep = 10; } bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value) @@ -97,6 +99,12 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffStrEqualsIgnCase(key, "ddcci-sleep")) + { + options->ddcciSleep = ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -118,6 +126,12 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffStrEqualsIgnCase(key, "ddcciSleep")) + { + options->ddcciSleep = (uint32_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -126,7 +140,7 @@ void ffGenerateBrightnessJson(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjs { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFBrightnessResult)); - const char* error = ffDetectBrightness(&result); + const char* error = ffDetectBrightness(options, &result); if (error) { diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index aa67ac1903..cad3e7ac8d 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -8,4 +8,6 @@ typedef struct FFBrightnessOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + uint32_t ddcciSleep; // ms } FFBrightnessOptions; From 501803c8733a1fe77eec568ea4301f0126afebab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 18:14:37 +0800 Subject: [PATCH 72/74] Logo (Builtin): add Xenia https://github.com/hykilpikonna/hyfetch/issues/197 --- CHANGELOG.md | 1 + README.md | 2 +- src/logo/ascii/xenia.txt | 21 +++++++++++++++++++++ src/logo/builtin.c | 10 ++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/logo/ascii/xenia.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 18ab8db190..cfe58825f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Bugfixes: Logo: * Add Chimera Linux * Add EndeavourSmall +* Add Xenia # 2.1.0 diff --git a/README.md b/README.md index d17646b1c3..26ccceda90 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsa ``` -AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, Chimera Linux, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin +AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, Chimera Linux, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, EndeavourSmall, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LainOS, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xenia, Xferience, YiffOS, Zorin ``` Run `fastfetch --print-logos` to print them diff --git a/src/logo/ascii/xenia.txt b/src/logo/ascii/xenia.txt new file mode 100644 index 0000000000..2d6e940c4d --- /dev/null +++ b/src/logo/ascii/xenia.txt @@ -0,0 +1,21 @@ +${c2} ,c. .c; +${c2} .${c1}KMMMk${c2}.... ....${c1}kMMMK${c2}. +${c2} .${c1}WMMMMMX${c2}..... .....${c1}KMMMMMW. +${c1} XMMMMMMM0${c2}..... ....${c1}OMMMMMMMN +${c1} dMMMMMMMMM;${c2}.... ..... ....,${c1}MMMMMMMMMd +${c1} WMMMMMMMMMl;${c3}okKKKKKKKKKOo${c1};cMMMMMMMMMM +${c1} 'MMMMMMMNX${c2}K0${c3}KKKKKKKKKKKKKKK${c2}0K${c1}XNMMMMMMM; +${c1} oMMMMMMM${c2}Oxo${c3}KKKKKKKKKKKKKKKKK${c2}oxO${c1}MMMMMMMd +${c1} dMMMMMMM${c2}dxxx${c3}KKKKKKKKKKKKKKK${c2}xxxd${c1}NMMMMMMk +${c1} :MMMMX0${c2}xxxxxx${c3}0KKKKKKKK0KK0${c2}xxxxxx0${c1}XMMMMc +${c1} MMMO${c2}xxxxxxxxdx${c3}kdd${c2}0x0${c3}ddk${c2}xdxxxxxxxx${c1}OMMM +${c1} ;${c2}xxkxddxxxxdodxxxxdxdxxxxdodxxxxddxkxx${c1}; +${c1}dxd${c2}KMMMWXo${c1}'.....'${c2}cdxxxdc${c1}'.....'${c2}lXWMMMX${c1}dxd +${c1}cxd${c2}XMMMN${c1},..........${c2}dxd${c1}'.........'${c2}XMMMN${c1}dxl +${c1} .xx${c2}WMMl${c1}...''....'.;k:.'....''...${c2}lMMW${c1}xx. +${c1}..:kXMMx..'....''..kMk..''....'..xMMXkc.. +${c1} dMMMMMMd.....'...xMMMx...''....dMMMMMMx +${c1} kMMMMWOoc:coOkolllokOoc:coOWMMMMO +${c1} .MMMMMMMMl${c2}...${c1}lNMMMMMMM. +${c1} KMMMMMMX${c2}l${c1}KMMMMMMX +${c1} .MMMMMMMMM. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 5298d47a6d..9e475ecdca 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4160,6 +4160,16 @@ static const FFlogo W[] = { }; static const FFlogo X[] = { + // Xenia + { + .names = {"Xenia"}, + .lines = FASTFETCH_DATATEXT_LOGO_XENIA, + .colors = { + FF_COLOR_FG_YELLOW, + FF_COLOR_FG_GREEN, + FF_COLOR_FG_RED, + } + }, // Xferience { .names = {"Xferience"}, From 5e1983871356fe37d5b51c9f02a03cf4f6c4621c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 18:19:10 +0800 Subject: [PATCH 73/74] Doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe58825f0..2546d975f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Bugfixes: * Improve support of `--help *-format` and several bugs are found and fixed * Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS) * Fix implementation processes counting (Processes, Linux) +* Work around a issue that SSID cannot be detected on macOS Sonoma (Wifi, macOS) Logo: * Add Chimera Linux From 98e8e599a62e02bb4016442878ae4157ea46bfde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Oct 2023 18:23:42 +0800 Subject: [PATCH 74/74] Release v2.1.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bdecfd90c7..91b13df6cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.1.0 + VERSION 2.1.1 LANGUAGES C DESCRIPTION "Fast system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"