Global: move general options to a new separate folder

This commit is contained in:
李通洲
2023-10-25 13:39:13 +08:00
parent 04c3a4ccf7
commit bed1b4cf0f
28 changed files with 195 additions and 763 deletions
+3
View File
@@ -1,5 +1,8 @@
# 2.2.0
Changes:
* `--pipe` and `--stat` are moved from `general` options to `display` options. This affects cjson configuration.
Features:
* Quirks for MIPS platforms (CPU, Linux)
* Use devicetree path for OBP hosts (Host, Linux)
+1
View File
@@ -355,6 +355,7 @@ set(LIBFASTFETCH_SRC
src/modules/wm/wm.c
src/modules/wmtheme/wmtheme.c
src/options/logo.c
src/options/general.c
src/util/edidHelper.c
src/util/FFlist.c
src/util/FFstrbuf.c
+10 -10
View File
@@ -242,21 +242,11 @@
"title": "Alias of multithreading",
"default": true
},
"stat": {
"type": "boolean",
"title": "Show time usage (in ms) for individual modules",
"default": false
},
"escapeBedrock": {
"type": "boolean",
"title": "On Bedrock Linux, whether to escape the bedrock jail",
"default": true
},
"pipe": {
"type": "boolean",
"title": "Whether to enable pipe mode (disable logo and all escape sequences)",
"default": false
},
"playerName": {
"type": "string",
"title": "The name of the player to use for module Media and Player. Linux only"
@@ -287,6 +277,16 @@
"title": "Configure how things to be displayed",
"type": "object",
"properties": {
"stat": {
"type": "boolean",
"title": "Show time usage (in ms) for individual modules",
"default": false
},
"pipe": {
"type": "boolean",
"title": "Whether to enable pipe mode (disable logo and all escape sequences)",
"default": false
},
"showErrors": {
"type": "boolean",
"title": "Print occurring errors to the console. False to ignore errored modules",
+1 -1
View File
@@ -87,7 +87,7 @@ void ffPrepareCommandOption(FFdata* data)
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
ffPrepareNetIO(&instance.config.netIo);
if(instance.config.multithreading)
if(instance.config.general.multithreading)
{
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
ffPreparePublicIp(&instance.config.publicIP);
+2 -18
View File
@@ -33,23 +33,14 @@ static void initState(FFstate* state)
static void defaultConfig(void)
{
ffInitLogoOptions(&instance.config.logo);
ffInitGeneralOptions(&instance.config.general);
ffStrbufInit(&instance.config.colorKeys);
ffStrbufInit(&instance.config.colorTitle);
instance.config.brightColor = true;
ffStrbufInitStatic(&instance.config.keyValueSeparator, ": ");
instance.config.processingTimeout = 1000;
#if defined(__linux__) || defined(__FreeBSD__)
ffStrbufInit(&instance.config.playerName);
ffStrbufInit(&instance.config.osFile);
instance.config.dsForceDrm = false;
#elif defined(_WIN32)
instance.config.wmiTimeout = 5000;
#endif
instance.config.showErrors = false;
instance.config.allowSlowOperations = false;
instance.config.pipe = !isatty(STDOUT_FILENO);
#ifdef NDEBUG
@@ -60,12 +51,10 @@ static void defaultConfig(void)
instance.config.hideCursor = false;
#endif
instance.config.escapeBedrock = true;
instance.config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
instance.config.sizeNdigits = 2;
instance.config.sizeMaxPrefix = UINT8_MAX;
instance.config.temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS;
instance.config.multithreading = true;
instance.config.stat = false;
instance.config.noBuffer = false;
instance.config.keyWidth = 0;
@@ -233,7 +222,7 @@ static void exitSignalHandler(int signal)
void ffStart(void)
{
#ifdef FF_START_DETECTION_THREADS
if(instance.config.multithreading)
if(instance.config.general.multithreading)
startDetectionThreads();
#endif
@@ -287,11 +276,6 @@ static void destroyConfig(void)
ffStrbufDestroy(&instance.config.barCharElapsed);
ffStrbufDestroy(&instance.config.barCharTotal);
#if defined(__linux__) || defined(__FreeBSD__)
ffStrbufDestroy(&instance.config.playerName);
ffStrbufDestroy(&instance.config.osFile);
#endif
ffDestroyBatteryOptions(&instance.config.battery);
ffDestroyBiosOptions(&instance.config.bios);
ffDestroyBluetoothOptions(&instance.config.bluetooth);
+8 -54
View File
@@ -227,59 +227,6 @@ static const char* printJsonConfig(bool prepare)
return NULL;
}
const char* ffParseGeneralJsonConfig(FFconfig* config)
{
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
if (!yyjson_is_obj(root))
return "Invalid JSON config format. Root value must be an object";
yyjson_val* object = yyjson_obj_get(root, "general");
if (!object) return NULL;
if (!yyjson_is_obj(object)) return "Property 'general' must be an object";
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(object, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "allowSlowOperations"))
config->allowSlowOperations = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
config->multithreading = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "stat"))
{
if ((config->stat = yyjson_get_bool(val)))
config->showErrors = true;
}
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
config->escapeBedrock = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "pipe"))
config->pipe = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
config->processingTimeout = (int32_t) yyjson_get_int(val);
#if defined(__linux__) || defined(__FreeBSD__)
else if (ffStrEqualsIgnCase(key, "playerName"))
ffStrbufSetS(&config->playerName, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "osFile"))
ffStrbufSetS(&config->osFile, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
config->dsForceDrm = yyjson_get_bool(val);
#elif defined(_WIN32)
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
config->wmiTimeout = (int32_t) yyjson_get_int(val);
#endif
else
return "Unknown general property";
}
return NULL;
}
const char* ffParseDisplayJsonConfig(FFconfig* config)
{
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
@@ -298,7 +245,14 @@ const char* ffParseDisplayJsonConfig(FFconfig* config)
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "showErrors"))
if (ffStrEqualsIgnCase(key, "stat"))
{
if ((config->stat = yyjson_get_bool(val)))
config->showErrors = true;
}
else if (ffStrEqualsIgnCase(key, "pipe"))
config->pipe = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "showErrors"))
config->showErrors = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "disableLinewrap"))
config->disableLinewrap = yyjson_get_bool(val);
-1
View File
@@ -5,7 +5,6 @@
bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs);
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
void ffPrintJsonConfig(bool prepare);
const char* ffParseGeneralJsonConfig(FFconfig* config);
const char* ffParseDisplayJsonConfig(FFconfig* config);
const char* ffParseLibraryJsonConfig(FFconfig* config);
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs);
+1 -1
View File
@@ -48,7 +48,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
int timeout = instance.config.processingTimeout;
int timeout = instance.config.general.processingTimeout;
if (timeout >= 0)
fcntl(childPipeFd, F_SETFL, fcntl(childPipeFd, F_GETFL) | O_NONBLOCK);
+1 -1
View File
@@ -8,7 +8,7 @@ enum { FF_PIPE_BUFSIZ = 4096 };
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
{
int timeout = instance.config.processingTimeout;
int timeout = instance.config.general.processingTimeout;
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
L"\\\\.\\pipe\\LOCAL\\",
+1 -1
View File
@@ -32,7 +32,7 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
if(instance.config.allowSlowOperations)
if(instance.config.general.allowSlowOperations)
{
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
+1 -1
View File
@@ -67,7 +67,7 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
extern "C"
const char* ffDetectChassis(FFChassisResult* result)
{
if (instance.config.allowSlowOperations)
if (instance.config.general.allowSlowOperations)
return detectWithWmi(result);
return detectWithRegistry(result);
}
@@ -116,7 +116,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
ffStrbufInit(&ds->wmProtocolName);
if(instance.config.allowSlowOperations)
if(instance.config.general.allowSlowOperations)
{
FF_STRBUF_AUTO_DESTROY name;
ffStrbufInit(&name);
@@ -88,7 +88,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
ffStrbufInit(&ds->deVersion);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
if (!instance.config.dsForceDrm)
if (!instance.config.general.dsForceDrm)
{
//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
+4 -4
View File
@@ -154,7 +154,7 @@ static void getKDE(FFDisplayServerResult* result)
if(result->deVersion.length == 0)
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
{
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"plasmashell",
@@ -214,7 +214,7 @@ static void getMate(FFDisplayServerResult* result)
ffParseSemver(&result->deVersion, &major, &minor, &micro);
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
{
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"mate-session",
@@ -250,7 +250,7 @@ static void getXFCE4(FFDisplayServerResult* result)
}
#endif
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
{
//This is somewhat slow
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
@@ -276,7 +276,7 @@ static void getLXQt(FFDisplayServerResult* result)
if(result->deVersion.length == 0)
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
if(result->deVersion.length == 0 && instance.config.general.allowSlowOperations)
{
//This is really, really, really slow. Thank you, LXQt developers
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
+2 -2
View File
@@ -161,8 +161,8 @@ static const char* getMedia(FFMediaResult* result)
// FIXME: This is shared for both player and media module.
// However it uses an option in one specific module
if(instance.config.playerName.length > 0)
getCustomBus(&data, &instance.config.playerName, result);
if(instance.config.general.playerName.length > 0)
getCustomBus(&data, &instance.config.general.playerName, result);
else
getBestBus(&data, result);
+3 -3
View File
@@ -133,13 +133,13 @@ static void getDebianVersion(FFOSResult* result)
static void detectOS(FFOSResult* os)
{
if(instance.config.osFile.length > 0)
if(instance.config.general.osFile.length > 0)
{
parseFile(instance.config.osFile.chars, os);
parseFile(instance.config.general.osFile.chars, os);
return;
}
if(instance.config.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
if(instance.config.general.escapeBedrock && parseFile(FASTFETCH_TARGET_DIR_ROOT"/bedrock"FASTFETCH_TARGET_DIR_ETC"/bedrock-release", os))
{
if(os->id.length == 0)
ffStrbufAppendS(&os->id, "bedrock");
+1 -1
View File
@@ -110,6 +110,6 @@ void ffDetectPackagesImpl(FFPackagesResult* result)
detectScoop(result);
detectChoco(result);
detectPacman(result);
if (instance.config.allowSlowOperations)
if (instance.config.general.allowSlowOperations)
detectWinget(result);
}
+1 -1
View File
@@ -247,7 +247,7 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul
{"font_size ", &fontSize},
};
if(instance.config.allowSlowOperations)
if(instance.config.general.allowSlowOperations)
{
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if(!ffProcessAppendStdOut(&buf, (char* const[]){
+1 -1
View File
@@ -119,7 +119,7 @@ static const char* detectVulkan(FFVulkanResult* result)
PFN_vkGetPhysicalDeviceMemoryProperties ffvkGetPhysicalDeviceMemoryProperties = NULL;
PFN_vkGetPhysicalDeviceMemoryProperties2 ffvkGetPhysicalDeviceMemoryProperties2 =
instance.config.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1
instance.config.general.allowSlowOperations ? (PFN_vkGetPhysicalDeviceMemoryProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties2") : NULL; // 1.1
if(!ffvkGetPhysicalDeviceMemoryProperties2)
ffvkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties");
+22 -31
View File
@@ -471,9 +471,9 @@ static void parseOption(FFdata* data, const char* key, const char* value)
customValue->printKey = key[5] == '\0';
}
///////////////////
//General options//
///////////////////
////////////
//Switches//
////////////
else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--load-config") || ffStrEqualsIgnCase(key, "--config"))
optionParseConfigFile(data, key, value);
@@ -501,23 +501,8 @@ static void parseOption(FFdata* data, const char* key, const char* value)
else
instance.state.migrateConfigDoc = NULL;
}
else if(ffStrEqualsIgnCase(key, "--thread") || ffStrEqualsIgnCase(key, "--multithreading"))
instance.config.multithreading = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--stat"))
{
if((instance.config.stat = ffOptionParseBoolean(value)))
instance.config.showErrors = true;
}
else if(ffStrEqualsIgnCase(key, "--allow-slow-operations"))
instance.config.allowSlowOperations = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--escape-bedrock"))
instance.config.escapeBedrock = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--pipe"))
instance.config.pipe = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--load-user-config"))
data->loadUserConfig = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--processing-timeout"))
instance.config.processingTimeout = ffOptionParseInt32(key, value);
else if(ffStrEqualsIgnCase(key, "--format"))
{
switch (ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
@@ -543,17 +528,11 @@ static void parseOption(FFdata* data, const char* key, const char* value)
}
}
#if defined(__linux__) || defined(__FreeBSD__)
else if(ffStrEqualsIgnCase(key, "--player-name"))
ffOptionParseString(key, value, &instance.config.playerName);
else if (ffStrEqualsIgnCase(key, "--os-file"))
ffOptionParseString(key, value, &instance.config.osFile);
else if(ffStrEqualsIgnCase(key, "--ds-force-drm"))
instance.config.dsForceDrm = ffOptionParseBoolean(value);
#elif defined(_WIN32)
else if (ffStrEqualsIgnCase(key, "--wmi-timeout"))
instance.config.wmiTimeout = ffOptionParseInt32(key, value);
#endif
///////////////////
//General options//
///////////////////
else if(ffParseGeneralCommandOptions(&instance.config.general, key, value)) {}
////////////////
//Logo options//
@@ -565,6 +544,13 @@ static void parseOption(FFdata* data, const char* key, const char* value)
//Display options//
///////////////////
else if(ffStrEqualsIgnCase(key, "--stat"))
{
if((instance.config.stat = ffOptionParseBoolean(value)))
instance.config.showErrors = true;
}
else if(ffStrEqualsIgnCase(key, "--pipe"))
instance.config.pipe = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--show-errors"))
instance.config.showErrors = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--disable-linewrap"))
@@ -801,9 +787,14 @@ static void run(FFdata* data)
{
const char* error = NULL;
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
if (!yyjson_is_obj(root))
error = "Invalid JSON config format. Root value must be an object";
if (
(error = ffParseLogoJsonConfig(&instance.config.logo)) ||
(error = ffParseGeneralJsonConfig(&instance.config)) ||
error ||
(error = ffParseLogoJsonConfig(&instance.config.logo, root)) ||
(error = ffParseGeneralJsonConfig(&instance.config.general, root)) ||
(error = ffParseDisplayJsonConfig(&instance.config)) ||
(error = ffParseLibraryJsonConfig(&instance.config)) ||
false
+4 -15
View File
@@ -25,6 +25,7 @@
#include "modules/options.h"
#include "options/logo.h"
#include "options/general.h"
typedef enum FFBinaryPrefixType
{
@@ -43,6 +44,7 @@ typedef enum FFTemperatureUnit
typedef struct FFconfig
{
FFLogoOptions logo;
FFGeneralOptions general;
//If one of those is empty, ffLogoPrint will set them
FFstrbuf colorKeys;
@@ -52,11 +54,11 @@ typedef struct FFconfig
FFstrbuf keyValueSeparator;
bool stat;
bool pipe; //disables logo and all escape sequences
bool showErrors;
bool allowSlowOperations;
bool disableLinewrap;
bool hideCursor;
bool escapeBedrock;
FFBinaryPrefixType binaryPrefixType;
uint8_t sizeNdigits;
uint8_t sizeMaxPrefix;
@@ -67,22 +69,9 @@ typedef struct FFconfig
bool barBorder;
uint8_t percentType;
uint8_t percentNdigits;
bool pipe; //disables logo and all escape sequences
bool multithreading;
bool stat;
bool noBuffer;
int32_t processingTimeout;
uint32_t keyWidth;
// Module options that cannot be put in module option structure
#if defined(__linux__) || defined(__FreeBSD__)
FFstrbuf playerName;
FFstrbuf osFile;
bool dsForceDrm;
#elif defined(_WIN32)
int32_t wmiTimeout;
#endif
FFBatteryOptions battery;
FFBiosOptions bios;
FFBluetoothOptions bluetooth;
-560
View File
@@ -1,560 +0,0 @@
#include "logo/logo.h"
#include "common/jsonconfig.h"
#include "util/stringUtils.h"
void ffInitLogoOptions(FFLogoOptions* options)
{
ffStrbufInit(&options->source);
options->type = FF_LOGO_TYPE_AUTO;
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufInit(&options->colors[i]);
options->width = 0;
options->height = 0; //preserve aspect ratio
options->paddingTop = 0;
options->paddingLeft = 0;
options->paddingRight = 4;
options->printRemaining = true;
options->preserveAspectRadio = false;
options->recache = false;
options->separate = false;
options->chafaFgOnly = false;
ffStrbufInitStatic(&options->chafaSymbols, "block+border+space-wide-inverted"); // Chafa default
options->chafaCanvasMode = UINT32_MAX;
options->chafaColorSpace = UINT32_MAX;
options->chafaDitherMode = UINT32_MAX;
}
bool ffParseLogoCommandOptions(FFLogoOptions* options, const char* key, const char* value)
{
if (strcasecmp(key, "-l") == 0)
goto logoType;
const char* subKey = ffOptionTestPrefix(key, "logo");
if(subKey)
{
if (subKey[0] == '\0')
{
logoType:
if(value == NULL)
{
fprintf(stderr, "Error: usage: %s <none|small|logo-source>\n", key);
exit(477);
}
//this is usually wanted when disabling logo
if(strcasecmp(value, "none") == 0)
{
options->paddingTop = 0;
options->paddingRight = 0;
options->paddingLeft = 0;
options->type = FF_LOGO_TYPE_NONE;
}
else if(strcasecmp(value, "small") == 0)
{
options->type = FF_LOGO_TYPE_SMALL;
}
else
ffOptionParseString(key, value, &options->source);
}
else if(strcasecmp(subKey, "type") == 0)
{
options->type = (FFLogoType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "auto", FF_LOGO_TYPE_AUTO },
{ "builtin", FF_LOGO_TYPE_BUILTIN },
{ "small", FF_LOGO_TYPE_SMALL },
{ "file", FF_LOGO_TYPE_FILE },
{ "file-raw", FF_LOGO_TYPE_FILE_RAW },
{ "data", FF_LOGO_TYPE_DATA },
{ "data-raw", FF_LOGO_TYPE_DATA_RAW },
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
{ "none", FF_LOGO_TYPE_NONE },
{},
});
}
else if(ffStrStartsWithIgnCase(subKey, "color-") && subKey[6] != '\0' && subKey[7] == '\0') // matches "--logo-color-*"
{
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
int index = (int)subKey[6] - '0' - 1;
//Match only --logo-color-[1-9]
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
{
fprintf(stderr, "Error: invalid --color-[1-9] index: %c\n", key[13]);
exit(472);
}
if(value == NULL)
{
fprintf(stderr, "Error: usage: %s <str>\n", key);
exit(477);
}
ffOptionParseColor(value, &options->colors[index]);
}
else if(strcasecmp(subKey, "width") == 0)
options->width = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "height") == 0)
options->height = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "padding") == 0)
{
uint32_t padding = ffOptionParseUInt32(key, value);
options->paddingLeft = padding;
options->paddingRight = padding;
}
else if(strcasecmp(subKey, "padding-top") == 0)
options->paddingTop = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "padding-left") == 0)
options->paddingLeft = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "padding-right") == 0)
options->paddingRight = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "print-remaining") == 0)
options->printRemaining = ffOptionParseBoolean(value);
else if(strcasecmp(subKey, "preserve-aspect-radio") == 0)
options->preserveAspectRadio = ffOptionParseBoolean(value);
else if(strcasecmp(subKey, "recache") == 0)
options->recache = ffOptionParseBoolean(value);
else if(strcasecmp(subKey, "separate") == 0)
options->separate = ffOptionParseBoolean(value);
else
return false;
}
else if((subKey = ffOptionTestPrefix(key, "file")))
{
if(subKey[0] == '\0')
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_FILE;
}
else if(strcasecmp(subKey, "raw") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_FILE_RAW;
}
else
return false;
}
else if((subKey = ffOptionTestPrefix(key, "data")))
{
if(subKey[0] == '\0')
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_DATA;
}
else if(strcasecmp(subKey, "raw") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_DATA_RAW;
}
else
return false;
}
else if(strcasecmp(key, "--sixel") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_SIXEL;
}
else if(strcasecmp(key, "--kitty") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_KITTY;
}
else if(strcasecmp(key, "--kitty-direct") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_KITTY_DIRECT;
}
else if(strcasecmp(key, "--iterm") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_ITERM;
}
else if(strcasecmp(key, "--raw") == 0)
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_RAW;
}
else if((subKey = ffOptionTestPrefix(key, "chafa")))
{
if(subKey[0] == '\0')
{
ffOptionParseString(key, value, &options->source);
options->type = FF_LOGO_TYPE_IMAGE_CHAFA;
}
else if(strcasecmp(subKey, "fg-only") == 0)
options->chafaFgOnly = ffOptionParseBoolean(value);
else if(strcasecmp(subKey, "symbols") == 0)
ffOptionParseString(key, value, &options->chafaSymbols);
else if(strcasecmp(subKey, "canvas-mode") == 0)
options->chafaCanvasMode = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "color-space") == 0)
options->chafaColorSpace = ffOptionParseUInt32(key, value);
else if(strcasecmp(subKey, "dither-mode") == 0)
options->chafaDitherMode = ffOptionParseUInt32(key, value);
else
return false;
}
else
return false;
return true;
}
void ffDestroyLogoOptions(FFLogoOptions* options)
{
ffStrbufDestroy(&options->source);
ffStrbufDestroy(&options->chafaSymbols);
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufDestroy(&options->colors[i]);
}
const char* ffParseLogoJsonConfig(FFLogoOptions* options)
{
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
if (!yyjson_is_obj(root))
return "Invalid JSON config format. Root value must be an object";
yyjson_val* object = yyjson_obj_get(root, "logo");
if (!object) return NULL;
if (yyjson_is_null(object))
{
options->type = FF_LOGO_TYPE_NONE;
options->paddingTop = 0;
options->paddingRight = 0;
options->paddingLeft = 0;
return NULL;
}
if (yyjson_is_str(object))
{
const char* value = yyjson_get_str(object);
ffStrbufSetS(&options->source, value);
return NULL;
}
if (!yyjson_is_obj(object)) return "Property 'logo' must be an object";
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(object, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if (strcasecmp(key, "type") == 0)
{
int value;
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
{ "auto", FF_LOGO_TYPE_AUTO },
{ "builtin", FF_LOGO_TYPE_BUILTIN },
{ "small", FF_LOGO_TYPE_SMALL },
{ "file", FF_LOGO_TYPE_FILE },
{ "file-raw", FF_LOGO_TYPE_FILE_RAW },
{ "data", FF_LOGO_TYPE_DATA },
{ "data-raw", FF_LOGO_TYPE_DATA_RAW },
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
{ "iterm", FF_LOGO_TYPE_IMAGE_ITERM },
{ "chafa", FF_LOGO_TYPE_IMAGE_CHAFA },
{ "raw", FF_LOGO_TYPE_IMAGE_RAW },
{ "none", FF_LOGO_TYPE_NONE },
{},
});
if (error) return error;
options->type = (FFLogoType) value;
continue;
}
else if (strcasecmp(key, "source") == 0)
{
ffStrbufSetS(&options->source, yyjson_get_str(val));
continue;
}
else if (strcasecmp(key, "color") == 0)
{
if (!yyjson_is_obj(val))
return "Property 'color' must be an object";
yyjson_val *key_c, *valc;
size_t idxc, maxc;
yyjson_obj_foreach(val, idxc, maxc, key_c, valc)
{
const char* keyc = yyjson_get_str(key_c);
uint32_t index = (uint32_t) strtoul(keyc, NULL, 10);
if (index < 1 || index > FASTFETCH_LOGO_MAX_COLORS)
return "Keys of property 'color' must be a number between 1 to 9";
ffOptionParseColor(yyjson_get_str(valc), &options->colors[index - 1]);
}
continue;
}
else if (strcasecmp(key, "width") == 0)
{
uint32_t value = (uint32_t) yyjson_get_uint(val);
if (value == 0)
return "Logo width must be a possitive integer";
options->width = value;
continue;
}
else if (strcasecmp(key, "height") == 0)
{
uint32_t value = (uint32_t) yyjson_get_uint(val);
if (value == 0)
return "Logo height must be a possitive integer";
options->height = value;
continue;
}
else if (strcasecmp(key, "padding") == 0)
{
if (!yyjson_is_obj(val))
return "Logo padding must be an object";
#define FF_PARSE_PADDING_POSITON(pos, paddingPos) \
yyjson_val* pos = yyjson_obj_get(val, #pos); \
if (pos) \
{ \
if (!yyjson_is_uint(pos)) \
return "Logo padding values must be possitive integers"; \
options->paddingPos = (uint32_t) yyjson_get_uint(pos); \
}
FF_PARSE_PADDING_POSITON(left, paddingLeft);
FF_PARSE_PADDING_POSITON(top, paddingTop);
FF_PARSE_PADDING_POSITON(right, paddingRight);
#undef FF_PARSE_PADDING_POSITON
continue;
}
else if (strcasecmp(key, "printRemaining") == 0)
{
options->printRemaining = yyjson_get_bool(val);
continue;
}
else if (strcasecmp(key, "preserveAspectRadio") == 0)
{
options->preserveAspectRadio = yyjson_get_bool(val);
continue;
}
else if (strcasecmp(key, "recache") == 0)
{
options->recache = yyjson_get_bool(val);
continue;
}
else if (strcasecmp(key, "separate") == 0)
{
options->separate = yyjson_get_bool(val);
continue;
}
else if (strcasecmp(key, "chafa") == 0)
{
if (!yyjson_is_obj(val))
return "Chafa config must be an object";
yyjson_val* fgOnly = yyjson_obj_get(val, "fgOnly");
if (fgOnly)
options->chafaFgOnly = yyjson_get_bool(fgOnly);
yyjson_val* symbols = yyjson_obj_get(val, "symbols");
if (symbols)
ffStrbufAppendS(&options->chafaSymbols, yyjson_get_str(symbols));
yyjson_val* canvasMode = yyjson_obj_get(val, "canvasMode");
if (canvasMode)
{
int value;
const char* error = ffJsonConfigParseEnum(canvasMode, &value, (FFKeyValuePair[]) {
{ "TRUECOLOR", 0 },
{ "INDEXED_256", 1 },
{ "INDEXED_240", 2 },
{ "INDEXED_16", 3 },
{ "FGBG_BGFG", 4 },
{ "FGBG", 5 },
{ "INDEXED_8", 6 },
{ "INDEXED_16_8", 7 },
{},
});
if (error) return error;
options->chafaCanvasMode = (uint32_t) value;
}
yyjson_val* colorSpace = yyjson_obj_get(val, "colorSpace");
if (colorSpace)
{
int value;
const char* error = ffJsonConfigParseEnum(colorSpace, &value, (FFKeyValuePair[]) {
{ "RGB", 0 },
{ "DIN99D", 1 },
{},
});
if (error) return error;
options->chafaColorSpace = (uint32_t) value;
}
yyjson_val* ditherMode = yyjson_obj_get(val, "ditherMode");
if (ditherMode)
{
int value;
const char* error = ffJsonConfigParseEnum(ditherMode, &value, (FFKeyValuePair[]) {
{ "NONE", 0 },
{ "ORDERED", 1 },
{ "DIFFUSION", 2 },
{},
});
if (error) return error;
options->chafaDitherMode = (uint32_t) value;
}
continue;
}
else
return "Unknown logo key";
}
return NULL;
}
void ffGenerateLogoJsonConfig(FFLogoOptions* options, yyjson_mut_doc* doc)
{
__attribute__((__cleanup__(ffDestroyLogoOptions))) FFLogoOptions defaultOptions;
ffInitLogoOptions(&defaultOptions);
yyjson_mut_val* obj = yyjson_mut_obj(doc);
if (options->type != defaultOptions.type)
{
switch (options->type)
{
case FF_LOGO_TYPE_NONE:
yyjson_mut_obj_add_null(doc, doc->root, "logo");
return;
case FF_LOGO_TYPE_BUILTIN:
yyjson_mut_obj_add_str(doc, obj, "type", "builtin");
break;
case FF_LOGO_TYPE_SMALL:
yyjson_mut_obj_add_str(doc, obj, "type", "small");
break;
case FF_LOGO_TYPE_FILE:
yyjson_mut_obj_add_str(doc, obj, "type", "file");
break;
case FF_LOGO_TYPE_FILE_RAW:
yyjson_mut_obj_add_str(doc, obj, "type", "file-raw");
break;
case FF_LOGO_TYPE_DATA:
yyjson_mut_obj_add_str(doc, obj, "type", "data");
break;
case FF_LOGO_TYPE_DATA_RAW:
yyjson_mut_obj_add_str(doc, obj, "type", "data-raw");
break;
case FF_LOGO_TYPE_IMAGE_SIXEL:
yyjson_mut_obj_add_str(doc, obj, "type", "sixel");
break;
case FF_LOGO_TYPE_IMAGE_KITTY:
yyjson_mut_obj_add_str(doc, obj, "type", "kitty");
break;
case FF_LOGO_TYPE_IMAGE_ITERM:
yyjson_mut_obj_add_str(doc, obj, "type", "iterm");
break;
case FF_LOGO_TYPE_IMAGE_CHAFA:
yyjson_mut_obj_add_str(doc, obj, "type", "chafa");
break;
case FF_LOGO_TYPE_IMAGE_RAW:
yyjson_mut_obj_add_str(doc, obj, "type", "raw");
break;
default:
yyjson_mut_obj_add_str(doc, obj, "type", "auto");
break;
}
}
if (!ffStrbufEqual(&options->source, &defaultOptions.source))
yyjson_mut_obj_add_str(doc, obj, "source", options->source.chars);
{
yyjson_mut_val* color = yyjson_mut_arr(doc);
for (int i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
{
if (!ffStrbufEqual(&options->colors[i], &defaultOptions.colors[i]))
yyjson_mut_arr_add_strbuf(doc, color, &options->colors[i]);
}
if (yyjson_mut_arr_size(color) > 0)
yyjson_mut_obj_add_val(doc, obj, "color", color);
}
if (options->width != defaultOptions.width)
yyjson_mut_obj_add_uint(doc, obj, "width", options->width);
if (options->height != defaultOptions.height)
yyjson_mut_obj_add_uint(doc, obj, "height", options->height);
{
yyjson_mut_val* padding = yyjson_mut_obj(doc);
if (options->paddingTop != defaultOptions.paddingTop)
yyjson_mut_obj_add_uint(doc, padding, "top", options->paddingTop);
if (options->paddingLeft != defaultOptions.paddingLeft)
yyjson_mut_obj_add_uint(doc, padding, "left", options->paddingLeft);
if (options->paddingRight != defaultOptions.paddingRight)
yyjson_mut_obj_add_uint(doc, padding, "right", options->paddingRight);
if (yyjson_mut_obj_size(padding) > 0)
yyjson_mut_obj_add_val(doc, obj, "padding", padding);
}
if (options->printRemaining != defaultOptions.printRemaining)
yyjson_mut_obj_add_bool(doc, obj, "printRemaining", options->printRemaining);
if (options->preserveAspectRadio != defaultOptions.preserveAspectRadio)
yyjson_mut_obj_add_bool(doc, obj, "preserveAspectRadio", options->preserveAspectRadio);
if (options->recache != defaultOptions.recache)
yyjson_mut_obj_add_bool(doc, obj, "recache", options->recache);
if (options->separate != defaultOptions.separate)
yyjson_mut_obj_add_bool(doc, obj, "separate", options->separate);
{
yyjson_mut_val* chafa = yyjson_mut_obj(doc);
if (options->chafaFgOnly != defaultOptions.chafaFgOnly)
yyjson_mut_obj_add_bool(doc, chafa, "fgOnly", options->chafaFgOnly);
if (!ffStrbufEqual(&options->chafaSymbols, &defaultOptions.chafaSymbols))
yyjson_mut_obj_add_strbuf(doc, chafa, "symbols", &options->chafaSymbols);
if (options->chafaCanvasMode != defaultOptions.chafaCanvasMode && options->chafaCanvasMode <= 7)
{
yyjson_mut_obj_add_str(doc, chafa, "canvasMode", ((const char* []) {
"TRUECOLOR",
"INDEXED_256",
"INDEXED_240",
"INDEXED_16",
"FGBG_BGFG",
"FGBG",
"INDEXED_8",
"INDEXED_16_8",
})[options->chafaCanvasMode]);
}
if (options->chafaColorSpace != defaultOptions.chafaColorSpace && options->chafaColorSpace <= 1)
{
yyjson_mut_obj_add_str(doc, chafa, "colorSpace", ((const char* []) {
"RGB",
"DIN99D",
})[options->chafaColorSpace]);
}
if (options->chafaDitherMode != defaultOptions.chafaDitherMode && options->chafaDitherMode <= 2)
{
yyjson_mut_obj_add_str(doc, chafa, "ditherMode", ((const char* []) {
"NONE",
"ORDERED",
"DIFFUSION",
})[options->chafaDitherMode]);
}
if (yyjson_mut_obj_size(chafa) > 0)
yyjson_mut_obj_add_val(doc, obj, "chafa", chafa);
}
if (yyjson_mut_obj_size(obj) > 0)
yyjson_mut_obj_add_val(doc, doc->root, "logo", obj);
}
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#include "util/FFstrbuf.h"
#define FASTFETCH_LOGO_MAX_NAMES 9
#define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9)
typedef enum FFLogoType
{
FF_LOGO_TYPE_AUTO, //if something is given, first try builtin, then file. Otherwise detect logo
FF_LOGO_TYPE_BUILTIN, //builtin ascii art
FF_LOGO_TYPE_SMALL, //builtin ascii art, small version
FF_LOGO_TYPE_FILE, //text file, printed with color code replacement
FF_LOGO_TYPE_FILE_RAW, //text file, printed as is
FF_LOGO_TYPE_DATA, //text data, printed with color code replacement
FF_LOGO_TYPE_DATA_RAW, //text data, printed as is
FF_LOGO_TYPE_IMAGE_SIXEL, //image file, printed as sixel codes.
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
FF_LOGO_TYPE_IMAGE_KITTY_DIRECT, //image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)
FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol
FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa
FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string
FF_LOGO_TYPE_NONE, //--logo none
} FFLogoType;
typedef struct FFLogoOptions
{
FFstrbuf source;
FFLogoType type;
FFstrbuf colors[FASTFETCH_LOGO_MAX_COLORS];
uint32_t width;
uint32_t height;
uint32_t paddingTop;
uint32_t paddingLeft;
uint32_t paddingRight;
bool printRemaining;
bool preserveAspectRadio;
bool recache;
bool separate;
bool chafaFgOnly;
FFstrbuf chafaSymbols;
uint32_t chafaCanvasMode;
uint32_t chafaColorSpace;
uint32_t chafaDitherMode;
} FFLogoOptions;
+98
View File
@@ -0,0 +1,98 @@
#include "fastfetch.h"
#include "util/stringUtils.h"
#include "options/general.h"
#include <unistd.h>
const char* ffParseGeneralJsonConfig(FFGeneralOptions* options, yyjson_val* root)
{
yyjson_val* object = yyjson_obj_get(root, "general");
if (!object) return NULL;
if (!yyjson_is_obj(object)) return "Property 'general' must be an object";
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(object, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "allowSlowOperations"))
options->allowSlowOperations = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
options->multithreading = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
options->processingTimeout = (int32_t) yyjson_get_int(val);
#if defined(__linux__) || defined(__FreeBSD__)
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
options->escapeBedrock = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "playerName"))
ffStrbufSetS(&options->playerName, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "osFile"))
ffStrbufSetS(&options->osFile, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
options->dsForceDrm = yyjson_get_bool(val);
#elif defined(_WIN32)
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
options->wmiTimeout = (int32_t) yyjson_get_int(val);
#endif
else
return "Unknown general property";
}
return NULL;
}
bool ffParseGeneralCommandOptions(FFGeneralOptions* options, const char* key, const char* value)
{
if(ffStrEqualsIgnCase(key, "--allow-slow-operations"))
options->allowSlowOperations = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--thread") || ffStrEqualsIgnCase(key, "--multithreading"))
options->multithreading = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--processing-timeout"))
options->processingTimeout = ffOptionParseInt32(key, value);
#if defined(__linux__) || defined(__FreeBSD__)
else if(ffStrEqualsIgnCase(key, "--escape-bedrock"))
options->escapeBedrock = ffOptionParseBoolean(value);
else if(ffStrEqualsIgnCase(key, "--player-name"))
ffOptionParseString(key, value, &options->playerName);
else if (ffStrEqualsIgnCase(key, "--os-file"))
ffOptionParseString(key, value, &options->osFile);
else if(ffStrEqualsIgnCase(key, "--ds-force-drm"))
options->dsForceDrm = ffOptionParseBoolean(value);
#elif defined(_WIN32)
else if (ffStrEqualsIgnCase(key, "--wmi-timeout"))
options->wmiTimeout = ffOptionParseInt32(key, value);
#endif
else
return false;
return true;
}
void ffInitGeneralOptions(FFGeneralOptions* options)
{
options->processingTimeout = 1000;
options->allowSlowOperations = false;
options->multithreading = true;
#if defined(__linux__) || defined(__FreeBSD__)
options->escapeBedrock = true;
ffStrbufInit(&options->playerName);
ffStrbufInit(&options->osFile);
options->dsForceDrm = false;
#elif defined(_WIN32)
options->wmiTimeout = 5000;
#endif
}
void ffDestroyGeneralOptions(FF_MAYBE_UNUSED FFGeneralOptions* options)
{
#if defined(__linux__) || defined(__FreeBSD__)
ffStrbufDestroy(&options->playerName);
ffStrbufDestroy(&options->osFile);
#endif
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "util/FFstrbuf.h"
typedef struct FFGeneralOptions
{
bool allowSlowOperations;
bool multithreading;
int32_t processingTimeout;
// Module options that cannot be put in module option structure
#if defined(__linux__) || defined(__FreeBSD__)
FFstrbuf playerName;
FFstrbuf osFile;
bool escapeBedrock;
bool dsForceDrm;
#elif defined(_WIN32)
int32_t wmiTimeout;
#endif
} FFGeneralOptions;
const char* ffParseGeneralJsonConfig(FFGeneralOptions* options, yyjson_val* root);
bool ffParseGeneralCommandOptions(FFGeneralOptions* options, const char* key, const char* value);
void ffInitGeneralOptions(FFGeneralOptions* options);
void ffDestroyGeneralOptions(FFGeneralOptions* options);
+1 -7
View File
@@ -211,14 +211,8 @@ void ffDestroyLogoOptions(FFLogoOptions* options)
ffStrbufDestroy(&options->colors[i]);
}
const char* ffParseLogoJsonConfig(FFLogoOptions* options)
const char* ffParseLogoJsonConfig(FFLogoOptions* options, yyjson_val* root)
{
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
assert(root);
if (!yyjson_is_obj(root))
return "Invalid JSON config format. Root value must be an object";
yyjson_val* object = yyjson_obj_get(root, "logo");
if (!object) return NULL;
if (yyjson_is_null(object))
+1 -1
View File
@@ -48,5 +48,5 @@ typedef struct FFLogoOptions
void ffInitLogoOptions(FFLogoOptions* options);
bool ffParseLogoCommandOptions(FFLogoOptions* options, const char* key, const char* value);
void ffDestroyLogoOptions(FFLogoOptions* options);
const char* ffParseLogoJsonConfig(FFLogoOptions* options);
const char* ffParseLogoJsonConfig(FFLogoOptions* options, yyjson_val* root);
void ffGenerateLogoJsonConfig(FFLogoOptions* options, yyjson_mut_doc* doc);
+1 -1
View File
@@ -162,7 +162,7 @@ struct FFWmiRecord
if(!pEnumerator) return;
ULONG ret;
bool ok = SUCCEEDED(pEnumerator->Next(instance.config.wmiTimeout, 1, &obj, &ret)) && ret;
bool ok = SUCCEEDED(pEnumerator->Next(instance.config.general.wmiTimeout, 1, &obj, &ret)) && ret;
if(!ok) obj = nullptr;
}
FFWmiRecord(const FFWmiRecord&) = delete;