diff --git a/CMakeLists.txt b/CMakeLists.txt index 662e4c663..dd95d4291 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -382,6 +382,7 @@ set(LIBFASTFETCH_SRC src/modules/locale/locale.c src/modules/localip/localip.c src/modules/memory/memory.c + src/modules/monitor/monitor.c src/modules/netio/netio.c src/modules/opencl/opencl.c src/modules/opengl/opengl.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 7eebf0099..009e35484 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -684,6 +684,7 @@ "localip", "media", "memory", + "monitor", "netio", "opencl", "opengl", @@ -813,6 +814,10 @@ "const": "media", "description": "Print playing song name" }, + { + "const": "monitor", + "description": "Alias of Display module; deprecated" + }, { "const": "opencl", "description": "Print highest OpenCL version supported by the GPU" diff --git a/presets/all.jsonc b/presets/all.jsonc index e50c450cb..9b27615e0 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -24,6 +24,7 @@ "editor", "display", "brightness", + "monitor", "lm", "de", "wm", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index fe506e354..3027010d8 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -26,6 +26,7 @@ "editor", "display", "brightness", + "monitor", "lm", "de", "wm", diff --git a/src/common/modules.c b/src/common/modules.c index 87ae82829..4e8ae69e4 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -87,6 +87,7 @@ static FFModuleBaseInfo* L[] = { static FFModuleBaseInfo* M[] = { (void*) &instance.config.modules.media, (void*) &instance.config.modules.memory, + (void*) &instance.config.modules.monitor, NULL, }; diff --git a/src/modules/modules.h b/src/modules/modules.h index 76d76d622..4f9fa7a40 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -40,6 +40,7 @@ #include "modules/localip/localip.h" #include "modules/media/media.h" #include "modules/memory/memory.h" +#include "modules/monitor/monitor.h" #include "modules/netio/netio.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c new file mode 100644 index 000000000..6fe9b91ad --- /dev/null +++ b/src/modules/monitor/monitor.c @@ -0,0 +1,166 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/displayserver/displayserver.h" +#include "modules/monitor/monitor.h" +#include "util/stringUtils.h" + +#include + +#define FF_MONITOR_NUM_FORMAT_ARGS 12 + +void ffPrintMonitor(FFMonitorOptions* options) +{ + const FFDisplayServerResult* result = ffConnectDisplayServer(); + + if(!result->displays.length) + { + ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); + return; + } + + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + uint32_t index = 0; + FF_LIST_FOR_EACH(FFDisplayResult, display, result->displays) + { + double inch = sqrt(display->physicalWidth * display->physicalWidth + display->physicalHeight * display->physicalHeight) / 25.4; + double ppi = sqrt(display->width * display->width + display->height * display->height) / inch; + bool hdrCompatible = display->hdrStatus == FF_DISPLAY_HDR_STATUS_SUPPORTED || display->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; + + ffStrbufClear(&key); + if(options->moduleArgs.key.length == 0) + { + ffStrbufAppendF(&key, "%s (%s)", FF_MONITOR_MODULE_NAME, display->name.chars); + } + else + { + uint32_t moduleIndex = result->displays.length == 1 ? 0 : index + 1; + FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){ + FF_FORMAT_ARG(moduleIndex, "index"), + FF_FORMAT_ARG(display->name, "name"), + FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"), + })); + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + + printf("%ux%u px", display->width, display->height); + if (display->refreshRate > 0) + printf(" @ %g Hz", ((int) (display->refreshRate * 1000 + 0.5)) / 1000.0); + if (inch > 0) + printf(" - %ux%u mm (%.2f inches, %.2f ppi)", display->physicalWidth, display->physicalHeight, inch, ppi); + if (hdrCompatible) + fputs(" [HDR Compatible]", stdout); + putchar('\n'); + } + else + { + char buf[32]; + if (display->serial) + { + const uint8_t* nums = (uint8_t*) &display->serial; + snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); + } + else + buf[0] = '\0'; + + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_MONITOR_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_FORMAT_ARG(display->name, "name"), + FF_FORMAT_ARG(display->width, "width"), + FF_FORMAT_ARG(display->height, "height"), + FF_FORMAT_ARG(display->physicalWidth, "physical-width"), + FF_FORMAT_ARG(display->physicalHeight, "physical-height"), + FF_FORMAT_ARG(inch, "inch"), + FF_FORMAT_ARG(ppi, "ppi"), + FF_FORMAT_ARG(display->manufactureYear, "manufacture-year"), + FF_FORMAT_ARG(display->manufactureWeek, "manufacture-week"), + FF_FORMAT_ARG(buf, "serial"), + FF_FORMAT_ARG(display->refreshRate, "refresh-rate"), + FF_FORMAT_ARG(hdrCompatible, "hdr-compatible"), + })); + } + + ffStrbufDestroy(&display->name); + ++index; + } +} + +bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_MONITOR_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseMonitorJsonObject(FFMonitorOptions* 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; + + ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateMonitorJsonConfig(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyMonitorOptions))) FFMonitorOptions defaultOptions; + ffInitMonitorOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + yyjson_mut_obj_add_str(doc, module, "error", "Monitor module is an alias of Display module"); +} + +void ffPrintMonitorHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(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 - name", + "Native resolution width in pixels - width", + "Native resolution height in pixels - height", + "Physical width in millimeters - physical-width", + "Physical height in millimeters - physical-height", + "Physical diagonal length in inches - inch", + "Pixels per inch (PPI) - ppi", + "Year of manufacturing - manufacture-year", + "Nth week of manufacturing in the year - manufacture-week", + "Serial number - serial", + "Maximum refresh rate in Hz - refresh-rate", + "True if the display is HDR compatible - hdr-compatible", + })); +} + +void ffInitMonitorOptions(FFMonitorOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_MONITOR_MODULE_NAME, + "Alias of Display module; deprecated", + ffParseMonitorCommandOptions, + ffParseMonitorJsonObject, + ffPrintMonitor, + ffGenerateMonitorJsonResult, + ffPrintMonitorHelpFormat, + ffGenerateMonitorJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰹑"); +} + +void ffDestroyMonitorOptions(FFMonitorOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h new file mode 100644 index 000000000..d928c2ffe --- /dev/null +++ b/src/modules/monitor/monitor.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_MONITOR_MODULE_NAME "Monitor" + +void ffPrintMonitor(FFMonitorOptions* options); +void ffInitMonitorOptions(FFMonitorOptions* options); +void ffDestroyMonitorOptions(FFMonitorOptions* options); diff --git a/src/modules/monitor/option.h b/src/modules/monitor/option.h new file mode 100644 index 000000000..b474ae7b2 --- /dev/null +++ b/src/modules/monitor/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFMonitorOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFMonitorOptions; diff --git a/src/modules/options.h b/src/modules/options.h index b3a9dc74a..783757d3a 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -40,6 +40,7 @@ #include "modules/localip/option.h" #include "modules/media/option.h" #include "modules/memory/option.h" +#include "modules/monitor/option.h" #include "modules/netio/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index 4006391d3..cea3c7af0 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -41,6 +41,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitLocaleOptions(&options->locale); ffInitMediaOptions(&options->media); ffInitMemoryOptions(&options->memory); + ffInitMonitorOptions(&options->monitor); ffInitNetIOOptions(&options->netIo); ffInitOSOptions(&options->os); ffInitOpenCLOptions(&options->openCL); @@ -115,6 +116,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyLocaleOptions(&options->locale); ffDestroyMediaOptions(&options->media); ffDestroyMemoryOptions(&options->memory); + ffDestroyMonitorOptions(&options->monitor); ffDestroyNetIOOptions(&options->netIo); ffDestroyOSOptions(&options->os); ffDestroyOpenCLOptions(&options->openCL); diff --git a/src/options/modules.h b/src/options/modules.h index c57ac5c6b..919d92408 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -42,6 +42,7 @@ typedef struct FFOptionsModules FFLocaleOptions locale; FFMediaOptions media; FFMemoryOptions memory; + FFMonitorOptions monitor; FFNetIOOptions netIo; FFOSOptions os; FFOpenCLOptions openCL;