Compare commits
No commits in common. "e2ea8fed1edc0759b648ec62b7deaa10df17db50" and "f76eaa53f25e0f4a7313a90156260e03118ad4c1" have entirely different histories.
e2ea8fed1e
...
f76eaa53f2
1
graph.h
1
graph.h
|
@ -33,7 +33,6 @@ struct graph_node_specification {
|
||||||
void (*destroy)(GraphNodeSpecification * self, GraphNode * target);
|
void (*destroy)(GraphNodeSpecification * self, GraphNode * target);
|
||||||
void (*register_io)(GraphNodeSpecification * self, GraphNode * target, ProcessingState * state);
|
void (*register_io)(GraphNodeSpecification * self, GraphNode * target, ProcessingState * state);
|
||||||
char *name;
|
char *name;
|
||||||
char *documentation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void graph_channel_init(GraphChannel * ch, GraphNode * start, size_t start_idx, GraphNode * end, size_t end_idx);
|
void graph_channel_init(GraphChannel * ch, GraphNode * start, size_t start_idx, GraphNode * end, size_t end_idx);
|
||||||
|
|
84
main.c
84
main.c
|
@ -1,89 +1,12 @@
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "processing.h"
|
#include "processing.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
#include "module_registry.h"
|
#include "module_registry.h"
|
||||||
|
|
||||||
union __attribute__((transparent_union)) option_ident {
|
|
||||||
enum {
|
|
||||||
NCOPT_BASE = 0xFF,
|
|
||||||
NCOPT_MODULE_HELP,
|
|
||||||
} as_nonchar;
|
|
||||||
int as_int;
|
|
||||||
// No "as_char" field, because it can cause problems on big-endian CPUs
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char ** argv)
|
main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
const char* config_filename = "config.cfg";
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
while (true) {
|
|
||||||
static const struct option long_options [] = {
|
|
||||||
{"config", required_argument, NULL, 'c'},
|
|
||||||
{"help", no_argument, NULL, 'h'},
|
|
||||||
{"list-modules", no_argument, NULL, 'l'},
|
|
||||||
{"module-help", required_argument, NULL, NCOPT_MODULE_HELP},
|
|
||||||
{NULL, 0, NULL, 0}};
|
|
||||||
static const char help_fstring[] =
|
|
||||||
"Usage: %s <[options...]>\n"
|
|
||||||
"Options:\n"
|
|
||||||
"\t--config <filename>, -c <filename> read configuration from <filename>\n"
|
|
||||||
"\t instead of ./config.cfg\n"
|
|
||||||
"\t--help, -h show this message\n"
|
|
||||||
"\t--list-modules, -l list currently loaded node types\n"
|
|
||||||
"\t--module-help <name> print help information provided for node type <name>\n"
|
|
||||||
;
|
|
||||||
|
|
||||||
union option_ident opt = {.as_int = getopt_long(argc, argv, "c:hl", long_options, NULL)};
|
|
||||||
if (opt.as_int < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (opt.as_int) {
|
|
||||||
case 'c':
|
|
||||||
config_filename = optarg;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
printf(help_fstring, argv[0]);
|
|
||||||
return 0;
|
|
||||||
case 'l':
|
|
||||||
{
|
|
||||||
const GraphNodeSpecificationRegistry * reg = get_graph_node_specification_registy();
|
|
||||||
for (size_t i = 0; i < reg->capacity; ++i) {
|
|
||||||
if (!reg->key_array[i].key.bytes) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("%.*s\n", (int) reg->key_array[i].key.length, reg->key_array[i].key.bytes);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return 0;
|
|
||||||
case NCOPT_MODULE_HELP:
|
|
||||||
{
|
|
||||||
GraphNodeSpecification *spec = lookup_graph_node_specification(optarg);
|
|
||||||
if (!spec) {
|
|
||||||
fprintf(stderr, "Unknown node type \"%s\"\n", optarg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
const char* module_help = spec->documentation;
|
|
||||||
if (module_help) {
|
|
||||||
printf("Help for node type \"%s\":\n", optarg);
|
|
||||||
printf("%s\n", module_help);
|
|
||||||
} else {
|
|
||||||
printf("No help provided for node type \"%s\"\n", optarg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Unexpected option ");
|
|
||||||
if ((unsigned int) opt.as_int <= 0xFF) {
|
|
||||||
fprintf(stderr, "'%c'\n", (char) opt.as_int);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "%d\n", opt.as_int);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessingState state = (ProcessingState) {
|
ProcessingState state = (ProcessingState) {
|
||||||
.wait_delay = NULL,
|
.wait_delay = NULL,
|
||||||
|
@ -95,7 +18,7 @@ main(int argc, char ** argv)
|
||||||
config_t config_tree;
|
config_t config_tree;
|
||||||
FullConfig loaded_config;
|
FullConfig loaded_config;
|
||||||
config_init(&config_tree);
|
config_init(&config_tree);
|
||||||
config_read_file(&config_tree, config_filename);
|
config_read_file(&config_tree, "config.cfg");
|
||||||
config_set_auto_convert(&config_tree, CONFIG_TRUE);
|
config_set_auto_convert(&config_tree, CONFIG_TRUE);
|
||||||
if (!load_config(config_root_setting(&config_tree), &loaded_config)) {
|
if (!load_config(config_root_setting(&config_tree), &loaded_config)) {
|
||||||
perror("Failed to load config");
|
perror("Failed to load config");
|
||||||
|
@ -169,5 +92,6 @@ main(int argc, char ** argv)
|
||||||
|
|
||||||
io_subscription_list_deinit(&state.wait_output);
|
io_subscription_list_deinit(&state.wait_output);
|
||||||
io_subscription_list_deinit(&state.wait_input);
|
io_subscription_list_deinit(&state.wait_input);
|
||||||
|
destroy_graph_node_specification_registry();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ modifier_operation_parse(const char* name)
|
||||||
if (strcmp(name, "reset") == 0) {
|
if (strcmp(name, "reset") == 0) {
|
||||||
return MODOP_UNSET;
|
return MODOP_UNSET;
|
||||||
}
|
}
|
||||||
if (strcmp(name, "toggle") == 0) {
|
if (strcmp(name, "togggle") == 0) {
|
||||||
return MODOP_TOGGLE;
|
return MODOP_TOGGLE;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "module_registry.h"
|
#include "module_registry.h"
|
||||||
|
#include "hash_table.h"
|
||||||
|
|
||||||
static GraphNodeSpecificationRegistry registry;
|
static TYPED_HASH_TABLE(GraphNodeSpecification*) registry;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -33,14 +34,7 @@ lookup_graph_node_specification(const char * name)
|
||||||
return registry.value_array[idx];
|
return registry.value_array[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
const GraphNodeSpecificationRegistry *
|
void
|
||||||
get_graph_node_specification_registy()
|
|
||||||
{
|
|
||||||
ensure_initialized();
|
|
||||||
return ®istry;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((destructor)) void
|
|
||||||
destroy_graph_node_specification_registry()
|
destroy_graph_node_specification_registry()
|
||||||
{
|
{
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
|
|
|
@ -2,13 +2,9 @@
|
||||||
#define MODULE_REGISTRY_H_
|
#define MODULE_REGISTRY_H_
|
||||||
|
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "hash_table.h"
|
|
||||||
|
|
||||||
typedef TYPED_HASH_TABLE(GraphNodeSpecification*) GraphNodeSpecificationRegistry;
|
|
||||||
|
|
||||||
void register_graph_node_specification(GraphNodeSpecification * spec);
|
void register_graph_node_specification(GraphNodeSpecification * spec);
|
||||||
GraphNodeSpecification * lookup_graph_node_specification(const char * name);
|
GraphNodeSpecification * lookup_graph_node_specification(const char * name);
|
||||||
void destroy_graph_node_specification_registry();
|
void destroy_graph_node_specification_registry();
|
||||||
const GraphNodeSpecificationRegistry * get_graph_node_specification_registy();
|
|
||||||
|
|
||||||
#endif /* end of include guard: MODULE_REGISTRY_H_ */
|
#endif /* end of include guard: MODULE_REGISTRY_H_ */
|
||||||
|
|
|
@ -47,7 +47,7 @@ handle_io(EventPositionBase * self, int fd, bool is_output)
|
||||||
monotime = absolute_time_sub_relative(realtime, realtime_adj);
|
monotime = absolute_time_sub_relative(realtime, realtime_adj);
|
||||||
EventData data = {
|
EventData data = {
|
||||||
.code = {
|
.code = {
|
||||||
.ns = node->namespace,
|
.ns = 1,
|
||||||
.major = buf.type,
|
.major = buf.type,
|
||||||
.minor = buf.code,
|
.minor = buf.code,
|
||||||
},
|
},
|
||||||
|
@ -139,10 +139,6 @@ GraphNodeSpecification nodespec_evdev = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = ®ister_io,
|
.register_io = ®ister_io,
|
||||||
.name = "evdev",
|
.name = "evdev",
|
||||||
.documentation = "Reads evdev events of the specified device\nDoes not accept events\nSends events on all connectors with major code, minor code, payload respectively set to evdev event type, code, value"
|
|
||||||
"\nOption 'namespace' (optional): set namespace for the generated events"
|
|
||||||
"\nOption 'file' (required): device file to read events from (like '/dev/input/eventN'), the process must have sufficient privileges to read the file"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
|
@ -29,7 +29,7 @@ handle_io(EventPositionBase * self, int fd, bool is_output)
|
||||||
},
|
},
|
||||||
.ttl = 100,
|
.ttl = 100,
|
||||||
.priority = 10,
|
.priority = 10,
|
||||||
.payload = (unsigned char) buf[0],
|
.payload = buf[0],
|
||||||
.modifiers = EMPTY_MODIFIER_SET,
|
.modifiers = EMPTY_MODIFIER_SET,
|
||||||
.time = get_current_time(),
|
.time = get_current_time(),
|
||||||
};
|
};
|
||||||
|
@ -95,9 +95,6 @@ GraphNodeSpecification nodespec_getchar = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = ®ister_io,
|
.register_io = ®ister_io,
|
||||||
.name = "getchar",
|
.name = "getchar",
|
||||||
.documentation = "Converts stdin bytes to events\nDoes not accept events\nSends events on all connectors with major and minor codes (0, 1) and the read byte as payload"
|
|
||||||
"\nOption 'namespace' (optional): set namespace for the generated events"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
|
@ -91,10 +91,6 @@ GraphNodeSpecification nodespec_modifiers = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = NULL,
|
.register_io = NULL,
|
||||||
.name = "modifiers",
|
.name = "modifiers",
|
||||||
.documentation = "Sets/unsets/toggles modifiers in an event\nAccepts events on any connector\nSends events on all connectors"
|
|
||||||
"\nOption 'operation' (required): the operation to apply to the event modifier set ('set'/'unset'/'toggle')"
|
|
||||||
"\nOption 'modifiers' (required): collection of integers --- the set of modifiers to operate on"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
|
@ -94,13 +94,6 @@ GraphNodeSpecification nodespec_modify_predicate = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = NULL,
|
.register_io = NULL,
|
||||||
.name = "modify_predicate",
|
.name = "modify_predicate",
|
||||||
.documentation = "Changes 'enabled' and 'inverted' flags of a predicate\nAccepts events on any connector\nDoes not send events"
|
|
||||||
"\nOption 'target' (required): the predicate to modify"
|
|
||||||
"\nOption 'enable_on' (optional): the predicate, satisfying events of which set 'enabled' flag of the target predicate to 1"
|
|
||||||
"\nOption 'disable_on' (optional): the predicate, satisfying events of which set 'enabled' flag of the target predicate to 0"
|
|
||||||
"\nOption 'invert_on' (optional): the predicate, satisfying events of which set 'inverted' flag of the target predicate to 1"
|
|
||||||
"\nOption 'uninvert_on' (optional): the predicate, satisfying events of which set 'inverted' flag of the target predicate to 0"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
|
@ -60,8 +60,6 @@ GraphNodeSpecification nodespec_print = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = NULL,
|
.register_io = NULL,
|
||||||
.name = "print",
|
.name = "print",
|
||||||
.documentation = "Prints received events\nAccepts events on any connector\nDoes not send events"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
|
@ -88,9 +88,6 @@ GraphNodeSpecification nodespec_router = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = NULL,
|
.register_io = NULL,
|
||||||
.name = "router",
|
.name = "router",
|
||||||
.documentation = "Conditionally copies the received events\nAccepts events on any connector\nSends events on all connectors with configured predicates"
|
|
||||||
"\nOption 'predicates' (required): collection of predicates in the order of output connectors from zero, a received event is copied to the given connector iff it satisfies the predicate"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
|
@ -53,8 +53,6 @@ GraphNodeSpecification nodespec_tee = (GraphNodeSpecification) {
|
||||||
.destroy = &destroy,
|
.destroy = &destroy,
|
||||||
.register_io = NULL,
|
.register_io = NULL,
|
||||||
.name = "tee",
|
.name = "tee",
|
||||||
.documentation = "Copies the received events\nAccepts events on any connector\nSends events on all connectors"
|
|
||||||
,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_CONSTRUCTOR(init)
|
MODULE_CONSTRUCTOR(init)
|
||||||
|
|
Loading…
Reference in New Issue