diff --git a/doc/json_schema.json b/doc/json_schema.json index 071695dba..d32269bd2 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -2636,6 +2636,15 @@ "const": "gamepad", "description": "List connected gamepads" }, + "ignores": { + "type": "array", + "description": "An array of case-insensitive device name prefixes to ignore", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, "percent": { "$ref": "#/$defs/percent" }, @@ -2895,6 +2904,15 @@ "const": "keyboard", "description": "List (connected) keyboards" }, + "ignores": { + "type": "array", + "description": "An array of case-insensitive device name prefixes to ignore", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, "key": { "$ref": "#/$defs/key" }, @@ -3218,6 +3236,15 @@ "const": "mouse", "description": "List connected mouses" }, + "ignores": { + "type": "array", + "description": "An array of case-insensitive device name prefixes to ignore", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, "key": { "$ref": "#/$defs/key" }, diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 087e7dc35..ce0c6079a 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -68,10 +68,40 @@ bool ffPrintGamepad(FFGamepadOptions* options) return false; } - uint8_t index = 0; + FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFGamepadDevice*)); + FF_LIST_FOR_EACH(FFGamepadDevice, device, result) + { + bool ignored = false; + FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores) + { + if(ffStrbufStartsWithIgnCase(&device->name, ignore)) + { + ignored = true; + break; + } + } + if(!ignored) + { + FFGamepadDevice** ptr = ffListAdd(&filtered); + *ptr = device; + } + } + + if(!filtered.length) + { + ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + return false; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFGamepadDevice*, pdevice, filtered) + { + FFGamepadDevice* device = *pdevice; + printDevice(options, device, filtered.length > 1 ? ++index : 0); + } + FF_LIST_FOR_EACH(FFGamepadDevice, device, result) { - printDevice(options, device, result.length > 1 ? ++index : 0); ffStrbufDestroy(&device->serial); ffStrbufDestroy(&device->name); } @@ -88,6 +118,21 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (unsafe_yyjson_equals_str(key, "ignores")) + { + yyjson_val *elem; + size_t eidx, emax; + yyjson_arr_foreach(val, eidx, emax, elem) + { + if (yyjson_is_str(elem)) + { + FFstrbuf* strbuf = ffListAdd(&options->ignores); + ffStrbufInitJsonVal(strbuf, elem); + } + } + continue; + } + if (ffPercentParseJsonObject(key, val, &options->percent)) continue; @@ -99,6 +144,12 @@ void ffGenerateGamepadJsonConfig(FFGamepadOptions* options, yyjson_mut_doc* doc, { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + if (options->ignores.length > 0) + { + yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores"); + FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores) + yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length)); + } ffPercentGenerateJsonConfig(doc, module, options->percent); } @@ -120,6 +171,17 @@ bool ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + + bool ignored = false; + FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores) + { + if(ffStrbufStartsWithIgnCase(&device->name, ignore)) + { + ignored = true; + break; + } + } + yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored); } FF_LIST_FOR_EACH(FFGamepadDevice, device, result) @@ -134,12 +196,18 @@ bool ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs void ffInitGamepadOptions(FFGamepadOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰺵"); + + ffListInit(&options->ignores, sizeof(FFstrbuf)); options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; } void ffDestroyGamepadOptions(FFGamepadOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); + + FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores) + ffStrbufDestroy(str); + ffListDestroy(&options->ignores); } FFModuleBaseInfo ffGamepadModuleInfo = { diff --git a/src/modules/gamepad/option.h b/src/modules/gamepad/option.h index 8640a0d7c..b52b1dea3 100644 --- a/src/modules/gamepad/option.h +++ b/src/modules/gamepad/option.h @@ -1,11 +1,13 @@ #pragma once #include "common/option.h" +#include "util/FFlist.h" typedef struct FFGamepadOptions { FFModuleArgs moduleArgs; + FFlist ignores; // List of FFstrbuf FFPercentageModuleConfig percent; } FFGamepadOptions; diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index c02c8653b..57f27ad43 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -39,10 +39,36 @@ bool ffPrintKeyboard(FFKeyboardOptions* options) return false; } - uint8_t index = 0; + FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFKeyboardDevice*)); FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) { - printDevice(options, device, result.length > 1 ? ++index : 0); + bool ignored = false; + FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores) + { + if(ffStrbufStartsWithIgnCase(&device->name, ignore)) + { + ignored = true; + break; + } + } + if(!ignored) + { + FFKeyboardDevice** ptr = ffListAdd(&filtered); + *ptr = device; + } + } + + if(!filtered.length) + { + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + return false; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFKeyboardDevice*, pdevice, filtered) + { + FFKeyboardDevice* device = *pdevice; + printDevice(options, device, filtered.length > 1 ? ++index : 0); ffStrbufDestroy(&device->serial); ffStrbufDestroy(&device->name); } @@ -59,6 +85,21 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (unsafe_yyjson_equals_str(key, "ignores")) + { + yyjson_val *elem; + size_t eidx, emax; + yyjson_arr_foreach(val, eidx, emax, elem) + { + if (yyjson_is_str(elem)) + { + FFstrbuf* strbuf = ffListAdd(&options->ignores); + ffStrbufInitJsonVal(strbuf, elem); + } + } + continue; + } + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -66,6 +107,13 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) void ffGenerateKeyboardJsonConfig(FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + + if (options->ignores.length > 0) + { + yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores"); + FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores) + yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length)); + } } bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -86,6 +134,17 @@ bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + + bool ignored = false; + FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores) + { + if(ffStrbufStartsWithIgnCase(&device->name, ignore)) + { + ignored = true; + break; + } + } + yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored); } FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) @@ -100,11 +159,17 @@ bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy void ffInitKeyboardOptions(FFKeyboardOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, ""); + + ffListInit(&options->ignores, sizeof(FFstrbuf)); } void ffDestroyKeyboardOptions(FFKeyboardOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); + + FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores) + ffStrbufDestroy(str); + ffListDestroy(&options->ignores); } FFModuleBaseInfo ffKeyboardModuleInfo = { diff --git a/src/modules/keyboard/option.h b/src/modules/keyboard/option.h index b65de5ceb..6f5244a6a 100644 --- a/src/modules/keyboard/option.h +++ b/src/modules/keyboard/option.h @@ -1,10 +1,13 @@ #pragma once #include "common/option.h" +#include "util/FFlist.h" typedef struct FFKeyboardOptions { FFModuleArgs moduleArgs; + + FFlist ignores; // List of FFstrbuf } FFKeyboardOptions; static_assert(sizeof(FFKeyboardOptions) <= FF_OPTION_MAX_SIZE, "FFKeyboardOptions size exceeds maximum allowed size"); diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index f7afcccb0..9789399fe 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -39,10 +39,36 @@ bool ffPrintMouse(FFMouseOptions* options) return false; } - uint8_t index = 0; + FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFMouseDevice*)); FF_LIST_FOR_EACH(FFMouseDevice, device, result) { - printDevice(options, device, result.length > 1 ? ++index : 0); + bool ignored = false; + FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores) + { + if(ffStrbufStartsWithIgnCase(&device->name, ignore)) + { + ignored = true; + break; + } + } + if(!ignored) + { + FFMouseDevice** ptr = ffListAdd(&filtered); + *ptr = device; + } + } + + if(!filtered.length) + { + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + return false; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFMouseDevice*, pdevice, filtered) + { + FFMouseDevice* device = *pdevice; + printDevice(options, device, filtered.length > 1 ? ++index : 0); ffStrbufDestroy(&device->serial); ffStrbufDestroy(&device->name); } @@ -59,6 +85,21 @@ void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (unsafe_yyjson_equals_str(key, "ignores")) + { + yyjson_val *elem; + size_t eidx, emax; + yyjson_arr_foreach(val, eidx, emax, elem) + { + if (yyjson_is_str(elem)) + { + FFstrbuf* strbuf = ffListAdd(&options->ignores); + ffStrbufInitJsonVal(strbuf, elem); + } + } + continue; + } + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -66,6 +107,13 @@ void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) void ffGenerateMouseJsonConfig(FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + + if (options->ignores.length > 0) + { + yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores"); + FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores) + yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length)); + } } bool ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -86,6 +134,17 @@ bool ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_m yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + + bool ignored = false; + FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores) + { + if(ffStrbufStartsWithIgnCase(&device->name, ignore)) + { + ignored = true; + break; + } + } + yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored); } FF_LIST_FOR_EACH(FFMouseDevice, device, result) @@ -100,11 +159,17 @@ bool ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_m void ffInitMouseOptions(FFMouseOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍽"); + + ffListInit(&options->ignores, sizeof(FFstrbuf)); } void ffDestroyMouseOptions(FFMouseOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); + + FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores) + ffStrbufDestroy(str); + ffListDestroy(&options->ignores); } FFModuleBaseInfo ffMouseModuleInfo = { diff --git a/src/modules/mouse/option.h b/src/modules/mouse/option.h index 470104d3f..dcb5331f7 100644 --- a/src/modules/mouse/option.h +++ b/src/modules/mouse/option.h @@ -1,10 +1,13 @@ #pragma once #include "common/option.h" +#include "util/FFlist.h" typedef struct FFMouseOptions { FFModuleArgs moduleArgs; + + FFlist ignores; // List of FFstrbuf } FFMouseOptions; static_assert(sizeof(FFMouseOptions) <= FF_OPTION_MAX_SIZE, "FFMouseOptions size exceeds maximum allowed size");