From e08b473d0eeb467ad358ba5314157753b4f37c18 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 5 Jan 2020 23:26:04 +0100 Subject: Implement commandline config override (Fixes #26) --- midimonster.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 2ec165b..583601e 100644 --- a/midimonster.c +++ b/midimonster.c @@ -274,9 +274,30 @@ static int args_parse(int argc, char** argv, char** cfg_file){ version(); return 1; } - - //if nothing else matches, it's probably the configuration file - *cfg_file = argv[u]; + else if(!strcmp(argv[u], "-i")){ + if(!argv[u + 1]){ + fprintf(stderr, "Missing instance override specification\n"); + return 1; + } + if(config_add_override(override_instance, argv[u + 1])){ + return 1; + } + u++; + } + else if(!strcmp(argv[u], "-b")){ + if(!argv[u + 1]){ + fprintf(stderr, "Missing backend override specification\n"); + return 1; + } + if(config_add_override(override_backend, argv[u + 1])){ + return 1; + } + u++; + } + else{ + //if nothing else matches, it's probably the configuration file + *cfg_file = argv[u]; + } } return 0; @@ -317,6 +338,7 @@ int main(int argc, char** argv){ map_free(); fds_free(); plugins_close(); + config_free(); return usage(argv[0]); } @@ -403,6 +425,7 @@ bail: fds_free(); event_free(); plugins_close(); + config_free(); return rv; } -- cgit v1.2.3 From 78b21a9ac3f975f35ec7b61108531e1495eb91c0 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 12 Jan 2020 17:34:14 +0100 Subject: Rework instance creation --- midimonster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 583601e..b6f7758 100644 --- a/midimonster.c +++ b/midimonster.c @@ -341,7 +341,7 @@ int main(int argc, char** argv){ config_free(); return usage(argv[0]); } - + //load an initial timestamp update_timestamp(); -- cgit v1.2.3 From 8c32598449895e506b4d0eab71be0abf219a62da Mon Sep 17 00:00:00 2001 From: cbdev Date: Mon, 13 Jan 2020 22:49:33 +0100 Subject: Hide core-internal structures --- midimonster.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index b6f7758..d9a99d9 100644 --- a/midimonster.c +++ b/midimonster.c @@ -14,6 +14,7 @@ #include "backend.h" #include "plugin.h" +/* Core-internal structures */ typedef struct /*_event_collection*/ { size_t alloc; size_t n; @@ -21,6 +22,12 @@ typedef struct /*_event_collection*/ { channel_value* value; } event_collection; +typedef struct /*_mm_channel_mapping*/ { + channel* from; + size_t destinations; + channel** to; +} channel_mapping; + static size_t mappings = 0; static channel_mapping* map = NULL; static size_t fds = 0; -- cgit v1.2.3 From 9c564af18dc3faad8910bfe14b45ed4ab884d797 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 29 Feb 2020 15:35:08 +0100 Subject: Keep console alive when exiting as last process on Windows --- midimonster.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index d9a99d9..9cbc3a9 100644 --- a/midimonster.c +++ b/midimonster.c @@ -264,13 +264,27 @@ static fd_set fds_collect(int* max_fd){ } static int platform_initialize(){ -#ifdef _WIN32 + #ifdef _WIN32 WSADATA wsa; WORD version = MAKEWORD(2, 2); if(WSAStartup(version, &wsa)){ return 1; } -#endif + #endif + return 0; +} + +static int platform_shutdown(){ + #ifdef _WIN32 + DWORD processes; + if(GetConsoleProcessList(&processes, 1) == 1){ + fprintf(stderr, "\nMIDIMonster is the last process in this console, please press any key to exit\n"); + HANDLE input = GetStdHandle(STD_INPUT_HANDLE); + SetConsoleMode(input, 0); + FlushConsoleInputBuffer(input); + WaitForSingleObject(input, INFINITE); + } + #endif return 0; } @@ -346,7 +360,7 @@ int main(int argc, char** argv){ fds_free(); plugins_close(); config_free(); - return usage(argv[0]); + return (usage(argv[0]) | platform_shutdown()); } //load an initial timestamp @@ -433,6 +447,7 @@ bail: event_free(); plugins_close(); config_free(); + platform_shutdown(); return rv; } -- cgit v1.2.3 From 20e8f4632b8e11415435d143ec3c7c4528c54d46 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 8 Mar 2020 13:25:00 +0100 Subject: Allow managed_fd implementation data to be updated --- midimonster.c | 1 + 1 file changed, 1 insertion(+) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 9cbc3a9..2087c28 100644 --- a/midimonster.c +++ b/midimonster.c @@ -127,6 +127,7 @@ MM_API int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ //find exact match for(u = 0; u < fds; u++){ if(fd[u].fd == new_fd && fd[u].backend == b){ + fd[u].impl = impl; if(!manage){ fd[u].fd = -1; fd[u].backend = NULL; -- cgit v1.2.3 From aa5650c77af9379fc80c5329e0c0ffbe1f5d2355 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 8 Mar 2020 13:44:34 +0100 Subject: Print proper error messages from core select on Windows --- midimonster.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 2087c28..b8594b4 100644 --- a/midimonster.c +++ b/midimonster.c @@ -333,6 +333,9 @@ int main(int argc, char** argv){ managed_fd* signaled_fds = NULL; int rv = EXIT_FAILURE, error, maxfd = -1; char* cfg_file = DEFAULT_CFG; + #ifdef _WIN32 + char* error_message = NULL; + #endif //parse commandline arguments if(args_parse(argc, argv, &cfg_file)){ @@ -392,7 +395,15 @@ int main(int argc, char** argv){ tv = backend_timeout(); error = select(maxfd + 1, &read_fds, NULL, NULL, &tv); if(error < 0){ + #ifndef _WIN32 fprintf(stderr, "select failed: %s\n", strerror(errno)); + #else + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error_message, 0, NULL); + fprintf(stderr, "select failed: %s\n", error_message); + LocalFree(error_message); + error_message = NULL; + #endif break; } -- cgit v1.2.3 From d757a9c63371fcf5f9aa832d58ed4b8bdf634909 Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 10 Mar 2020 20:42:55 +0100 Subject: Restructure core loop, add check for zero-descriptor case --- midimonster.c | 197 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 76 deletions(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index b8594b4..3212f7f 100644 --- a/midimonster.c +++ b/midimonster.c @@ -9,6 +9,7 @@ #else #define MM_API __attribute__((dllexport)) #endif +#define BACKEND_NAME "core" #include "midimonster.h" #include "config.h" #include "backend.h" @@ -325,18 +326,126 @@ static int args_parse(int argc, char** argv, char** cfg_file){ return 0; } -int main(int argc, char** argv){ - fd_set all_fds, read_fds; +static int core_process(size_t nfds, managed_fd* signaled_fds){ event_collection* secondary = NULL; - struct timeval tv; - size_t u, n; + size_t u; + + //run backend processing, collect events + DBGPF("%lu backend FDs signaled\n", nfds); + if(backends_handle(nfds, signaled_fds)){ + return 1; + } + + while(primary->n){ + //swap primary and secondary event collectors + DBGPF("Swapping event collectors, %lu events in primary\n", primary->n); + for(u = 0; u < sizeof(event_pool) / sizeof(event_collection); u++){ + if(primary != event_pool + u){ + secondary = primary; + primary = event_pool + u; + break; + } + } + + //push collected events to target backends + if(secondary->n && backends_notify(secondary->n, secondary->channel, secondary->value)){ + fprintf(stderr, "Backends failed to handle output\n"); + return 1; + } + + //reset the event count + secondary->n = 0; + } + + return 0; +} + +static int core_loop(){ + fd_set all_fds, read_fds; managed_fd* signaled_fds = NULL; - int rv = EXIT_FAILURE, error, maxfd = -1; - char* cfg_file = DEFAULT_CFG; + struct timeval tv; + int error, maxfd = -1; + size_t n, u; #ifdef _WIN32 char* error_message = NULL; + #else + struct timespec ts; #endif + FD_ZERO(&all_fds); + + //process events + while(!shutdown_requested){ + //rebuild fd set if necessary + if(fd_set_dirty){ + all_fds = fds_collect(&maxfd); + signaled_fds = realloc(signaled_fds, fds * sizeof(managed_fd)); + if(!signaled_fds){ + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + fd_set_dirty = 0; + } + + //wait for & translate events + read_fds = all_fds; + tv = backend_timeout(); + + //check whether there are any fds active, windows does not like select() without descriptors + if(maxfd >= 0){ + error = select(maxfd + 1, &read_fds, NULL, NULL, &tv); + if(error < 0){ + #ifndef _WIN32 + fprintf(stderr, "select failed: %s\n", strerror(errno)); + #else + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error_message, 0, NULL); + fprintf(stderr, "select failed: %s\n", error_message); + LocalFree(error_message); + error_message = NULL; + #endif + free(signaled_fds); + return 1; + } + } + else{ + DBGPF("No descriptors, sleeping for %zu msec", tv.tv_sec * 1000 + tv.tv_usec / 1000); + #ifdef _WIN32 + Sleep(tv.tv_sec * 1000 + tv.tv_usec / 1000); + #else + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + error = nanosleep(&ts, NULL); + #endif + } + + //update this iteration's timestamp + update_timestamp(); + + //find all signaled fds + n = 0; + for(u = 0; u < fds; u++){ + if(fd[u].fd >= 0 && FD_ISSET(fd[u].fd, &read_fds)){ + signaled_fds[n] = fd[u]; + n++; + } + } + + //fetch and process events + if(core_process(n, signaled_fds)){ + free(signaled_fds); + return 1; + } + } + + free(signaled_fds); + return 0; +} + +int main(int argc, char** argv){ + int rv = EXIT_FAILURE; + char* cfg_file = DEFAULT_CFG; + //parse commandline arguments if(args_parse(argc, argv, &cfg_file)){ return EXIT_FAILURE; @@ -347,7 +456,6 @@ int main(int argc, char** argv){ return EXIT_FAILURE; } - FD_ZERO(&all_fds); //initialize backends if(plugins_load(PLUGINS)){ fprintf(stderr, "Failed to initialize a backend\n"); @@ -377,80 +485,17 @@ int main(int argc, char** argv){ signal(SIGINT, signal_handler); - //process events - while(!shutdown_requested){ - //rebuild fd set if necessary - if(fd_set_dirty){ - all_fds = fds_collect(&maxfd); - signaled_fds = realloc(signaled_fds, fds * sizeof(managed_fd)); - if(!signaled_fds){ - fprintf(stderr, "Failed to allocate memory\n"); - goto bail; - } - fd_set_dirty = 0; - } - - //wait for & translate events - read_fds = all_fds; - tv = backend_timeout(); - error = select(maxfd + 1, &read_fds, NULL, NULL, &tv); - if(error < 0){ - #ifndef _WIN32 - fprintf(stderr, "select failed: %s\n", strerror(errno)); - #else - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error_message, 0, NULL); - fprintf(stderr, "select failed: %s\n", error_message); - LocalFree(error_message); - error_message = NULL; - #endif - break; - } - - //find all signaled fds - n = 0; - for(u = 0; u < fds; u++){ - if(fd[u].fd >= 0 && FD_ISSET(fd[u].fd, &read_fds)){ - signaled_fds[n] = fd[u]; - n++; - } - } - - //update this iteration's timestamp - update_timestamp(); - - //run backend processing, collect events - DBGPF("%lu backend FDs signaled\n", n); - if(backends_handle(n, signaled_fds)){ - goto bail; - } - - while(primary->n){ - //swap primary and secondary event collectors - DBGPF("Swapping event collectors, %lu events in primary\n", primary->n); - for(u = 0; u < sizeof(event_pool) / sizeof(event_collection); u++){ - if(primary != event_pool + u){ - secondary = primary; - primary = event_pool + u; - break; - } - } - - //push collected events to target backends - if(secondary->n && backends_notify(secondary->n, secondary->channel, secondary->value)){ - fprintf(stderr, "Backends failed to handle output\n"); - goto bail; - } + if(!fds){ + fprintf(stderr, "No descriptors registered for multiplexing\n"); + } - //reset the event count - secondary->n = 0; - } + //run the core loop + if(!core_loop()){ + rv = EXIT_SUCCESS; } - rv = EXIT_SUCCESS; bail: //free all data - free(signaled_fds); backends_stop(); channels_free(); instances_free(); -- cgit v1.2.3 From c15ac89a33b6f6f51ac0c3da7a86dc43c8a9321a Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 10 Mar 2020 22:31:17 +0100 Subject: Fix Coverity CID 354930 & CID 354929 --- midimonster.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 3212f7f..2b0b7a0 100644 --- a/midimonster.c +++ b/midimonster.c @@ -377,7 +377,7 @@ static int core_loop(){ //process events while(!shutdown_requested){ //rebuild fd set if necessary - if(fd_set_dirty){ + if(fd_set_dirty || !signaled_fds){ all_fds = fds_collect(&maxfd); signaled_fds = realloc(signaled_fds, fds * sizeof(managed_fd)); if(!signaled_fds){ @@ -415,7 +415,7 @@ static int core_loop(){ #else ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000; - error = nanosleep(&ts, NULL); + nanosleep(&ts, NULL); #endif } -- cgit v1.2.3 From 6da00154f7745a4705047fc73ce42b7036b0bbdc Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 15 Mar 2020 12:19:50 +0100 Subject: Fix build and CI exits --- midimonster.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 2b0b7a0..8e217e7 100644 --- a/midimonster.c +++ b/midimonster.c @@ -466,8 +466,6 @@ int main(int argc, char** argv){ if(config_read(cfg_file)){ fprintf(stderr, "Failed to read configuration file %s\n", cfg_file); backends_stop(); - channels_free(); - instances_free(); map_free(); fds_free(); plugins_close(); @@ -497,8 +495,6 @@ int main(int argc, char** argv){ bail: //free all data backends_stop(); - channels_free(); - instances_free(); map_free(); fds_free(); event_free(); -- cgit v1.2.3 From 846a49199ba011a00e4814bacac524a6fe9b299a Mon Sep 17 00:00:00 2001 From: cbdev Date: Mon, 16 Mar 2020 22:19:27 +0100 Subject: Hash-index event routing table --- midimonster.c | 142 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 76 insertions(+), 66 deletions(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 8e217e7..afb6a2b 100644 --- a/midimonster.c +++ b/midimonster.c @@ -29,25 +29,34 @@ typedef struct /*_mm_channel_mapping*/ { channel** to; } channel_mapping; -static size_t mappings = 0; -static channel_mapping* map = NULL; +static struct { + //routing_hash is set up for 256 buckets + size_t entries[256]; + channel_mapping* map[256]; + + event_collection pool[2]; + event_collection* events; +} routing = { + .events = routing.pool +}; + static size_t fds = 0; static managed_fd* fd = NULL; static volatile sig_atomic_t fd_set_dirty = 1; static uint64_t global_timestamp = 0; -static event_collection event_pool[2] = { - {0}, - {0} -}; -static event_collection* primary = event_pool; - volatile static sig_atomic_t shutdown_requested = 0; static void signal_handler(int signum){ shutdown_requested = 1; } +static size_t routing_hash(channel* key){ + uint64_t repr = (uint64_t) key; + //return 8bit hash for 256 buckets, not ideal but it works + return (repr ^ (repr >> 8) ^ (repr >> 16) ^ (repr >> 24) ^ (repr >> 32)) & 0xFF; +} + MM_API uint64_t mm_timestamp(){ return global_timestamp; } @@ -67,53 +76,66 @@ static void update_timestamp(){ } int mm_map_channel(channel* from, channel* to){ - size_t u, m; + size_t u, m, bucket = routing_hash(from); + //find existing source mapping - for(u = 0; u < mappings; u++){ - if(map[u].from == from){ + for(u = 0; u < routing.entries[bucket]; u++){ + if(routing.map[bucket][u].from == from){ break; } } //create new entry - if(u == mappings){ - map = realloc(map, (mappings + 1) * sizeof(channel_mapping)); - if(!map){ + if(u == routing.entries[bucket]){ + routing.map[bucket] = realloc(routing.map[bucket], (routing.entries[bucket] + 1) * sizeof(channel_mapping)); + if(!routing.map[bucket]){ + routing.entries[bucket] = 0; fprintf(stderr, "Failed to allocate memory\n"); return 1; } - memset(map + mappings, 0, sizeof(channel_mapping)); - mappings++; - map[u].from = from; + + memset(routing.map[bucket] + routing.entries[bucket], 0, sizeof(channel_mapping)); + routing.entries[bucket]++; + routing.map[bucket][u].from = from; } //check whether the target is already mapped - for(m = 0; m < map[u].destinations; m++){ - if(map[u].to[m] == to){ + for(m = 0; m < routing.map[bucket][u].destinations; m++){ + if(routing.map[bucket][u].to[m] == to){ return 0; } } - map[u].to = realloc(map[u].to, (map[u].destinations + 1) * sizeof(channel*)); - if(!map[u].to){ + //add a mapping target + routing.map[bucket][u].to = realloc(routing.map[bucket][u].to, (routing.map[bucket][u].destinations + 1) * sizeof(channel*)); + if(!routing.map[bucket][u].to){ fprintf(stderr, "Failed to allocate memory\n"); - map[u].destinations = 0; + routing.map[bucket][u].destinations = 0; return 1; } - map[u].to[map[u].destinations] = to; - map[u].destinations++; + routing.map[bucket][u].to[routing.map[bucket][u].destinations] = to; + routing.map[bucket][u].destinations++; return 0; } -static void map_free(){ - size_t u; - for(u = 0; u < mappings; u++){ - free(map[u].to); +static void routing_cleanup(){ + size_t u, n; + + for(u = 0; u < sizeof(routing.map) / sizeof(routing.map[0]); u++){ + for(n = 0; n < routing.entries[u]; n++){ + free(routing.map[u][n].to); + } + free(routing.map[u]); + routing.map[u] = NULL; + routing.entries[u] = 0; + } + + for(u = 0; u < sizeof(routing.pool) / sizeof(routing.pool[0]); u++){ + free(routing.pool[u].channel); + free(routing.pool[u].value); + routing.pool[u].alloc = 0; } - free(map); - mappings = 0; - map = NULL; } MM_API int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ @@ -170,7 +192,6 @@ MM_API int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ static void fds_free(){ size_t u; for(u = 0; u < fds; u++){ - //TODO free impl if(fd[u].fd >= 0){ close(fd[u].fd); fd[u].fd = -1; @@ -182,56 +203,46 @@ static void fds_free(){ } MM_API int mm_channel_event(channel* c, channel_value v){ - size_t u, p; + size_t u, p, bucket = routing_hash(c); //find mapped channels - for(u = 0; u < mappings; u++){ - if(map[u].from == c){ + for(u = 0; u < routing.entries[bucket]; u++){ + if(routing.map[bucket][u].from == c){ break; } } - if(u == mappings){ + if(u == routing.entries[bucket]){ //target-only channel return 0; } //resize event structures to fit additional events - if(primary->n + map[u].destinations >= primary->alloc){ - primary->channel = realloc(primary->channel, (primary->alloc + map[u].destinations) * sizeof(channel*)); - primary->value = realloc(primary->value, (primary->alloc + map[u].destinations) * sizeof(channel_value)); + if(routing.events->n + routing.map[bucket][u].destinations >= routing.events->alloc){ + routing.events->channel = realloc(routing.events->channel, (routing.events->alloc + routing.map[bucket][u].destinations) * sizeof(channel*)); + routing.events->value = realloc(routing.events->value, (routing.events->alloc + routing.map[bucket][u].destinations) * sizeof(channel_value)); - if(!primary->channel || !primary->value){ + if(!routing.events->channel || !routing.events->value){ fprintf(stderr, "Failed to allocate memory\n"); - primary->alloc = 0; - primary->n = 0; + routing.events->alloc = 0; + routing.events->n = 0; return 1; } - primary->alloc += map[u].destinations; + routing.events->alloc += routing.map[bucket][u].destinations; } //enqueue channel events //FIXME this might lead to one channel being mentioned multiple times in an apply call - for(p = 0; p < map[u].destinations; p++){ - primary->channel[primary->n + p] = map[u].to[p]; - primary->value[primary->n + p] = v; + memcpy(routing.events->channel + routing.events->n, routing.map[bucket][u].to, routing.map[bucket][u].destinations * sizeof(channel*)); + for(p = 0; p < routing.map[bucket][u].destinations; p++){ + routing.events->value[routing.events->n + p] = v; } - primary->n += map[u].destinations; + routing.events->n += routing.map[bucket][u].destinations; return 0; } -static void event_free(){ - size_t u; - - for(u = 0; u < sizeof(event_pool) / sizeof(event_collection); u++){ - free(event_pool[u].channel); - free(event_pool[u].value); - event_pool[u].alloc = 0; - } -} - static void version(){ printf("MIDIMonster %s\n", MIDIMONSTER_VERSION); } @@ -336,13 +347,13 @@ static int core_process(size_t nfds, managed_fd* signaled_fds){ return 1; } - while(primary->n){ + while(routing.events->n){ //swap primary and secondary event collectors - DBGPF("Swapping event collectors, %lu events in primary\n", primary->n); - for(u = 0; u < sizeof(event_pool) / sizeof(event_collection); u++){ - if(primary != event_pool + u){ - secondary = primary; - primary = event_pool + u; + DBGPF("Swapping event collectors, %lu events in primary\n", routing.events->n); + for(u = 0; u < sizeof(routing.pool) / sizeof(routing.pool[0]); u++){ + if(routing.events != routing.pool + u){ + secondary = routing.events; + routing.events = routing.pool + u; break; } } @@ -466,7 +477,7 @@ int main(int argc, char** argv){ if(config_read(cfg_file)){ fprintf(stderr, "Failed to read configuration file %s\n", cfg_file); backends_stop(); - map_free(); + routing_cleanup(); fds_free(); plugins_close(); config_free(); @@ -495,9 +506,8 @@ int main(int argc, char** argv){ bail: //free all data backends_stop(); - map_free(); + routing_cleanup(); fds_free(); - event_free(); plugins_close(); config_free(); platform_shutdown(); -- cgit v1.2.3 From 636a9592eab1963c2b1a77bd59eaff317fa55b75 Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 17 Mar 2020 01:09:52 +0100 Subject: Fix registry apply bug, fix openpixelcontrol broadcast --- midimonster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index afb6a2b..1691671 100644 --- a/midimonster.c +++ b/midimonster.c @@ -409,7 +409,7 @@ static int core_loop(){ #ifndef _WIN32 fprintf(stderr, "select failed: %s\n", strerror(errno)); #else - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error_message, 0, NULL); fprintf(stderr, "select failed: %s\n", error_message); LocalFree(error_message); -- cgit v1.2.3 From daf9ac5b883cf981a163654d58932bfbdce619d9 Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 17 Mar 2020 23:58:06 +0100 Subject: Output routing info to log --- midimonster.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'midimonster.c') diff --git a/midimonster.c b/midimonster.c index 1691671..5109eab 100644 --- a/midimonster.c +++ b/midimonster.c @@ -456,6 +456,7 @@ static int core_loop(){ int main(int argc, char** argv){ int rv = EXIT_FAILURE; char* cfg_file = DEFAULT_CFG; + size_t u, n = 0, max = 0; //parse commandline arguments if(args_parse(argc, argv, &cfg_file)){ @@ -494,6 +495,14 @@ int main(int argc, char** argv){ signal(SIGINT, signal_handler); + //count and report mappings + for(u = 0; u < sizeof(routing.map) / sizeof(routing.map[0]); u++){ + n += routing.entries[u]; + max = max(max, routing.entries[u]); + } + LOGPF("Routing %" PRIsize_t " sources, largest bucket has %" PRIsize_t " entries", + n, max); + if(!fds){ fprintf(stderr, "No descriptors registered for multiplexing\n"); } -- cgit v1.2.3