From a46131716ed30fa60bdd846f0f349eeae3f1d6fc Mon Sep 17 00:00:00 2001 From: Vftdan Date: Sat, 17 Aug 2024 11:35:36 +0200 Subject: [PATCH] Add "router" node type --- Makefile | 2 +- config.cfg | 13 +++++-- nodes/router.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 nodes/router.c diff --git a/Makefile b/Makefile index 4bdd068..f8cb4e7 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS)) LDLIBS += $(shell pkg-config --libs $(DEPS)) INTERP ?= MAIN = main -OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o +OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o nodes/router.o all: $(MAIN) diff --git a/config.cfg b/config.cfg index b5df3f7..dff3e35 100644 --- a/config.cfg +++ b/config.cfg @@ -39,14 +39,23 @@ nodes = { namespace = "namespaces.clickpad"; }; }; + select_key_events = { + type = "router"; + options = { + predicates = ["key_event"]; + }; + }; }; channels = ({ from: ("stdin", 0); - to: ("print", 0); + to: ("select_key_events", 0); }, { from: ("clickpad", 0); - to: ("print", 1); + to: ("select_key_events", 1); +}, { + from: ("select_key_events", 0); + to: ("print", 0); }); // vim: ft=libconfig diff --git a/nodes/router.c b/nodes/router.c new file mode 100644 index 0000000..109c3b3 --- /dev/null +++ b/nodes/router.c @@ -0,0 +1,96 @@ +#include "../graph.h" +#include "../module_registry.h" + +typedef struct { + GraphNode as_GraphNode; + size_t length; + EventPredicateHandle * predicates; +} RouterGraphNode; + +static bool +handle_event(EventPositionBase * self, EventNode * event) +{ + RouterGraphNode *node = DOWNCAST(RouterGraphNode, GraphNode, DOWNCAST(GraphNode, EventPositionBase, self)); + for (size_t i = 0; i < node->length; ++i) { + if (i >= node->as_GraphNode.outputs.length) { + break; + } + if (event_predicate_apply(node->predicates[i], event) == EVPREDRES_ACCEPTED) { + if (event_replicate(event, 1)) { + event->next->position = &node->as_GraphNode.outputs.elements[i]->as_EventPositionBase; + } + } + } + event_destroy(event); + return true; +} + +static GraphNode * +create(GraphNodeSpecification * spec, GraphNodeConfig * config, InitializationEnvironment * env) +{ + (void) config; + (void) env; + RouterGraphNode * node = T_ALLOC(1, RouterGraphNode); + if (!node) { + return NULL; + } + + config_setting_t *predicates_setting = config_setting_get_member(config->options, "predicates"); + if (!predicates_setting) { + free(node); + return NULL; + } + + EventPredicateHandle *predicates = NULL; + size_t length = config_setting_length(predicates_setting); + if (length > 0) { + predicates = T_ALLOC(length, EventPredicateHandle); + if (!predicates) { + free(node); + return NULL; + } + for (size_t i = 0; i < length; ++i) { + predicates[i] = env_resolve_event_predicate(env, config_setting_get_elem(predicates_setting, i)); + } + } + + *node = (RouterGraphNode) { + .as_GraphNode = { + .as_EventPositionBase = { + .handle_event = &handle_event, + .waiting_new_event = false, + }, + .specification = spec, + .inputs = EMPTY_GRAPH_CHANNEL_LIST, + .outputs = EMPTY_GRAPH_CHANNEL_LIST, + }, + .length = length, + .predicates = predicates, + }; + return &node->as_GraphNode; +} + +static void destroy +(GraphNodeSpecification * self, GraphNode * target) +{ + (void) self; + RouterGraphNode * node = DOWNCAST(RouterGraphNode, GraphNode, target); + if (node->predicates) { + free(node->predicates); + node->predicates = NULL; + node->length = 0; + } + free(target); +} + +GraphNodeSpecification nodespec_router = (GraphNodeSpecification) { + .create = &create, + .destroy = &destroy, + .register_io = NULL, + .name = "router", +}; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_router); +}