diff --git a/Makefile b/Makefile index f4f5088..789dfe1 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 nodes/router.o nodes/modifiers.o nodes/modify_predicate.o nodes/uinput.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 nodes/modifiers.o nodes/modify_predicate.o nodes/uinput.o nodes/assign.o all: $(MAIN) diff --git a/nodes/assign.c b/nodes/assign.c new file mode 100644 index 0000000..c680ea3 --- /dev/null +++ b/nodes/assign.c @@ -0,0 +1,120 @@ +#include "../graph.h" +#include "../module_registry.h" + +typedef struct { + GraphNode as_GraphNode; + bool has_ns, has_maj, has_min, has_payload; + EventData source; +} AssignGraphNode; + +static bool +handle_event(EventPositionBase * self, EventNode * event) +{ + AssignGraphNode *node = DOWNCAST(AssignGraphNode, GraphNode, DOWNCAST(GraphNode, EventPositionBase, self)); + size_t count = node->as_GraphNode.outputs.length; + if (!count) { + event_destroy(event); + return true; + } + + if (node->has_ns) { + event->data.code.ns = node->source.code.ns; + } + if (node->has_maj) { + event->data.code.major = node->source.code.major; + } + if (node->has_min) { + event->data.code.minor = node->source.code.minor; + } + if (node->has_payload) { + event->data.payload = node->source.payload; + } + + if (count > 1) { + count = event_replicate(event, count - 1) + 1; + } + for (size_t i = 0; i < count; ++i) { + event->position = &node->as_GraphNode.outputs.elements[i]->as_EventPositionBase; + event = event->next; + } + return true; +} + +static GraphNode * +create(GraphNodeSpecification * spec, GraphNodeConfig * config, InitializationEnvironment * env) +{ + (void) config; + (void) env; + AssignGraphNode * node = T_ALLOC(1, AssignGraphNode); + if (!node) { + return NULL; + } + + EventData source; + bool + has_ns = false, + has_maj = false, + has_min = false, + has_payload = false; + const config_setting_t *setting; + + if ((setting = config_setting_get_member(config->options, "namespace"))) { + has_ns = true; + source.code.ns = env_resolve_constant(env, setting); + } + if ((setting = config_setting_get_member(config->options, "major"))) { + has_maj = true; + source.code.major = env_resolve_constant(env, setting); + } + if ((setting = config_setting_get_member(config->options, "minor"))) { + has_min = true; + source.code.minor = env_resolve_constant(env, setting); + } + if ((setting = config_setting_get_member(config->options, "payload"))) { + has_payload = true; + source.payload = env_resolve_constant(env, setting); + } + + *node = (AssignGraphNode) { + .as_GraphNode = { + .as_EventPositionBase = { + .handle_event = &handle_event, + .waiting_new_event = false, + }, + .specification = spec, + .inputs = EMPTY_GRAPH_CHANNEL_LIST, + .outputs = EMPTY_GRAPH_CHANNEL_LIST, + }, + .has_ns = has_ns, + .has_maj = has_maj, + .has_min = has_min, + .has_payload = has_payload, + .source = source, + }; + return &node->as_GraphNode; +} + +static void destroy +(GraphNodeSpecification * self, GraphNode * target) +{ + (void) self; + free(target); +} + +GraphNodeSpecification nodespec_assign = (GraphNodeSpecification) { + .create = &create, + .destroy = &destroy, + .register_io = NULL, + .name = "assign", + .documentation = "Assigns field(s) in an event\nAccepts events on any connector\nSends events on all connectors" + "\nOption 'namespace' (optional): new event code namespace" + "\nOption 'major' (optional): new event code major" + "\nOption 'minor' (optional): new event code minor" + "\nOption 'payload' (optional): new event payload" + , +}; + +MODULE_CONSTRUCTOR(init) +{ + register_graph_node_specification(&nodespec_assign); +}