Files
fastfetch/src/modules/display/display.c
T

225 lines
8.3 KiB
C
Raw Normal View History

2023-03-10 10:56:36 +08:00
#include "common/printing.h"
2023-06-10 15:01:54 +08:00
#include "common/jsonconfig.h"
2023-03-10 10:56:36 +08:00
#include "detection/displayserver/displayserver.h"
#include "modules/display/display.h"
#include "util/stringUtils.h"
2023-03-10 10:56:36 +08:00
2023-06-12 10:35:28 +08:00
#define FF_DISPLAY_NUM_FORMAT_ARGS 8
2023-03-10 10:56:36 +08:00
void ffPrintDisplay(FFDisplayOptions* options)
2023-03-10 10:56:36 +08:00
{
const FFDisplayServerResult* dsResult = ffConnectDisplayServer();
2023-03-10 10:56:36 +08:00
if(dsResult->displays.length == 0)
{
2023-08-24 09:55:40 +08:00
ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, "Couldn't detect display");
2023-03-10 10:56:36 +08:00
return;
}
if (options->compactType != FF_DISPLAY_COMPACT_TYPE_NONE)
{
ffPrintLogoAndKey(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
2023-03-10 10:56:36 +08:00
int index = 0;
FF_LIST_FOR_EACH(FFDisplayResult, result, dsResult->displays)
{
if (options->compactType & FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT)
{
if (index++) putchar(' ');
printf("%ix%i", result->width, result->height);
}
if (options->compactType & FF_DISPLAY_COMPACT_TYPE_SCALED_BIT)
{
if (index++) putchar(' ');
printf("%ix%i", result->scaledWidth, result->scaledHeight);
}
}
putchar('\n');
return;
}
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
2023-03-10 10:56:36 +08:00
for(uint32_t i = 0; i < dsResult->displays.length; i++)
{
FFDisplayResult* result = ffListGet(&dsResult->displays, i);
uint32_t moduleIndex = dsResult->displays.length == 1 ? 0 : i + 1;
2023-03-10 10:56:36 +08:00
const char* displayType = result->type == FF_DISPLAY_TYPE_UNKNOWN ? NULL : result->type == FF_DISPLAY_TYPE_BUILTIN ? "built-in" : "external";
ffStrbufClear(&key);
if(options->moduleArgs.key.length == 0)
2023-03-10 10:56:36 +08:00
{
const char* subkey = result->name.length ? result->name.chars : displayType;
if (subkey)
ffStrbufAppendF(&key, "%s (%s)", FF_DISPLAY_MODULE_NAME, subkey);
else if (moduleIndex > 0)
ffStrbufAppendF(&key, "%s (%d)", FF_DISPLAY_MODULE_NAME, moduleIndex);
2023-03-10 10:56:36 +08:00
else
ffStrbufAppendS(&key, FF_DISPLAY_MODULE_NAME);
}
else
{
ffParseFormatString(&key, &options->moduleArgs.key, 3, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &moduleIndex},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRING, displayType},
});
}
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
2023-03-10 10:56:36 +08:00
printf("%ix%i", result->width, result->height);
if(result->refreshRate > 0)
{
if(options->preciseRefreshRate)
printf(" @ %gHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0);
else
printf(" @ %iHz", (uint32_t) (result->refreshRate + 0.5));
}
if(
result->scaledWidth > 0 && result->scaledWidth != result->width &&
result->scaledHeight > 0 && result->scaledHeight != result->height)
printf(" (as %ix%i)", result->scaledWidth, result->scaledHeight);
2023-06-17 15:38:50 +08:00
if(moduleIndex > 0 && result->primary)
printf(" *");
2023-03-10 10:56:36 +08:00
putchar('\n');
}
else
{
ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, (FFformatarg[]) {
2023-03-10 10:56:36 +08:00
{FF_FORMAT_ARG_TYPE_UINT, &result->width},
{FF_FORMAT_ARG_TYPE_UINT, &result->height},
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->refreshRate},
{FF_FORMAT_ARG_TYPE_UINT, &result->scaledWidth},
{FF_FORMAT_ARG_TYPE_UINT, &result->scaledHeight},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRING, displayType},
2023-06-12 10:35:28 +08:00
{FF_FORMAT_ARG_TYPE_UINT, &result->rotation},
2023-06-17 15:38:50 +08:00
{FF_FORMAT_ARG_TYPE_BOOL, &result->primary},
2023-03-10 10:56:36 +08:00
});
}
}
}
void ffInitDisplayOptions(FFDisplayOptions* options)
{
2023-08-31 14:36:21 +08:00
ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, ffGenerateDisplayJson);
2023-03-10 10:56:36 +08:00
ffOptionInitModuleArg(&options->moduleArgs);
options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE;
options->preciseRefreshRate = false;
}
bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_DISPLAY_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
if (ffStrEqualsIgnCase(subKey, "compact-type"))
2023-03-10 10:56:36 +08:00
{
options->compactType = (FFDisplayCompactType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "none", FF_DISPLAY_COMPACT_TYPE_NONE },
{ "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT },
{ "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT },
{},
});
return true;
}
if (ffStrEqualsIgnCase(subKey, "precise-refresh-rate"))
2023-03-10 10:56:36 +08:00
{
options->preciseRefreshRate = ffOptionParseBoolean(value);
return true;
}
return false;
}
void ffDestroyDisplayOptions(FFDisplayOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}
2023-06-18 14:00:24 +08:00
2023-08-17 10:56:54 +08:00
void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module)
2023-03-10 10:56:36 +08:00
{
2023-08-17 16:09:41 +08:00
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
2023-03-10 10:56:36 +08:00
{
2023-08-17 16:09:41 +08:00
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
2023-06-10 15:01:54 +08:00
2023-08-17 16:09:41 +08:00
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
2023-03-10 10:56:36 +08:00
2023-08-17 16:09:41 +08:00
if (ffStrEqualsIgnCase(key, "compactType"))
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "none", FF_DISPLAY_COMPACT_TYPE_NONE },
{ "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT },
{ "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT },
{},
});
if (error)
ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, "Invalid %s value: %s", key, error);
else
options->compactType = (FFDisplayCompactType) value;
continue;
}
2023-03-15 11:24:49 +08:00
2023-08-17 16:09:41 +08:00
if (ffStrEqualsIgnCase(key, "preciseRefreshRate"))
{
options->preciseRefreshRate = yyjson_get_bool(val);
continue;
}
2023-08-17 16:09:41 +08:00
ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
2023-03-10 10:56:36 +08:00
}
}
2023-08-31 14:36:21 +08:00
void ffGenerateDisplayJson(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
const FFDisplayServerResult* dsResult = ffConnectDisplayServer();
if(dsResult->displays.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect display");
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFDisplayResult, item, dsResult->displays)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
2023-09-08 20:03:26 +08:00
yyjson_mut_obj_add_uint(doc, obj, "width", item->width);
2023-08-31 14:36:21 +08:00
yyjson_mut_obj_add_uint(doc, obj, "height", item->height);
yyjson_mut_obj_add_uint(doc, obj, "id", item->id);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_bool(doc, obj, "primary", item->primary);
yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate);
yyjson_mut_obj_add_uint(doc, obj, "rotation", item->rotation);
yyjson_mut_obj_add_uint(doc, obj, "scaledHeight", item->scaledHeight);
yyjson_mut_obj_add_uint(doc, obj, "scaledWidth", item->scaledWidth);
switch (item->type)
{
case FF_DISPLAY_TYPE_BUILTIN:
yyjson_mut_obj_add_str(doc, obj, "type", "Builtin");
break;
case FF_DISPLAY_TYPE_EXTERNAL:
yyjson_mut_obj_add_str(doc, obj, "type", "External");
break;
default:
yyjson_mut_obj_add_str(doc, obj, "type", "Unknown");
break;
}
}
}